145
Ezi As... ALFLB Library Functions The programming ALFLB Function Library has been growing and maturing for decades. ALFLB is a box full of solid and mature pieces of C & C++ code. Many of these routines have been used in multiple projects across multiple platforms & they are as tough and as stable as I can make them. The idea of ALFLB was to create a whole toolbox of different tools that could be taken from project to project without having to reinvent the wheel. This document is copyright © 2002-2012 Alf Lacis. This document is released, see Appendix 1, under the terms of the GNU General Public License Version 2, June 1991. The functions which I have written have been released under the terms of the GNU Lesser General Public License Version 2.1, February 1999. Document : alflb_20120306.odt This document is primarily published at http://www.alfredo4570.net/src

ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

Ezi As...

ALFLB Library Functions

The programming ALFLB Function Library has been growing and maturing for decades. ALFLB is a box full of solid and mature pieces of C & C++ code. Many of these routines have been used in multiple projects across multiple platforms & they are as tough and as stable as I can make them. The idea of ALFLB was to create a whole toolbox of different tools that could be taken from project to project without

having to reinvent the wheel.

This document is copyright © 2002-2012 Alf Lacis.This document is released, see Appendix 1, under the terms of the GNU General Public License Version 2, June 1991.

The functions which I have written have been released under the terms of the GNU Lesser General Public License Version 2.1, February 1999.

Document : alflb_20120306.odtThis document is primarily published at http://www.alfredo4570.net/src

Page 2: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

Revision List

Issue Date Nature of Amendment

20120306 Changed URI for this document and the library. Added the large character library data & functions, lg*(). Added ezi_fill().

20100727 Added ezi_trunc().

20100317 Added description for the alflog logging library reader application.

20100303 Rewrote ezi_sproc() from scratch; removed snonp(), sproc(), sproc_trail(); added ezi_printable() and ezi_squash(). Updated the alflog logging library documentation. Fixed some typos.

20100214 Removed restriction in fd_set_and(): output can now be one of the inputs; improved example.

20200207 Added fd_set_ops library. Added ezi_opt_set_bit(), ezi_opt_set_byte(), ezi_opt_byte().

20090806 Added footnote regarding Cygwin and IPC functionality to "Interprocess Communication, Debugging & Monitoring - the ezi_opt suite".

20090804 Described ezi_since_when. Described longer set string for opt & updated u option.

20090801 Described new opt option u (last updated seconds or 'seconds since last run').

20090728 Added seconds to opt_alive. int returns for ezi_snprintf & ezi_vsnprintf. Fonts again.

20090718 Added ezi_cpy_cat, ezi_cpy_cat_raw, ezi_vsnprintf. Fonts.

20090709 For the ezi_opt suite, added ezi_opt_st, documented last pid & pid counter.

20090702 Documented name parameter in opt.

20090627 Added description for ezi_opt_snprintf, added save/restore description for opt. Added descriptions for new w_r_buf.c functions.

20090620 Slimmed down the ezi_opt interface to make it more streamlined.

20090614 Documented the ezi_opt suite.

20090608 Added test example in w_r_buf.c for writebuf & readbuf.

20081101 Due to INIT clashing with another library, replaced INIT, ALLOCATE & EXTERN with EZI_INIT, EZI_ALLOCATE & EZI_EXTERN; removed ACCESS. Updated folder & hand logo.

20081005 Fixed typos.

20080929 Added C++ version of eziqueue library.

20080906 Replaced Boyer-Moore algorithm with new, thread-safe version.

20080904 Documented new subdirectory layout. Changed indexed_list.c to ezi_index.c. Added C++ ezi_index and ezi_min family templates, and ezi_index_cpp.cpp. Removed ini files.

20080517 Documented Ezi versions of the ASCII-Hex/Binary functions.

20080510 Added Ezi Queue test app output as example 2.

20080505 Some more tidy-ups. Changed record pointer for Ezi Queue suite from UCHAR* to void*.

20080425 Some tidy ups resulting from merge of alflb.h with a re-examination of each suite's test apps.

20080422 Merged the contents of alflb.h, ezitypes.h & alf_defines.h into alflb.h.Revisited several of the test apps to ensure correct operation.

20080408 Added IS_FULL, IS_EMPTY, IS_FULL_MACRO, IS_EMPTY_MACRO.

20071225 Added the definition and instantiation macros ALLOCATE, ACCESS, EXTERN & INIT. Added the casting and setting macros CAST_PTR and CAST_SET. Added CAPACITY_OF.

20071214 Updated example for memfill.

20071201 Added the Error Check and Return Macros suite. Added ezi_cpy_raw and ezi_cat_raw; deprecated ezi_set.

20071128 Added d_string_special, updated test app.

20071123 Fixed some typos.

20071116 Added a get/delete loop in the flowchart for Ezi Queues. Added a description on the front page.

20071104 Reduced number of d_string_safe formats down to just octal and hex; added ', " and \ to examples in the test application; removed ConvertEscapeSequences.

20071101 Added hex36range. Fixed some header #includes.

20071027 Documented memxor. Added example for simple_itoa.c.

20071010 Added NEXT_N and PREV_N to the Indexed List suite. Improved doco.

20071008 Removed d_string: was already deprecated.

20070928 For long long integers, added SLL, ULL & ULLSZ. Added ability to change the Index Macros (NEXT, PREV, etc) into functions.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 2 of 145

Page 3: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

Issue Date Nature of Amendment

20070925 Changed public interface for timer_msec_ended from function to macro so that a cast can be built-in, removing the need for a separate xxx_cast macro; renamed function timer_msec_ended to timer_msec_ended_private; removed timer_msec_ended_ushort & timer_msec_ended_cast.

20070923 Wrote a new endian suite, with a different interface.

20070907 In Compile-Time Asserts, added a description_as_variable_name to generate the variable name containing the assert-error in English.

20070904 Added timer_msec_xxx suite of millisecond timers.

20070903 Added COMPILE_TIME_ASSERT, FILE_SCOPED_COMPILE_TIME_ASSERT. Fixed some typos.

20070823 Added description for loopfunc.

20070812 Changed prototype for nooploop from a size_t parameter to ULONG. Added section on Ezi-Types. Fixed doco for ezi_dbg & d_stringxxx functions; changed prototypes for ezi_xxx functions to use EZISTR_T* for the function prototypes.

20070806 Added doco for PREV, NEXT, DISTANCE, PREV_GP, NEXT_GP, JOG.

20070724 Added Ezi Queue functions: eziq_init, eziq_check, eziq_empty, eziq_full, eziq_num, eziq_add, eziq_get, eziq_delete, eziq_scan.

20070710 Removed Revs (now just relying on date). Added lots of stuff, including ezi queue and ezi string functions.

20070615 Added camel style entry points for const zero variables (nameCamel).

20070227 Added MEMMOVESZ(to,fm) and MEMCCPYSZ(to,fm,c).

20070118 Added null.

20070105 Added memfill.

20061230 Added swedish_build.

20061219 Added ezi_ltrim & ezi_rtrim.

20061203 Added mem_backup and mem_restore.

20061203 Added bytewisecrc16 & bytewisecrc32 prototypes.

20061201 Added ezi_calloc, ezi_salloc & ezi_realloc prototypes.

20061110 Added ezi_sproc, ezi_dbg, ezi_esc, ConvertEscapeSequencesSafe & d_string_safe.

20060809 Added noop & nooploop.

20060711 Changed prototype for strnicmp to use size_t for length. Added c2str.

20051019 Removed thread-dangerous variables sproc_cm & sproc_len. Changed return type of sproc from char* to size_t.

20050830 Removed thread-dangerous variable strncpyprintnlen. Removed macro STRNCPYN. Changed strncpyprintn's & strncpyn's variable name max to last_index (but I do not regard this as a code change) as a mnemonic to remembering the functioning of this variable.

20050518 Replaced int first, int last in sproc with size_t first, size_t last.

20050516 Converted dates in this document to Swedish format (yyyy-mm-dd). Added memall.

20041022 Added BM_DECLARE, BM_ANY.

20040407 Removed VoxsonPassword & erroneous Voxson copyright. Reformatted slightly.

20031110 Added strcatlen and strncatlen.

20031103 Copied description of uniquify from uniquify.h.

20031014 Fixed some formatting

20031013 Added section on Logging Events.

20031013 Replaced C comments in bit-map example with C++ comments. Added CompressedDateTimeStr. Added strcasestr. Added mkdirhier. Added StrippedSize. Added NULLIFY.

20030620 Added Comma/Tab-Separated-Variables (CSV/TSV) library csv_kppp.

20030317 Added stricmp, strnicmp, strcmpi, strncmpi, STRIEQUAL, STRNIEQUAL to String Equality Checks - Various.

20030303 Added TS_InfoQual. Added instructions for cygwin library build.

20030228 Added descriptions for fProgCalc, ProgCalc. Added DOLOOP. Added MAX, MIN, etc. Added Range Checking and Normalisation. Added String Equality Checks.

20021210 Added many more index entries. Fixed comments in bitmap example.

20021209 Updated document with VXD name and checked in to PVCS.

20021128 Added d_string_vary and d_string_do_mults_set.

20021113 Added ConvertEscapeSequences.

20021016 Added description of return values from TS_Info.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 3 of 145

Page 4: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

Issue Date Nature of Amendment

20021014 Added note and example for D_STRING_HEXV to Debug String Routines.

20021008 Added "Adding Routines to the Library", "Examples of Useful Target-Specific Constructions".

20021007 Added void macro version of strncpyn, STRNCPYN.

20021001 Added FileHasChanged.

20020925 Added VoxsonPassword. Converted from HTML to Word.

20020910 Replace pseudo example for Bit-Map functions with real example.

20020909 Added notes about BM_FUNCS_AS_FUNCTIONS.

20020905 Added description for endian. Added TS_Info, TagStringMakePrefix, TagStringFind. Added ShorterName, GetPixelSizes.

20020815 Following revisions to index.html.

20020815 Initial .html version.

unknown Original .txt document by Alf Lacis.

Document Information

This document is written in OpenOffice.org format, refer www.openoffice.org, and exported for use as a .pdf - the document was formatted from alflb_20120306.odt. A .html version, then a .doc version of this document were updated at Voxson. This document was mistakenly marked copyright Voxson Limited when the contents were added to one of Voxson's document templates.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 4 of 145

Page 5: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

Table of Contents1 Introduction............................................................................................................................................72 Ezi-Types.............................................................................................................................................103 Ezi-String Function Suite.....................................................................................................................114 Allocate and Access Variables.............................................................................................................195 ASCII-Hex to Raw Binary Data & v/v..................................................................................................206 Bit-Array (Bit-Map) Suite.....................................................................................................................227 Bit-Masks (Visual) - 4-, 8- & 16-bit Versions.......................................................................................258 Capacity of - Number of Entries in an Array........................................................................................269 Character to String Converter.............................................................................................................2710 Comma/Tab Separated Variable (csv/tsv) Files - Reading...............................................................2811 Compile-Time Asserts........................................................................................................................3212 C-String and Debug-String Functions...............................................................................................3413 Cyclic Redundancy Check Functions................................................................................................3914 File Date - datethis............................................................................................................................4115 Date/Time String Routines - Sortable Format...................................................................................4216 Directory Path Make - mkdirhier........................................................................................................4317 Display a numeric string with commas - i_commas..........................................................................4418 Do Loop Statement - DOLOOP.........................................................................................................4519 Error Check and Return Macros.......................................................................................................4620 Ezi Endian Byte Transposal..............................................................................................................4921 File Descriptor Set Operations..........................................................................................................5222 File-in-memory Vs File-on-disk - FileHasChanged...........................................................................5423 File Name / Path - Splitting & Merging Routines - fnsplit, fnmerge...................................................5624 File Name or Path Changes - Change_File, Change_Ext................................................................5725 Flash Programmer Boot Code Address Setup - MSBXxxx...............................................................5826 Base-36 Checker - hex36range........................................................................................................5927 Human-Readable Time Period - 'Since When'..................................................................................6028 Indexes - The Ezi Index Suite...........................................................................................................6129 Integers to ASCII Conversion (non-sprintf suite)...............................................................................6830 Interprocess Communication, Debugging & Monitoring - the ezi_opt suite......................................7231 Logging Events (Encrypted) - alflog_write, etc..................................................................................7932 Large Character Functions................................................................................................................8533 MAX/MIN-family Macros, ezi_max-family Templates........................................................................8834 Memory All the Same Value? - memall.............................................................................................9135 Memory Fill with Copies of the 'from' buffer - memfill........................................................................9236 Memory Function Wrappers - MEMSETSZ, etc................................................................................9337 Memory Backup Functions - mem_backup, etc................................................................................9438 Memory Search using the Boyer-Moore Algorithm...........................................................................9639 Memory X-Or - memxor.....................................................................................................................9840 Millisecond Timing: Real Time Clock Functions................................................................................9941 Nibble Array Suite............................................................................................................................10142 No-Operation Functions..................................................................................................................10243 Null Function...................................................................................................................................10344 Percentage Progress Calculator.....................................................................................................10445 Plural Selector.................................................................................................................................10646 Pointer - Casting and Setting..........................................................................................................10747 Pointer - return memory & nullify pointer.........................................................................................10848 Queues - The Ezi Queue Function Suite........................................................................................10949 Range Checking and Normalisation................................................................................................11550 Replace Pattern Character in a String - replace, etc.......................................................................11751 Reverse a String - reversen.............................................................................................................11852 String Equality Checks - Various.....................................................................................................11953 Case-insensitive strstr - strcasestr..................................................................................................12154 Fast String Catenate, Returned Length - strcatlen, etc...................................................................12255 Safe String N-Copy with Trailing Null - strncpyn, etc......................................................................124

alflb_20120306.odt © 2002-2012 Alf Lacis Page 5 of 145

Page 6: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

56 String Processor Suite.....................................................................................................................12557 Strip Trailing Bytes - StrippedSize...................................................................................................12958 'Swedish' Equivalent for __DATE__ & __TIME__...........................................................................13059 Tagged Variable Search - TS_Info, etc............................................................................................13160 Text Size Routines - ShorterName, GetPixelSizes.........................................................................13361 'Uniquify' a Pre-Sorted List - uniquify..............................................................................................13462 Write & Read a Buffer 'Safely' To/From a File.................................................................................13663 Zeros - All Types..............................................................................................................................13864 Appendix 1 - GNU Licences............................................................................................................139

alflb_20120306.odt © 2002-2012 Alf Lacis Page 6 of 145

Page 7: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

1 IntroductionThis documents the various functions available in the ALFLB Function Library. ALFLB is a grab-bag or potpourri of all sorts of useful tools: some are simple, some are more involved and make up functional suites.

ALFLB is something that has been growing and maturing for decades. Many of these routines have been used in multiple projects across multiple platforms & they are as tough and as stable as I can make them.

Some of them are one or two liners, for example, the Indexed List Macros, NEXT and PREV, but behind this code stands rigorous testing and long-term usage, with improvements being made where necessary. For example, even though NEXT was a macro with a long usage history, I had not considered the environment where division was expensive and for smaller embedded targets this represents a considerable cost. Also, using GCC1 on a tiny target (16K Flash, 1K RAM), size-optimisation was better if a wrapper function was used.

The coding style, even down to routine names and some return values, have been influenced by particular projects that I had been working on at the time: for example, d_string.c and convescs.c perform complimentary functions, but were written 15 years apart, and the coding styles vary by the breadth of time, the span of companies and projects and just through experience.

A few years ago, I was motivated to build a suite of routines, plus some wrapper routines for old code, using my Ezi-String types. I do not think it is worthwhile converting or creating a wrapper for every string function to Ezi-Strings, but I now have a simple, tough string library and type which is low-impact, and easily usable by legacy code.

Enjoy... they are there to make the chore of programming into a happier experience with the knowledge that the code is usable, stable and generally simple enough even for new project members to use readily.

1.1 Test ApplicationsMany of these library functions and suites feature test applications. When I saw how a simple and thorough test application could remain part of library, typically through the use of a #ifdef TEST_APP_xxx fence contained within the same source file, I have almost always written at least one test application concomitant with the library code. The test app is almost always a console application. The advantage of concomitant code is that, regardless of the platform, a test app can be run to exercise the code, to demonstrate results, and to gain confidence from the strength of the library, before applying the library to the user's application.

1.2 Getting ALFLB§ Go to http://www.alfredo4570.net/src (since February 2012)

(previously http://alfredo4570.customer.netspace.net.au/src since July 2008,previouslyhttp://au.geocities.com/lacis_alfredo/src);

§ download alflb.zip;§ to keep the files together and to prevent any file-name clashes, extract to

<your generic library dir>/alflb;§ either include the required source files in your project or use GNU make to build the library

first and add the library to your project;§ add the include directive -I<your generic library dir>/alflb to the compiler flags in your

Makefiles.

1 GCC= GNU Compiler Collection, available from www.gnu.org.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 7 of 145

Page 8: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

1.3 RequirementsRequirements are:

• A C/C++ Compiler, for example:

• GNU Compiler Collection (GCC) and Integrated Development Environments (IDEs) & tools based on GCC: GNU Linux/GCC; Rowley Associates, WinAVR;

• ARM Project Manager;• Renesas (ex Hitachi) HEW;• Labwindows CVI.• Some specific functions have been marked National Instruments, LabWindows

• Comma/Tab Separated Variable (csv/tsv) Files, datethis, mkdirhier, FileHasChanged, Text Size Routines.

• Borland Builder:• mkdirhier.

• A large subset has been built with MS Visual Studio 6: refer to Alf for a recent list.

• Useful, although not mandatory, is GNU make.make and gcc can build most of the library and all of the test applications in one pass.

• Header files: typical system headers are:<ctype.h> <stdarg.h> <stddef.h> <stdio.h> <stdlib.h> <string.h>

• Header files: typical ALFLB headers are:"alflb.h" "alflog.h" "bitmapfs.h" "bytewisecrc.h" "cassert.h" "csv_kppp.h"

"ctrlchar.h" "ezi_endian.h" "ezi_opt.h" "eziqueue.h" "fd_set_ops.h"

"ftoa_truncate.h" "is_not.h" "mirror_table.h" "nibblefs.h" "timer_msec.h"

"uniquify.h"

• ctrlchar.h requires awk to rebuild it from ctrlchar.txt, or it can be manually edited.

1.4 Building the Library and the Test ApplicationsMost of the library and the test apps build with GNU make and gcc, but a small fraction of these, due to their platform base, will never be part of a GCC build without modification. In this document, these exceptions have been highlighted immediately following the introduction of each library or suite.

Conversely, many of these have been built with other IDEs, such as the ARM Project Manager, Renesas HEW, Labwindows CVI and WinAVR. In some cases the library sources are simply added, directly or via soft links, to the project builds.

If you have GCC tools installed, either a Linux distribution, Cygwin or MinGW, ALFLB can be built from the root alflb subdirectory by typing make. This will build a a library called libalflb.a in alflb/, along with the test applications in a subdirectory called alflb/test.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 8 of 145

Page 9: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

1.5 Procedures Used When Routines Were Added To The Library

1.5.1 Only Clean Routines Need Apply

The new routines are exhaustively tested including usually writing a test application in the same source code file. This test app which can be enabled and built and with a -D command-line compiler switch. Once I am happy with the routines with respect to:

§ Design - will this make a good library routine? This is the best (only?) time for name changes;

§ Implementation - good encapsulation of functionality, well-behaved, not too inefficient, etc;§ Coding Standard - return values, naming, etc;§ Error and Exception Handling - defined behaviour when errors are encountered;

then they are considered for inclusion.

1.5.2 Adding Documentation to This Document

When reuse is intended, the next step is to write some documentation: at a minimum, Synopsis and Usage are required.

In very approximate alphabetical order, I place the new documentation into this document, and bump the document's rev (lately I have only been using a date, since it is easier to track. I note in particular things like Returns:. I also add a subsection called Bugs which does not describe faults, rather things like limitations, or perhaps history-and-why-you-cannot-change-this-routine's-functionality-any-more.

1.5.3 Check for Build Errors & Correct Operation

Obviously(?), I fix all errors, and steadfastly try to remove as many warnings as I can. I then run the test apps where available to check for correct operation.

1.6 Examples of Useful Target-Specific ConstructionsHere are some useful #if defined constructions when writing source to be compiled by several different compilers. The problems are often not the compilers as such, but header files may not be named in a Posix-compliant way, and I/O is often compiler-library based. Here is an example from ezi_sproc.c:

#if defined __arm /* ARM compiler */

#include <string.h>

#else

#include <memory.h>

#endif

1.7 Layout of This DocumentApart from the next two sections on Ezi-Types and Ezi-Strings, the remainder of the document is laid out in approximate alphabetical order of suite name. If you cannot find it in the Table Of Contents, try the Index.

Some routines described here are macros, and so their parameters have the type of the variables used and are shown as /type/: these should be replaced with the required type, e.g., int, char, etc. Macros that do not cast their return value are shown as /typeless/.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 9 of 145

Page 10: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

2 Ezi-TypesUCHAR, USHORT, UINT, ULONG, ULL, SCHAR, SSHORT, SINT, SLONG, SLL, USHORTSZ, ULONGSZ,

ULLSZ

The type EZISTR_T* is described in the following section on the Ezi-String Function Suite.

2.1 SynopsisOne of the problems facing C/C++ programmers is the lack of consistent types across development platforms and targets. Some programmers try to address these by creating typedefs for them. For example, an unsigned long (a 4-byte integer) has been seen by the author as:

int32u

UINT32

int4u (i.e. 4 bytes)

The problem with typedefs is that you have to be consistent. Sometimes, across platforms, and with company history against you, and especially across the breadth of time, these typedefs come back to byte you (ha-ha). What you really wanted was simply an unsigned long, a signed short, etc... but just a short-hand way of writing them down.

The Ezi-Types described here are not typedefs - they really are just macros for the standard C/C++ types shown below.

They are not perfect: they do not guarantee the number of bits used to store a particular value, but they are simple. Using these, you really can mix up an unsigned short with a USHORT, with the guarantee that a USHORT declaration will not break the next project in which you try to use that source file! These declarations are a matter of "Keep It Simple, Stupid!"

2.2 Usage#include "alflb.h"

#define UCHAR unsigned char

#define USHORT unsigned short

#define UINT unsigned int

#define ULONG unsigned long

#define ULL unsigned long long

#define SCHAR signed char Of these, typically only use SCHAR to ensure type of char.#define SSHORT signed short

#define SINT signed int

#define SLONG signed long

#define SLL signed long long

#define USHORTSZ (sizeof(USHORT)) These are typically only used.#define ULONGSZ (sizeof(ULONG))

#define ULLSZ (sizeof(ULL))

2.2.1 Various Functions Declared Using Ezi-Types

These are declarations from elsewhere in this document:

#include "alflb.h"

...

UCHAR *BM_ALLOC(BM_SIZE_T bit_max);

...

void eziq_init(EZIQUEUE_T *peq, size_t maxsize, UCHAR *pstorage);

alflb_20120306.odt © 2002-2012 Alf Lacis Page 10 of 145

Page 11: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

3 Ezi-String Function SuiteDeclaration (Instantiation) of Ezi-Strings:

EZISTR, EZISTRBASIC, EZISTREMPTY

Declaration of Ezi-String Pointers Only:EZISTR_T *

Memory Allocation for Ezi-String Pointers:ezi_salloc, ezi_calloc, ezi_realloc

Various Ezi-String Functions Described in This Section:ezi_clr, ezi_ch, ezi_cpy, ezi_cpy_raw, ezi_cat, ezi_cat_raw, ezi_cpy_cat,

ezi_cpy_cat_raw, ezi_len, ezi_fill, ezi_ltrim, ezi_rtrim, ezi_trunc, ezi_snprintf,

ezi_vsnprintf

Other Ezi-String Functions Described Elsewhere in This Document:ezi_binary2asciihex_raw, ezi_binary2asciihex, ezi_b2ah_raw, ezi_b2ah,

ezi_asciihex2binary_raw, ezi_asciihex2binary, ezi_ah2b_raw, ezi_ah2b,

ezi_dbg, ezi_dbg_raw, ezi_esc, ezi_sproc , ezi_squash, ezi_printable

3.1 SynopsisThe Ezi String suite provides a collection of often-required string functionality, using the EZISTR_T * type.

The driving force behind creating this suite was to have a consistent, safe (overflow-proof) and simple class of string handling functions. Because all the information is contained in the EZISTR_T type, the parameter list using ezi-string variables is much shorter than for a fully specified C-string (i.e. string address, maximum length and returned length); obviating the need for parameters for maximum lengths and returned lengths. Importantly, importing and exporting these Ezi-strings to/from ordinary C-strings is also easy, to help usage with library functions and other 'legacy' code which require ordinary C-strings.

Most of the usual string functions are detailed here, but some, such as ezi_dbg and ezi_esc are discussed under other headings, since the EZISTR_T-version interface has been added to these and other ALFLB functional groups.

3.2 The EZISTR_T * TypeOnce an ezi-string is created, all further usage of that string is via a pointer. I.e., the visible type of the created ezi-string is a pointer of type EZISTR_T*. Internally, the pointer points to a structure which is usually private, but is discussed here for background purposes.

(You may now skip the rest of this subsection if you want to go straight to Usage.)

The private part of the declaration of an ezi-string contains the following members:

struct

{

size_t max;

size_t len;

char str[max_len+1];

}

name ## _private ={ max_len, sizeof(init_str)-1, init_str };

The name ## creates a mangled private name, name_private, which is unique to every instantiation of every ezi-string.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 11 of 145

Page 12: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

However, the mangled name name_private is never actually used in practice. Instead, a separate pointer is given the original ezi-string instantiation name of name. And here is where the pointer's type is interesting: the type of the pointer is always the same (not unique): EZISTR_T*, and is identical for every ezi-string. The EZISTR_T* type is very similar to the above, with the differences highlighted:

typedef struct

{

size_t max;

size_t len;

char str[EZI_DBG_MAX+1];

}

EZISTR_T;

Typically EZI_DBG_MAX is set to 1. If using a debugger, it is sometimes better to use the value of about 30 (for small embedded systems) or perhaps 1024 for PCs and larger, so that strings are expanded properly by the debugger. This is OK, because no space is allocated when the pointer is instantiated: only the pointer itself is created, but then force-typed onto the private, unique variable.

An example may illustrate this better: Create and use 2 ezi-strings:

EZISTR(question, 100, "My query");

EZISTR(rev , 20 , "2.0.19");

These actually create these 2 different-length, unique structures (with important differences highlighted) named question_private and rev_private:

struct

{

size_t max;

size_t len;

char str[100+1];

} question_private ={ 100, sizeof("My query")-1, "My query" };

struct

{

size_t max;

size_t len;

char str[20+1];

} rev_private ={ 20, sizeof("2.0.19")-1, "2.0.19" };

However, the types of the named pointers created are always the same, EZISTR_T *, and are created from type casts from the private different-length structures:

EZISTR_T *question = (EZISTR_T *)&question_private;

EZISTR_T *rev = (EZISTR_T *)&rev_private;

3.3 Usage

3.3.1 Declaration (Instantiation) of Ezi-Strings

#include "alflb.h"

EZISTR(

name,

max_len,

init_str);

This is the usual declaration: it defines all the parameters, e.g.. . .

EZISTR(filename, MAX_PATH, "");

alflb_20120306.odt © 2002-2012 Alf Lacis Page 12 of 145

Page 13: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

EZISTRBASIC(

name,

init_str);

In case you simply need to initialise an ezi-string, but probably not need to use it to store a larger string, you can use this, e.g.. . .

EZISTRBASIC(mode, "rw+");

EZISTREMPTY(

name,

max_len);

This is used where no initialisation is required. Actually, the string is initialised, to the value "" and length 0. E.g.:. . .

EZISTREMPTY(filename, MAX_PATH);

3.3.2 Declaration (Instantiation) of Ezi-String Pointers Only

#include "alflb.h"

EZISTR_T *name = NULL;[1] This creates a pointer for use with ezi_salloc, ezi_calloc and ezi_realloc functions described below.

Also since a normal Ezi-String is known by its pointer, then pointer assignment could be used with safety, e.g.:. . .

EZISTR(name, MAXLEN, "");

EZISTR_T *ptr = NULL;

. . .

ptr = name; // Copy 'name's address to the pointer 'ptr'.

[1] Discussion: The '= NULL' is not required for global variables, since the initial design of C, then the ANSI standard, requires that explicitly uninitialised global space (BSS[2] space) actually is initialised by C start-up code (before main is called) to all zeros. This is NOT true for non-static variables which are local to functions (since they are created on the stack without being initialised, but is good practice: consider the situation where a variable was global, then was moved inside a function to reduce its scope.

[2] BSS comes from an old IBM assembler pseudo op-code for 'Block (of memory) Started by a Symbol'.

3.3.3 Memory Allocation for Ezi-String Pointers

#include "alflb.h"

EZISTR_T *ezi_salloc(

char *initstr);

Ezi, and safe, malloc + ezi_cpy_raw style call. Obeys malloc/calloc rules, e.g.: // argv[ii] contains a file name:

EZISTR_T *ptr = NULL; // create the pointer only.

. . .

if ( (ptr = ezi_salloc(argv[ii])) == NULL )

{

fprintf(stderr, "could not allocate memory at "__FILE__"

line %u\n", __LINE__);

. . .

EZISTR_T *ezi_calloc(

size_t size);

Ezi, and safe, calloc style call. Obeys malloc/calloc rules, e.g.:. . .

EZISTR_T *ptr = NULL; // create the pointer only.

. . .

if ( (ptr = ezi_calloc(MAXLEN)) == NULL )

{

fprintf(stderr,

"could not allocate %lu memory at "__FILE__

" line %u\n", MAXLEN, __LINE__);

. . .

alflb_20120306.odt © 2002-2012 Alf Lacis Page 13 of 145

Page 14: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

EZISTR_T *ezi_realloc(

EZISTR_T *old_ptr,

size_t size);

Ezi, and safe, realloc style call. Obeys realloc rules. This can be used to either increase or decrease the maximum size of an Ezi-string.

3.3.4 Various Ezi-String Functions

#include "alflb.h"

EZISTR_T *ezi_clr(

EZISTR_T *buf);

Clears an Ezi string to empty, and sets its length to 0. E.g.: ezi_clr(question);

EZISTR_T *ezi_ch(

EZISTR_T *buf,

int ch_integer);

Ezi, and safe, addition of a character ch_integer to the end of an Ezi string, and increments its length. Note int character. E.g.: ezi_ch(question, 'x');

EZISTR_T *ezi_cpy(

EZISTR_T *to,

EZISTR_T *from);

Ezi, and safe, string copy and length calculation. E.g.: ezi_cpy(revision, response);

EZISTR_T *ezi_cpy_raw(

EZISTR_T *to,

char *from);

Ezi, and safe, C-string to Ezi-string copy and length calculation. Typically used to intialise an ezi-string from a C-string. E.g.: ezi_cpy_raw(question, "what's going on?");

(This function was previously called ezi_set.)

EZISTR_T *ezi_cat(

EZISTR_T *to,

EZISTR_T *from);

Ezi, and safe, string concatenation and length adjustment. E.g.: ezi_cat(ezi_string, ezi_string_to_add);

EZISTR_T *ezi_cat_raw(

EZISTR_T *to,

char *from);

Ezi, and safe, C-string onto an ezi-string concatenation, with length adjustment. E.g.: ezi_cat_raw(ezi_string, " and result=SUCCESS");

EZISTR_T *ezi_cpy_cat(

EZISTR_T *to,

EZISTR_T *from1,

EZISTR_T *from2);

Ezi, and safe, Ezi-string copy and concatenation and length adjustment. E.g.: ezi_cpy_cat(ezi_string, ezi_str_one, ezi_str_two);

EZISTR_T *ezi_cpy_cat_raw(

EZISTR_T *to,

char *from1,

char *from2);

Ezi, and safe, C-string copy and concatenation to an Ezi-string, with length adjustment. For example, where argv[1] is the first parameter passed to main: char path[] = "/tmp/";

ezi_cpy_cat_raw(ezi_string, path, argv[1]);

size_t ezi_len(

EZISTR_T *buf);

Recalculates Ezi string length (especially if string populated by a non-Ezi or legacy function). E.g.: some_legacy_function(response->str);

ezi_len(response);

EZISTR_T *ezi_fill(

EZISTR_T *buf,

int ch_integer);

Ezi, and safe, filling of a string with the character ch_integer. Note int character. E.g.: ezi_fill(horizontal_ruler, '=');

EZISTR_T *ezi_ltrim(

EZISTR_T *buf,

size_t left_trim);

Ezi, and safe, trimming of left-hand characters from buf. E.g.: ezi_cpy_raw(ezi, "my junk");

ezi_ltrim(ezi, 3); // removes "my " from ezi

EZISTR_T *ezi_rtrim(

EZISTR_T *buf,

size_t right_trim);

Ezi, and safe, trimming of right-hand characters from buf. E.g.: ezi_cpy_raw(ezi, "junk of mine");

ezi_rtrim(ezi, 8); // removes " of mine" from ezi

alflb_20120306.odt © 2002-2012 Alf Lacis Page 14 of 145

Page 15: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

EZISTR_T *ezi_trunc(

EZISTR_T *buf,

size_t new_length);

Ezi, and safe, truncation of an Ezi String.

int ezi_snprintf(

EZISTR_T *ezi,

const char *format,

... );

Returns:

Ezi, and safe, snprintf-style call for ezi-strings. E.g.: ezi_snprintf(question, "V%dS%d", velocity, distance);

See any description of snprintf for the return value.

int ezi_vsnprintf(

EZISTR_T *ezi,

const char *format,

va_list args);

Returns:

Ezi, and safe, vsnprintf-style call for ezi-strings. E.g.: ezi_vsnprintf(question, fmt, args);

See any description of vsnprintf for the return value.

ezi_binary2asciihex_raw(),

ezi_binary2asciihex(),

ezi_b2ah_raw(),

ezi_b2ah(),

ezi_asciihex2binary_raw(),

ezi_asciihex2binary(),

ezi_ah2b_raw(),

ezi_ah2b()

See section on ASCII-Hex to Raw Binary Data.

ezi_dbg(),

ezi_dbg_raw()

See section on C-String and Debug-String Functions.

ezi_esc() See section on C-String and Debug-String Functions.

ezi_sproc(),

ezi_squash(),

ezi_printable()

See section on String Processor.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 15 of 145

Page 16: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

3.4 Example 1: Including Use of Ezi-Strings in Legacy C FunctionsThe parts of the ezi-string that can be exposed from the EZISTR_T type are a pointer to the string itself, str, the current length of the string, len, and the capacity of the string, max. These can be used with legacy library functions as shown in the following examples.

#include <stdio.h>

#include "alflb.h"

#define MAX_RECORD 120

#define MAX_COPY 10 // for this test, make 'copy' much shorter

int main(int argc, char *argv[])

{

EZISTR(record, MAX_RECORD, "");

EZISTR(copy, MAX_COPY , "");

int ii;

FILE *input;

input = fopen("my_file", "r");

while ( fgets(record->str, record->max, input) != NULL ) // legacy: max length

{

ezi_len(record); // Fixes record's length after a legacy call

ezi_cpy(copy, record); // Safe! Prevents overflow to shorter string

for ( ii = 0; ii < copy->len; ii++ ) // Access to copy's length

{

sputc(copy->str[ii]); // legacy: char array

}

}

fclose(input);

return 0;

}

3.5 Example 2: An Unrelated Code Snippetint DeviceRestart(Device *device)

{

EZISTR(command , CMD_MAX , ""); // could also use EZISTREMPTY(command , CMD_MAX );

EZISTR(response, RESP_MAX, ""); // EZISTREMPTY(response, RESP_MAX);

if ( ezi_snprintf(command, "F%d" "I%d" "S%d" "A%d" "D%d" "e%d" "r%d",

vel_final , // vf = velocity final

vel_init , // vi = velocity initial

vel_stop , // vs = velocity stopping

accel , // a = acceleration

decel , // d = deceleration

error_max , // max error between motor & encoder

retries ) // number of retries if collision detected

>= command->max )

return STATUS_STRING_OVERFLOW;

send_ezi_message(device, command, response); // see below

return ( strcmp("OK", response->str) == 0 ) ? // legacy usage: char array

STATUS_OK;

STATUS_NOT_OK:

}

void send_ezi_message(Device *device, EZISTR_T *command, EZISTR_T *response)

{

... <do something with command> // send command to device

... <do something with response> // wait for response

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 16 of 145

Page 17: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

3.6 Example 3: In-built Test ApplicationThe test app from ezi_str.c:

#ifdef EZI_TEST_APP #include <stdio.h> // for printf() #include <stdlib.h> // for free() int main(int argc, char *argv[]) { int jj; #define P printf #define TMAX 20 EZISTR(s1, TMAX, ""); EZISTR(s2, TMAX, ".123456789.12345678"); EZISTR(s3, TMAX, ".123456789.123456789"); EZISTR(s4, TMAX+1, ".123456789.123456789."); EZISTR(non, TMAX, ".\177\37\377456789.123456789"); char c1[] = ".123456789.12345678"; char c2[] = ".123456789.123456789.12345678"; #ifdef EZI_TEST_APP_OVERFLOW // should give at least a warning (would prefer an error) EZISTR(over , TMAX, ".123456789.123456789.123456789.123456789"); #endif EZISTR_T *p1; EZISTR_T *p2; ezi_cpy(s1, s2); P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from s2)" , s1->len, s1->str); ezi_cpy(s1, s3); P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from s3)" , s1->len, s1->str); ezi_cpy(s1, s4); P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from s4)" , s1->len, s1->str); ezi_len(s1); P("%24.24s=len=%2d \"%s\"\n", "ezi_len(recalc)" , s1->len, s1->str); // recalc length s1->str[15] = '\0'; ezi_len(s1); P("%24.24s=len=%2d \"%s\"\n", "ezi_len(recalc)" , s1->len, s1->str); // recalc length for ( jj = 0; jj < 6; jj++ ) { ezi_ch(s1,'A'+jj);P("%24.24s=len=%2d \"%s\"\n", "ezi_ch" , s1->len, s1->str); } ezi_cpy(s1, s2); P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from s2)" , s1->len, s1->str); ezi_cat(s1, s2); P("%24.24s=len=%2d \"%s\"\n", "ezi_cat(from s2)" , s1->len, s1->str); ezi_len(s1); P("%24.24s=len=%2d \"%s\"\n", "ezi_len" , s1->len, s1->str); ezi_clr(s1); P("%24.24s=len=%2d \"%s\"\n", "ezi_clr" , s1->len, s1->str); ezi_dbg(s1, non); P("%24.24s=len=%2d \"%s\"\n", "ezi_dbg(from non)" , s1->len, s1->str); // stops early ezi_esc(non, s1); P("%24.24s=len=%2d \"%s\"\n", "ezi_esc(from s1)" , non->len, non->str); ezi_sproc(non, SP_8BIT_NONP|SP_ONE_BLANK, ' '); P("%24.24s=len=%2d \"%s\"\n", "ezi_sproc(non)" , non->len, non->str); #ifdef EZI_TEST_APP_OVERFLOW ezi_cpy(s1, over );P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from over)", s1->len, s1->str); #endif ezi_cpy(s1, s3); P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from s3)" , s1->len, s1->str); ezi_ltrim(s1, 2); P("%24.24s=len=%2d \"%s\"\n", "ezi_ltrim(s1, 2)" , s1->len, s1->str); ezi_rtrim(s1, 2); P("%24.24s=len=%2d \"%s\"\n", "ezi_rtrim(s1, 2)" , s1->len, s1->str); ezi_ltrim(s1, 999); P("%24.24s=len=%2d \"%s\"\n", "ezi_ltrim(s1,999)" , s1->len, s1->str); ezi_cpy(s1, s3); P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from s3)" , s1->len, s1->str); ezi_rtrim(s1, 999); P("%24.24s=len=%2d \"%s\"\n", "ezi_rtrim(s1,999)" , s1->len, s1->str); ezi_cpy(s1, s3); P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from s3)" , s1->len, s1->str); ezi_ltrim(s1, 20); P("%24.24s=len=%2d \"%s\"\n", "ezi_ltrim(s1,20)" , s1->len, s1->str); ezi_cpy(s1, s3); P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy(from s3)" , s1->len, s1->str); ezi_rtrim(s1, 20); P("%24.24s=len=%2d \"%s\"\n", "ezi_rtrim(s1,20)" , s1->len, s1->str); ezi_cpy_raw(s1, c1);P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy_raw(from c1)" , s1->len, s1->str); ezi_cpy_raw(s1, c2);P("%24.24s=len=%2d \"%s\"\n", "ezi_cpy_raw(from c2)" , s1->len, s1->str); ezi_clr(s1);

ezi_cat_raw(s1, c1);P("%24.24s=len=%2d \"%s\"\n", "ezi_cat_raw(from c1)" , s1->len, s1->str); ezi_cat_raw(s1, c2);P("%24.24s=len=%2d \"%s\"\n", "ezi_cat_raw(from c2)" , s1->len, s1->str); p1 = ezi_salloc(c1);P("%24.24s=max=%2d len=%2d \"%s\"\n", "p1=ezi_salloc(c1)", p1->max, p1->len, p1->str ); p2 = ezi_calloc(20);P("%24.24s=max=%2d len=%2d \"%s\"\n", "p2=ezi_calloc(20)", p2->max, p2->len, p2->str ); ezi_cpy(p1, s2); P("%24.24s=max=%2d len=%2d \"%s\"\n", "ezi_cpy(p1,s2)" , p1->max, p1->len, p1->str ); ezi_cpy(p2, s2); P("%24.24s=max=%2d len=%2d \"%s\"\n", "ezi_cpy(p2,s2)" , p2->max, p2->len, p2->str ); p1 = ezi_realloc(p1,30); P("%24.24s=max=%2d len=%2d \"%s\"\n", "ezi_realloc(p1,30)",p1->max, p1->len, p1->str ); ezi_cpy(p1, s4); P("%24.24s=max=%2d len=%2d \"%s\"\n", "ezi_cpy(p1,s4)" , p1->max, p1->len, p1->str ); ezi_cat(p1, s2); P("%24.24s=max=%2d len=%2d \"%s\"\n", "ezi_cat(p1,s2)" , p1->max, p1->len, p1->str ); NULLIFY(p1) NULLIFY(p2) return 0; } #endif // #ifdef EZI_TEST_APP

alflb_20120306.odt © 2002-2012 Alf Lacis Page 17 of 145

Page 18: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

3.6.1 Output of Example 3

Use this command line to compile and run the test application contained in ezi_str.c:

$ gcc -Wall -o ezi_str d_string.c convescs.c strncpyn.c ezi_sproc.c ezi_alloc.c -DEZI_TEST_APP ezi_str.c$ ./ezi_str ezi_cpy(from s2)=len=19 ".123456789.12345678" ezi_cpy(from s3)=len=20 ".123456789.123456789" ezi_cpy(from s4)=len=20 ".123456789.123456789" ezi_len(recalc)=len=20 ".123456789.123456789" ezi_len(recalc)=len=15 ".123456789.1234" ezi_ch=len=16 ".123456789.1234A" ezi_ch=len=17 ".123456789.1234AB" ezi_ch=len=18 ".123456789.1234ABC" ezi_ch=len=19 ".123456789.1234ABCD" ezi_ch=len=20 ".123456789.1234ABCDE" ezi_ch=len=20 ".123456789.1234ABCDE" ezi_cpy(from s2)=len=19 ".123456789.12345678" ezi_cat(from s2)=len=20 ".123456789.12345678." ezi_len=len=20 ".123456789.12345678." ezi_clr=len= 0 "" ezi_dbg(from non)=len=20 ".\177\37\377456789.1" ezi_esc(from s1)=len=12 ". #�456789.1" � ezi_sproc(non)=len=10 ". 456789.1" ezi_cpy(from s3)=len=20 ".123456789.123456789" ezi_ltrim(s1, 2)=len=18 "23456789.123456789" ezi_rtrim(s1, 2)=len=16 "23456789.1234567" ezi_ltrim(s1,999)=len= 0 "" ezi_cpy(from s3)=len=20 ".123456789.123456789" ezi_rtrim(s1,999)=len= 0 "" ezi_cpy(from s3)=len=20 ".123456789.123456789" ezi_ltrim(s1,20)=len= 0 "" ezi_cpy(from s3)=len=20 ".123456789.123456789" ezi_rtrim(s1,20)=len= 0 "" ezi_cpy_raw(from c1)=len=19 ".123456789.12345678" ezi_cpy_raw(from c2)=len=20 ".123456789.123456789" ezi_cat_raw(from c1)=len=19 ".123456789.12345678" ezi_cat_raw(from c2)=len=20 ".123456789.12345678." p1=ezi_salloc(c1)=max=19 len=19 ".123456789.12345678" p2=ezi_calloc(20)=max=20 len= 0 "" ezi_cpy(p1,s2)=max=19 len=19 ".123456789.12345678" ezi_cpy(p2,s2)=max=20 len=19 ".123456789.12345678" ezi_realloc(p1,30)=max=30 len=19 ".123456789.12345678" ezi_cpy(p1,s4)=max=30 len=21 ".123456789.123456789." ezi_cat(p1,s2)=max=30 len=30 ".123456789.123456789..12345678" $

alflb_20120306.odt © 2002-2012 Alf Lacis Page 18 of 145

Page 19: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

4 Allocate and Access VariablesEZI_ALLOCATE, EZI_EXTERN, EZI_INIT

(EZI_ACCESS is no longer required.)

4.1 SynopsisThese macros prevent the "double specification" problem that occurs when using global variables, by putting everything into one location: both the declaration and the initialisation are specified once, in the header file only. Although the usage of global variables is decried, you still need some ability to use them easily. For example, in an embedded environment, the overhead of space and speed of using accessor functions may not be practicable.

Typically, if you want to do this with the C language, you have to doubly specify every variable, i.e., in two separate locations like this:

(1) declaration in a header file, e.g.: mem.h : extern char build[]; // All the references are specified

extern void *jump_addr; // All the references are specified

extern DEVICE_T config; // All the references are specified

(2) definition (instantiation) in one particular source file, e.g.: main.c : #include "mem.h"

. . .

char build[] = __DATE__ " " __TIME__; // All repeated

void *jump_addr = (void*)reboot_function; // and initialised.

CONFIG_T config = { 8, 'N', 1 }; // here.

4.2 Usage Notes

4.2.1 .c files

To use these macros, there is no direct instantiation in the .c source files such as in (2) above. It is all done in the header file, see (1) above, using the macros.

In one source file, e.g., main.c, just above the #include, you define the EZI_ALLOCATE directive to specify that this particular source file allocates the variables like this: (2) becomes:

#define EZI_ALLOCATE Nothing else is required! Initialisation is in mem.h.#include "mem.h"

Every other source file #includes "mem.h" without specifying the EZI_ALLOCATE define.

4.2.2 .h files

In your header file(s), replace the usage of extern with EZI_EXTERN, and use the EZI_INIT macro to perform the initialisation. Structures cannot use the EZI_INIT macro, but can still easily specify the variable in one location by referencing EZI_ALLOCATE. Using the above variables as examples:

(1) becomes: mem.h:#include "alflb.h"

EZI_EXTERN char build[] EZI_INIT(__DATE__ " " __TIME__);

EZI_EXTERN void *jump_addr EZI_INIT((void*)reboot_function);

EZI_EXTERN DEVICE_T config

#ifdef EZI_ALLOCATE

= { 8, 'N', 1 }

#endif

;

alflb_20120306.odt © 2002-2012 Alf Lacis Page 19 of 145

Page 20: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

5 ASCII-Hex to Raw Binary Data & v/vezi_binary2asciihex, ezi_b2ah, ezi_binary2asciihex_raw, ezi_b2ah_raw, binary2asciihex ,

ezi_asciihex2binary, ezi_ah2b, ezi_asciihex2binary_raw, ezi_ah2b_raw, asciihex2binary,

decode_asciihex_char_pair

5.1 SynopsisConverters specifically for converting ASCII-Hex formatted data to binary data and vice versa.

5.1.1 Binary to ASCII-Hex Functions

These functions convert any binary data to a string of ASCIIHEX characters. Conversion stops only at max_len, or in the case of the ezi_... functions, before the output is overflowed. By its nature, the size of the output buffer is twice max_len, plus 1. A trailing '\0' is always added, since the output buffer is meant to represent a C string.

Example: Convert binary data to ASCIIHEX. This example's binary length was specified to include the four '\0' in the binary data.

convert \7Fred Dagg\12Sue Smith\12\0\0\0\0

to 074672656420446167670A53756520536D6974680A00000000

5.1.2 ASCII-Hex to Binary Functions

These convert an ASCIIHEX string of the characters 0-9A-Fa-f to a series of binary (UCHAR) values. Conversion stops at the first non-hex character *pair* or the maximum length, i.e., end-of-string=='\0', or any other character not 0-9A-Fa-f, or in the case of the ezi_... functions, before the output is overflowed. By its nature, the output buffer is 1/2 (the size of the input string minus 1) or shorter. In the non-Ezi String version, no trailing '\0' is added to the output buffer. The Ezi String version always adds '\0', since an Ezi String has an extra byte allocated (e.g., for this purpose) over the instantiated size.

WARNING: The final out buffer, either Ezi or non-Ezi version, may not constitute a C character string, since the AsciiHex string may contain 00 representing embedded '\0's. The Ezi version's out->len value will be correct (providing it has not overflowed) so do not use ezi_len or ezi_cpy on the out buffer, since this may truncate valid data.

NOTE: Back-slashes shown for clarity: these are not actually printed: these non-printing characters are the <bell>(\7), <linefeed>(\12).

Example 1: Convert ASCIIHEX to binary data.convert 074672656420446167670A53756520536D6974680A

to \7Fred Dagg\12Sue Smith\12

Example 2: Convert ASCIIHEX with internal 00 to binary data.convert 074672656420446167670A0053756520536D6974680A

to \7Fred Dagg\12\0Sue Smith\12

5.2 Usage#include "alflb.h"

EZISTR_T *ezi_b2ah(

EZISTR_T *out,

EZISTR_T *in);

Ezi-String version for converting Ezi-String binary data object to an Ezi-String ASCII-Hex object.The full entry-point(linker) name is ezi_binary2asciihex.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 20 of 145

Page 21: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

EZISTR_T *ezi_b2ah_raw(

EZISTR_T *out,

UCHAR *in,

size_t max_len);

Ezi-String version for converting raw binary data to an Ezi-String ASCII-Hex object.The full entry-point name is ezi_binary2asciihex_raw.

char *binary2asciihex(

char *out,

unsigned char *in,

size_t max_len);

Old non-Ezi-String version.

EZISTR_T *ezi_ah2b(

EZISTR_T *out,

EZISTR_T *in);

Ezi-String version for converting Ezi-String ASCII-Hex data object to an Ezi-String binary object.The full entry-point name is ezi_asciihex2binary.

EZISTR_T *ezi_ah2b_raw(

EZISTR_T *out,

char *in);

Ezi-String version for converting raw ASCII-Hex data to an Ezi-String binary object.The full entry-point name is ezi_asciihex2binary_raw.

unsigned char

*asciihex2binary(

unsigned char *out,

size_t *out_len,

char *in,

size_t max_len);

Old non-Ezi-String version.

UCHAR

decode_asciihex_char_pair(

char *string);

Decodes 2 ASCIIHex chars. string does not need to be byte-aligned.

5.3 Example 1: Test AppIn asciihex.c, there are actually two applications. To build and run the test app, enter these commands:

$ gcc -Wall -o asciihex_test hex36.c d_string.c ezi_str.c convescs.c strncpyn.c reversen.c

simple_itoa.c -DTEST_APP_ASCIIHEX asciihex.c

$ ./asciihex_test

asciihex2binary and binary2asciihex conversions

from binary2asciihex: '\aFred Dagg\177\200\377Sue Smith\n\0\0\0\000'=>

'074672656420446167677F80FF53756520536D6974680A00000000'

back asciihex2binary: '\aFred Dagg\177\200\377Sue Smith\n\0\0\0\000'<=

'074672656420446167677F80FF53756520536D6974680A00000000'

$

5.4 Example 2: Command-Line Debugging AppThe second application has more long-term use: you can use it to debug or create ASCII-Hex, especially if it comes out of remote devices in ASCII-Hex format. To build and run the debugging app, enter these commands:

$ gcc -Wall -o asciihex hex36.c d_string.c ezi_str.c strncpyn.c -DMAIN_APP_ASCIIHEX asciihex.c

$ ./asciihex -a "Honk if you can read this"

486F6E6B20696620796F752063616E20726561642074686973

$ ./asciihex -b 486F6E6B20696620796F752063616E20726561642074686973

Honk if you can read this

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 21 of 145

Page 22: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

6 Bit-Array (Bit-Map) SuiteBM_DECLARE, BM_ALLOC, BM_FREE, BM_SET, BM_CLR, BM_TEST, BM_ANY, BM_ALL, BM_ASSIGN,

BM_MAX_BYTES

6.1 SynopsisThese routines provide the ability to set up and use large bit-arrays, also called bit-maps, (not bitmap pictures) of 1/0 (on/off) flags. These bit arrays are stored in unsigned char arrays, with a maximum number of elements as either 65,536 bits (16-bit target) or 4,294,967,296 bits (32-bit target). These have a corresponding maximum array size of 8k bytes or 536M bytes. As for any memory object, if used between threads, use semaphores, critical sections or other mechanism for coordination.

These routines were originally implemented as both macros and functions, but the macro versions have been removed, since it was found, at least under GCC, that the function versions were actually faster.

[#] On a target where you want to use malloc & free, this is typically allocated using BM_ALLOC. On those targets where you don’t want to use BM_ALLOC, you can use the simple declaration BM_DECLARE. Alternately, you may use any unsigned character array of your own choice.

The index and size parameters were, up to about 2005, of type int, but since is now BM_SIZE_T, which is typically defined as a size_t.

6.2 Usage#include "bitmapfs.h"

BM_DECLARE(

arrayName,

bit_max);

Macro to instantiate an array to hold bitmax bits.Unsigned char array to be instantiated/declared.Number of bits to allocate.

UCHAR *BM_ALLOC(

BM_SIZE_T bit_max);

Returns:

mallocs an array (of unsigned char) to hold bitmax bits.Number of bits to allocate.NULL if memory could not be allocated.

void BM_FREE(

UCHAR *bit_array);

We could also use free.Pointer obtained from BM_ALLOC

void BM_SET(

UCHAR *bit_array,

BM_SIZE_T bit_index);

Sets a bit to 1Pointer to a bit array[#]Number of the bit

void BM_CLR(

UCHAR *bit_array,

BM_SIZE_T bit_index);

Clears a bit to 0Pointer to a bit array[#]Number of the bit

int BM_TEST(

UCHAR *bit_array,

BM_SIZE_T bit_index);

Returns:

Returns TRUE (1) or FALSE (0) depending on a bitPointer to a bit array[#]Number of the bitReturns TRUE (1) or FALSE (0).

int BM_ANY(

UCHAR *bit_array,

int value,

BM_SIZE_T bitmax);

Returns:

Returns TRUE (1) if array contains the requested valuePointer to a bit array[#]Value to test for. This is normalized to 1 or 0.Maximum number of bits in your bit array. NOTE: if bit array is not a multiple of 8 bits, this function takes more CPU time to test the last left-over bits.Returns TRUE (1) or FALSE (0).

alflb_20120306.odt © 2002-2012 Alf Lacis Page 22 of 145

Page 23: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

UCHAR *BM_ALL(

UCHAR *bit_array,

int value,

BM_SIZE_T bit_max);

Returns:

Sets or clears all elements of a bit array to your value. Typically used after a BM_ALLOC.Pointer to a bit array[#]Value to set. This is normalized to either 1 or 0.Maximum number of bits in your bit array.Copy of address of bit array

void BM_ASSIGN(

UCHAR *bit_array,

int value,

BM_SIZE_T bit_index);

Sets or clears one element of your bit array to your valuePointer to a bit array[#]Value to set. This is normalized to either 1 or 0.Number of the bit

BM_MAX_BYTES(

int bit_max);

Returns:

Utility macro to calculate the number of bytes to store bitmax bits. E.g., if bitmax is 700, then 88 bytes will malloced (700/8 => 87.5, then rounded up => 88).Number of bits to calculate.A number specifying the number of bytes required to hold bitmax bits.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 23 of 145

Page 24: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

6.3 Example#include <stdlib.h>

#include <stdio.h>

#include "bitmapfs.h"

#define ARRAY_SIZE (1000000)

// Testing a bit:

#define PRINT_BIT(n) printf("bit %d is %s\n", n, BM_TEST(bit_array,n)? "TRUE": "FALSE")

int main(int argc, char *argv[])

{

int ii;

unsigned char *bit_array;

int value;

int bitno;

bit_array = BM_ALLOC(ARRAY_SIZE);

if ( bit_array == NULL )

{

fprintf(stderr, "Cannot allocate memory for bit bit_array of %d bits",

ARRAY_SIZE);

return 1;

}

BM_ALL(bit_array,1,ARRAY_SIZE); // Set all bits in bit_array to 1

PRINT_BIT(12);

BM_ALL(bit_array,0,ARRAY_SIZE); // Set all bits in bit_array to 0

PRINT_BIT(12);

// Assign value to the bit array at position bitno:

value = 11111; // some stupid non-zero value

bitno = ARRAY_SIZE - 1; // the bit array is indexed like a C array.. 0 to size-1

BM_ASSIGN(bit_array,value,bitno);

PRINT_BIT(bitno);

value = 0;

BM_ASSIGN(bit_array,value,bitno);

PRINT_BIT(bitno);

// Clearing every even bit to 0, setting every odd bit to 1

for ( ii = 0; ii < ARRAY_SIZE; ii += 2 )

{ BM_CLR(bit_array,ii);

BM_SET(bit_array,ii+1);

}

PRINT_BIT(3456); // display an even bit's value

PRINT_BIT(4567); // display an odd bit's value

// Freeing space requested by BM_ALLOC: We can also use free

BM_FREE(bit_array);

return 0;

}

6.4 Output of Examplebit 12 is TRUE

bit 12 is FALSE

bit 999999 is TRUE

bit 999999 is FALSE

bit 3456 is FALSE

bit 4567 is TRUE

alflb_20120306.odt © 2002-2012 Alf Lacis Page 24 of 145

Page 25: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

7 Bit-Masks (Visual) - 4-, 8- & 16-bit VersionsNormally, due to size, only the 4- and 8-bit versions are defined.

7.1 SynopsisThese masks provide a visual representation of bits. For example, it is difficult to see what the bits are that are represented by the hex number CB, but using these masks makes it easy:

_1100_1011

Reading from the left, the bits are the 7th, 6th, 3rd, 1st and 0th bits.

The header file is actually generated by a small program, called masks, and by default, only generates 4- and 8-bit masks. If 16-bit versions are requested, the output header file grows to about 3 Mbytes.

The values are typed as unsigned char for 4- & 8-bit values, and unsigned short for 16-bit values.

7.2 Usage#include "4n8bits.h"

_xxxx 4-bit masks where the masks range from:_0000

_0001

_0010

...

to: _1111

_xxxx_xxxx 8-bit masks. The masks are visually separated into the high and low nibbles, where the masks range from:

_0000_0000

_0000_0001

_0000_0010

...

to: _1111_1111

_xxxx_xxxx_xxxx_xxxx 16-bit masks. The masks are visually separated into four nibbles, where the masks range from:

_0000_0000_0000_0000

_0000_0000_0000_0001

_0000_0000_0000_0010

...

to: _1111_1111_1111_1111

7.3 ExampleEnable a typical microcontroller's bits 7, 5, 2 & 1 as outputs on Port 9.Set pull-up resisters on input bits 6 & 0 on the same Port:

#include <<<CPU I/O definition file>>>

#include "4n8bits.h"

...

// 7 5 21

Port9DirectionRegister = _1010_0110; // '1' bit sets pin to output on this CPU

...

// 6 0

Port9PullUpResisters = _0100_0001; // '1' bit sets pull-up resister on this CPU

alflb_20120306.odt © 2002-2012 Alf Lacis Page 25 of 145

Page 26: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

8 Capacity of - Number of Entries in an ArrayCAPACITY_OF

8.1 SynopsisSimple macro built along the lines of the sizeof operator used to calculate the number of entries in an array or struct array.

20080505 This macro has been seen in other libraries typically called NELEMS.

8.2 Usage#include "alflb.h"

size_t CAPACITY_OF(

array_or_structarray);

Returns:

Get the number of entries in the named array.The array variable.The number of entries in the named variable.

8.3 Example#include "alflb.h"

...

typedef struct

{

char *pcommand;

char *(*pfunction)(char *_cmd);

}

COMMAND_TABLE_T;

...

const COMMAND_TABLE_T command_table[] =

{

{ "prompt", parser_prompt },

{ "q" , parser_question },

{ "return", parser_return },

{ "zero" , parser_set_zero },

...

...

for ( ii = 0; ii < CAPACITY_OF(command_table); ++ii )

if ( cmd_match(command_table[ii].pcommand, cmd) )

break;

if ( ii < CAPACITY_OF(command_table) )

{

trace_str("###>> Got cmd", cmd);

errno = 0;

status = command_table[ii].pfunction(cmd);

}

else

{

...

alflb_20120306.odt © 2002-2012 Alf Lacis Page 26 of 145

Page 27: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

9 Character to String Converterc2str

9.1 SynopsisVery simple function to convert a single byte to a 2-character string (the second character is a trailing '\0'). Often a string is required when calling Standard-C-Library functions such as strcat and strtol, so this little function fills the gap.

9.2 Usage#include "alflb.h"

char *c2str(

char *pstr_to,

char c_from);

Returns:

To use, pass in a string of at least 2 bytes in size, plus the character that you want to convert.The address of the destination string, for example, so it can be used immediately in another function.

9.3 Example#include "alflb.h"

...

char temp[2];

char x;

int value;

...

// for example, get the hexadecimal character x from elsewhere...

...

// Convert the single character x to a string, temp,

// then read it with sscanf into value...

sscanf(c2str(temp, x), "%x", &value);

alflb_20120306.odt © 2002-2012 Alf Lacis Page 27 of 145

Page 28: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

10 Comma/Tab Separated Variable (csv/tsv) Files - ReadingLabwindows/CVI and GNU/cygwin only:

csvgetlinebyname, csvgetline, csvnfield, csvfieldbyname, csvfield, csvreset

cvs_kppp.h and csv_kppp.c were created from original files csv.h and csvgetline2.c respectively copyright (C) 1999 Lucent Technologies, excerpted from The Practice of Programming by Brian W. Kernighan and Rob Pike, used by implied permission provided that the copyright information is intact. The name csv_kppp stands for CSV Kernighan & Pike Plus Plus.

10.1 Synopsis

10.1.1 CSV(TSV) Format

Records in CSV/TSV files are typically one per line, with one exception, see below.

Fields are separated by commas (CSV files) or an alternative is tabs (TSV files), eg:

FieldOne, FieldTwo

Sometimes, Fields can be protected, for various reasons, see below, with the double quote character, eg:

"FieldOne", "FieldTwo"

Embedded tabs and commas require that the field is protected, eg:

"Stop, Go"

Embedded double quotes require that the field is protected, and each instanceof the original double quote must be doubled, eg:

A Mr "Big"

becomes:

"A Mr ""Big"""

Leading or trailing spaces around commas (or tabs) are ignored.

Often, the first row of the CSV/TSV file is a record of Field Names, in which case the same rules about Fields also apply, ie, quotes, etc.

Not implemented: if the last field on a line has an opening quote, then some lines, with or without characters, then a closing quote somewhere, then this is regarded as one field.

10.1.2 Typical Input File Examples

A typical input given by K&P is:

"LU",86.25,"11/4/1998","2:19PM",+4.0625

alflb_20120306.odt © 2002-2012 Alf Lacis Page 28 of 145

Page 29: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

Another example, which includes Field Names, is:

FileName,MagicWandCRC32,MagicWandUniqueID,FlashManId,FlashDevId

my1.bin,"3941989e 8259837","20030612.144059 QUALITY2 4",176,176

my2.bin,"3bb3973b 5725820","20030612.144059 QUALITY2 4",176,176

my3.bin,"9607776f 6788372","20030612.144059 QUALITY2 4",137,34901

my4.bin,"9f13213f 13074874","20030612.144059 QUALITY2 4",137,34901

10.1.3 This Library

This library follows all of the above rules, with the exception of the last one about multiple lines. Why? Well the original K&P library did not have it; and I did not need it, so it just has not been done.

This library assumes that you have opened a file for reading. You must open and close the file in your own code.

New functions include the ability to: use the tab as separator, ie, ability to read TSV files; parse the Field Names from the first row of the CSV/TSV file; ask for fields by Field Name.

This library contains all the K&P functions, which could obtain one line from a CSV file, and then obtain fields by number.

This library does not release memory until you call csvreset which returns all memory allocated by the csv functions to the system.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 29 of 145

Page 30: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

10.2 Typical Usage +-----------------+ | Open file | | for reading: | | fopen | +-----------------+ | V /-------------------\ Yes / Do you want to \ No +---------< read the file using >----------+ | \ Field Names? / | | \-------------------/ | V V+------------------------------+ +-----------------------------+| loop for | | loop for || Records: | | Records: @@@@ || | | || csvgetlinebyname | | csvgetline || | | || +--------------------------| | | +-------------------------+ || | Read fields as required | | | | loop for csvnfield | || | by Name: | | | | fields: | || | csvfieldbyname | | | | csvfield | || | process Field | | | | process Field | || +--------------------------+ | | +-------------------------+ |+------------------------------+ +-----------------------------+ | | |Finished file |Finished file | +------------------+ | +---------->| Release memory: |<------------+ | csvreset | +------------------+ | V +----------------+ | Close file: | | fclose | +----------------+

@@@@: csvgetline loops once more than csvgetlinebyname because the first call to csvgetlinebyname consumes two lines from the file: the 'Header' row, then the first 'Record' row.

10.3 Usage#include "csv_kppp.h"

char *csvgetlinebyname(

FILE *fin);

Returns:

To read a line using Field Names: Get one line of the file's body, grow as needed. First time thru, gets a copy of the header row fields.File being read.Pointer to record from file. NULL at EOF.

char *csvgetline(

FILE *fin);

Returns:

To read a line using numbered fields.File being read.Pointer to record from file. NULL at EOF.

int csvnfield(

void);

Returns:

Returns number of fields in current record.No arguments.Returns number of fields.

char *csvfieldbyname(

char *name);

Returns:

Returns the named field.Field name to search for, case sensitive.Returns the named field. Returns NULL if not found.

char *csvfield(

int n);

Returns:

Returns the nth field.Number of field to return. Counting begins at 0(zero).Returns NULL if n is illegal (check with csvnfield).

alflb_20120306.odt © 2002-2012 Alf Lacis Page 30 of 145

Page 31: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

void csvreset(

void);

Releases memory to pool and set variables back to starting values.No arguments.

10.4 ExampleIf you compile csv_kppp.c using Cygwin make and defining the macro TEST_APP, you get a standalone test program, csv_kppp:

$ make

gcc -O3 -DHAVE_UNISTD_H -DUSE_MMAP -DTEST_APP -o csv_kppp csv_kppp.c -L../cygwin -lrdtools

$ cat ../../taglister/docommatiny2.csv

FileName,MagicWandCRC32,MagicWandUniqueID,FlashManId,FlashDevId

my1.bin,"3941989e 8259837","20030612.144059 QUALITY2 4",176,176

my2.bin,"3bb3973b 5725820","20030612.144059 SOFTWARE7 2",176,176

my3.bin,"9607776f 6788372","20030612.144059 QUALITY2 4",137,34901

$ csv_kppp -2 <../../taglister/docommatiny2.csv

Test 2: cvsgetbodyline and csvfieldbyname

line = `my1.bin,"3941989e 8259837","20030612.144059 QUALITY2 4",176,176'

field[FileName ] = `my1.bin'

field[MagicWandCRC32 ] = `3941989e 8259837'

field[MagicWandUniqueID ] = `20030612.144059 QUALITY2 4'

field[Junk ] = `(null)'

field[FlashManId ] = `176'

field[FlashDevId ] = `176'

line = `my2.bin,"3bb3973b 5725820","20030612.144059 SOFTWARE7 2",176,176'

field[FileName ] = `my2.bin'

field[MagicWandCRC32 ] = `3bb3973b 5725820'

field[MagicWandUniqueID ] = `20030612.144059 SOFTWARE7 2'

field[Junk ] = `(null)'

field[FlashManId ] = `176'

field[FlashDevId ] = `176'

line = `my3.bin,"9607776f 6788372","20030612.144059 QUALITY2 4",137,34901'

field[FileName ] = `my3.bin'

field[MagicWandCRC32 ] = `9607776f 6788372'

field[MagicWandUniqueID ] = `20030612.144059 QUALITY2 4'

field[Junk ] = `(null)'

field[FlashManId ] = `137'

field[FlashDevId ] = `34901'

alflb_20120306.odt © 2002-2012 Alf Lacis Page 31 of 145

Page 32: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

11 Compile-Time AssertsCOMPILE_TIME_ASSERT, FILE_SCOPED_COMPILE_TIME_ASSERT

Copyright - none was expressed by the author & respondents, Niall Murphy, Bill Emsholl & John Carter, on this page: http://www.panelsoft.com/murphyslaw/apr01.htm.20070907 After correspondence with Niall Murphy [nmurphy at panelsoft dot com], I have added a description_as_variable_name to generate the variable name containing the assert-error in English.

11.1 SynopsisThese two macros provide the ability to raise errors at compile time. Some errors are best handled at compile time rather than letting the application be installed in an end-user system.

11.2 Usage#include "cassert.h"

void COMPILE_TIME_ASSERT(

expression_that_must_be_true,

description_as_variable_name)

Returns:

Compile-time assert to be used within a function.True expression, else a compiler error is generated.Description as a variable name.No return.

void FILE_SCOPED_COMPILE_TIME_ASSERT(

expression_that_must_be_true

description_as_variable_name)

Returns:

File-scoped compile-time assert to be used outside functions.True expression, else a compiler error is generated.Description as a variable name.No return.

11.3 ExampleTwo examples of FILE_SCOPED_COMPILE_TIME_ASSERT, and three examples of COMPILE_TIME_ASSERT, two of which are used in C conditional expressions:

#include <stdio.h>

#include "cassert.h"

FILE_SCOPED_COMPILE_TIME_ASSERT(sizeof(int)==4, sizeof_int_should_be_4);

FILE_SCOPED_COMPILE_TIME_ASSERT(sizeof(char)==2, sizeof_char_is_not_2); // assert failure

int main(void)

{

COMPILE_TIME_ASSERT(sizeof(int)==4, sizeof_int_must_be_4);

if(1)

COMPILE_TIME_ASSERT(1, does_not_fail_here);

else

printf("Foo\n");

if(0)

COMPILE_TIME_ASSERT(0, expression_not_true); // Compiler whinges.

else

printf("Foo\n");

return 0;

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 32 of 145

Page 33: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

11.4 Output of ExampleTwo examples of FILE_SCOPED_COMPILE_TIME_ASSERT, and three examples of COMPILE_TIME_ASSERT, two of which are used in C conditional expressions:

$ gcc -Wall -o assert_test assert_test.c

assert_test.c:7: error: size of array `ASSERT_FAILURE____sizeof_char_is_not_2' is negative

assert_test.c: In function `main':

assert_test.c:18: error: size of array `ASSERT_FAILURE____expression_not_true' is negative

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 33 of 145

Page 34: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

12 C-String and Debug-String FunctionsThese two suites of functions are complementary, and perform functions the inverse of the other group. The C-String and Debug String functions were written fifteen years apart, so there are some style differences.

12.1 Convert C-String Escape Sequences (like a C Compiler)ezi_esc, ConvertEscapeSequencesSafe

The central functionality of this suite was based on ideas but not the code in the GNU C Compiler, version 2.95.3, mirrored at mirror.aarnet.edu.au\pub\gcc\releases\gcc-2.95.3 (as at 12/11/'02).

12.1.1 Synopsis

These routines emulate the way that C Compilers convert escape sequences in C source code to byte values.

The backslash character (\) is used to introduce an escape sequence, which allows the visual representation of certain non-graphic characters. For example, the two characters \ and n are used to represent the single newline character.

A backslash is used with octal or hexadecimal numbers to represent the ASCII symbol or control code corresponding to that value; for example, \03 for Ctrl-C or \x3F for the question mark. You can use any string of up to three octal or two hexadecimal numbers in an escape sequence, provided that the value is in the range 0 to 0xff.

Larger numbers do not generate an error, but the conversion stops before the number exceeds 0xff. For example, the 4-character sequence representing the octal number \456 is larger than the maximum value allowed (\377) and will generate the two bytes 0x25 0x36 (0x25 is \45, and 0x36 is the character '6').

Similarly, the first non-octal or non-hexadecimal character encountered in an octal or hexadecimal escape sequence marks the end of the sequence.

The following table shows the available escape sequences. Note: You must use \\ to represent a single ASCII backslash:

Sequence Value Char What it does

======== ======== ======== ===============

\a 0x07 BEL Audible bell

\b 0x08 BS Backspace

\f 0x0C FF Formfeed

\n 0x0A LF Newline (linefeed)

\r 0x0D CR Carriage return

\t 0x09 HT Tab (horizontal)

\v 0x0B VT Vertical tab

\\ 0x5c \ Backslash

\' 0x27 ' Single quote (apostrophe)

\" 0x22 " Double quote

\? 0x3F ? Question mark

\O any O=a string of up to three octal digits

\xH any H=a string of hex digits

\XH any H=a string of hex digits

The input string is an ASCII formatted string. Although not enforced, the input string typically contains the characters space to tilde (0x20 to 0x7e). The trailing '\0' in the input string terminates the routine.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 34 of 145

Page 35: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

A trailing '\0' is appended for ezi_esc, but not for ConvertEscapeSequencesSafe, so if you need this behaviour, use Output[OutLen] = '\0' immediately following the call to this function.

In the case where a '\' exists in the input string, and the next character does not match one of the above, for example '\w', the next character ('w') is stored verbatim into the output string.

Typically, an output string will always be the same size or smaller than the input string.

12.1.2 Usage

#include "alflb.h"

EZISTR_T *ezi_esc(

EZISTR_T *to,

EZISTR_T *from);

Converts C-escaped string to a normal string or binary data. Inverse of ezi_dbg.Ezi-strings for both source and destination.

char *

ConvertEscapeSequencesSafe(

char *cOutput,

size_t *OutLen,

size_t max,

char *cIn);

Returns:

Non-ezi-string version.Output stringPointer to returned length of output stringsize of output string variableInput data to be converted.A copy of the cOutput pointer.

12.1.3 Example

Compile the standalone test application in convescs.c, and run it on an input file, here called straight_ascii.txt, and pipe it to an output file, here called binary.txt:

$ gcc -Wall -o convescs -DEZI_DBG_MAX=35 ezi_str.c strncpyn.c -DTEST_APP_CONVESCS convescs.c

$ od -t x1z -Ax straight_ascii.txt

000000 5c 5c 20 5c 39 20 5c 30 37 20 5c 37 20 5c 35 0a >\\ \9 \07 \7 \5.<

000010 5c 30 30 37 20 5c 30 37 20 5c 37 20 78 78 78 0a >\007 \07 \7 xxx.<

000020 5c 6e 20 5c 72 20 5c 74 20 78 78 78 78 78 78 0a >\n \r \t xxxxxx.<

000030 5c 78 32 61 20 5c 58 32 42 20 20 20 5c 58 44 0a >\x2a \X2B \XD.<

000040 5c 77 20 64 6f 6e 74 20 63 6f 6e 76 65 72 74 0a >\w dont convert.<

000050

$ ./convescs straight_ascii.txt >binary.txt

$ od -t x1z -Ax binary.txt

000000 5c 20 39 20 07 20 07 20 05 0a 07 20 07 20 07 20 >\ 9 . . ... . . <

000010 78 78 78 0a 0a 20 0d 20 09 20 78 78 78 78 78 78 >xxx.. . . xxxxxx<

000020 0a 2a 20 2b 20 20 20 0d 0a 77 20 64 6f 6e 74 20 >.* + ..w dont <

000030 63 6f 6e 76 65 72 74 0a >convert.<

000038

$

12.2 Debug String Routinesezi_dbg, d_string_safe, d_string_always_convert, d_string_special, d_string_fmt

These functions also perform the inverse operation to the suite of C-String functions, see above, with the appropriate formats, see below.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 35 of 145

Page 36: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

12.2.1 Synopsis

These functions provide ways to visualize a chunk of memory. They provide conversions for non-printing characters.

The formats can be used with C-Compilers, or with my ezi_esc/ConvertEscapeSequencesSafe suite of functions, see above.

Note that the flags set by the accessor functions d_string_always_convert, d_string_special & d_string_fmt are not thread-safe, although typically these remain the same per target binary.

12.2.2 Small, Simple Version

If d_string.c is compiled with the compiler flag D_STRING_SIMPLE set to 1, i.e., -DD_STRING_SIMPLE=1, then the d_string suite does not use sprintf, which may represent a considerable saving in a limited-memory target environment. In this case the octal and hex formats are fixed width: 3 and 2 digits, eg: \005 and \x05, not \5 & \x5. The library uses reversen, ultoa_direction and the array hex36[] to provide this smaller functionality: see elsewhere in this document. If hex36.c is compiled with HEX36LOWERCASE defined, then the hex digits will be a-f, not A-F.

12.2.3 Usage

#include "alflb.h"

EZISTR_T *ezi_dbg(

EZISTR_T *to,

EZISTR_T *from);

Returns:

Converts normal string or binary data to a C-escaped string. Inverse of ezi_esc.

A copy of the to pointer.

EZISTR_T *ezi_dbg_raw(

EZISTR_T *to,

void *from,

size_t from_len);

Returns:

Converts normal raw string or raw binary data to a C-escaped string. Inverse of ezi_esc.

A copy of the to pointer.

char *d_string_safe(

char *out,

size_t *out_len,

size_t max,

void *vin,

size_t length);

Returns: A copy of the out pointer.

int d_string_always_convert(

int new_flag);

Returns:

Set the always-convert-to-an-escaped-string flag.Value can be 0==off, <non-zero>==on.Old value if you want it.

int d_string_special(

int new_flag);

Returns:

Set the special characters flag. Default is 1: to print special characters such as "\r\n" instead of "\015\012".Value can be 0==off, <non-zero>==on.Old value if you want it.

void d_string_fmt(

int format_offset);

Returns:

A number describing the format. Use one of these enums:D_STRING_OCTAL gives "Hello\5\r\nWorld\377\r\n"

D_STRING_HEX gives "Hello\x5\r\nWorld\xFF\r\n"

void

alflb_20120306.odt © 2002-2012 Alf Lacis Page 36 of 145

Page 37: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

12.2.4 Example

Test application is:

int main(int argc, char *argv[])

{

#define TESTMAX 200

char fmt[] = "%d \"%s\"\n";

// 0123456789012345678901234

EZISTRBASIC(Aaa, "World##############Helllo");

EZISTREMPTY(tempbuf, TESTMAX);

int ii;

Aaa->str[ 6] = 0x07;

Aaa->str[ 7] = 0x08;

Aaa->str[ 8] = 0x09;

Aaa->str[ 9] = 0x0A;

Aaa->str[10] = 0x0B;

Aaa->str[11] = 0x0C;

Aaa->str[12] = 0x0D;

Aaa->str[13] = 0x0E;

Aaa->str[14] = 0244;

Aaa->str[15] = '\'';

Aaa->str[16] = '"';

Aaa->str[17] = '\\';

printf("d_string test app: "__DATE__" "__TIME__" sizeof(Aaa) = %d\n", sizeof(Aaa));

printf("\n");

for ( ii = 0; ii < D_STRING_LAST_FMT; ii++ )

{

d_string_fmt(ii); ezi_dbg(tempbuf, Aaa); printf(fmt, d_string_fmt_flag, tempbuf->str);

}

printf("\n");

d_string_special(0);

for ( ii = 0; ii < D_STRING_LAST_FMT; ii++ )

{

d_string_fmt(ii); ezi_dbg(tempbuf, Aaa); printf(fmt, d_string_fmt_flag, tempbuf->str);

}

printf("\n");

memset(&Aaa->str[6], 0, 12 );

d_string_special(1);

for ( ii = 0; ii < D_STRING_LAST_FMT; ii++ )

{

d_string_fmt(ii); ezi_dbg(tempbuf, Aaa); printf(fmt, d_string_fmt_flag, tempbuf->str);

}

printf("\n");

memset(&Aaa->str[6], 0, 12 );

d_string_special(0);

for ( ii = 0; ii < D_STRING_LAST_FMT; ii++ )

{

d_string_fmt(ii); ezi_dbg(tempbuf, Aaa); printf(fmt, d_string_fmt_flag, tempbuf->str);

}

return 0;

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 37 of 145

Page 38: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

12.2.5 Output

This is the test app compiled ordinarily, and then using D_STRING_SIMPLE:

$ gcc -Wall -o d_string ezi_str.c strncpyn.c -DD_STRING_TEST_APP d_string.c

$ ./d_string

d_string test app: Apr 25 2008 13:46:14 sizeof(Aaa) = 4

0 "World#\a\b\t\n\v\f\r\16\244'\"\\#Helllo"

1 "World#\a\b\t\n\v\f\r\xe\xa4'\"\\#Helllo"

0 "World#\7\10\11\12\13\14\15\16\244'\"\\#Helllo"

1 "World#\x7\x8\x9\xa\xb\xc\xd\xe\xa4'\"\\#Helllo"

0 "World#\0\0\0\0\0\0\0\0\0\0\0\0#Helllo"

1 "World#\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0#Helllo"

0 "World#\0\0\0\0\0\0\0\0\0\0\0\0#Helllo"

1 "World#\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0#Helllo"

$ gcc -Wall -o d_string_simple ezi_str.c strncpyn.c simple_itoa.c reversen.c hex36.c

-DD_STRING_SIMPLE -DD_STRING_TEST_APP d_string.c

$ ./d_string_simple

d_string test app: Apr 25 2008 13:48:58 sizeof(Aaa) = 4

0 "World#\a\b\t\n\v\f\r\016\244'\"\\#Helllo"

1 "World#\a\b\t\n\v\f\r\x0E\xA4'\"\\#Helllo"

0 "World#\007\010\011\012\013\014\015\016\244'\"\\#Helllo"

1 "World#\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\xA4'\"\\#Helllo"

0 "World#\000\000\000\000\000\000\000\000\000\000\000\000#Helllo"

1 "World#\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#Helllo"

0 "World#\000\000\000\000\000\000\000\000\000\000\000\000#Helllo"

1 "World#\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#Helllo"

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 38 of 145

Page 39: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

13 Cyclic Redundancy Check Functionsbytewisecrc16, bytewisecrc32

13.1 SynopsisThese functions calculate the 16-bit and 32-bit CRC based on the following 17-bit and 33-bit polynomials.

From Perez's article Byte-wise CRC Calculations IEEE MICRO, June 1983, plus follow-up Letters To The Editor. 16-bit Table data from an article by David Schwaderer in the April 1985 issue of PC Tech Journal.

17-bit polynomial is:

X16+X15+X2+X0

X16+X12+X5+X0 <<< compare with CCITT version

33-bit polynomial is:

X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0

13.2 Usage#include "alflb.h"

unsigned short bytewisecrc16(

unsigned short *crc_in_out,

unsigned char *data,

size_t length);

Returns:

Calculates 16-bit CRC using the above 17-bit polynomial.Address of CRC, passed in and updated.

Copy of resulting CRC.

unsigned long bytewisecrc32(

unsigned long *crc_in_out,

unsigned char *data,

size_t length);

Returns:

Calculates 32-bit CRC using the above 33-bit polynomial.Address of CRC, passed in and updated.

Copy of resulting CRC.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 39 of 145

Page 40: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

13.3 Example#include "alflb.h"

static EZI_EFS_CRC_T ezi_efs_crc(EZI_EFS_CRC_T *pcrc_in_out, UCHAR *data, EZI_EFS_SIZE_T len)

{

#if EZI_EFS_CRC_BYTES == 4

#if defined(__BORLANDC__) || defined(__GNUC__) // PC application or GNU compiler

bytewisecrc32(pcrc_in_out, data, (size_t) len); // Alf's bytewise 32-bit CRC calc

#else

#error A platform-specific 32-bit CRC algorithm must be called here.

#endif

#elif EZI_EFS_CRC_BYTES == 2

#if defined(__BORLANDC__) || defined(__GNUC__) // PC application or GNU compiler

bytewisecrc16(pcrc_in_out, data, (size_t) len); // Alf's bytewise 16-bit CRC calc

#else

#error A platform-specific 16-bit CRC algorithm must be called here.

#endif

#else

#error EZI_EFS_CRC_BYTES must be set to either 4 or 2.

#endif

// If the CRC just happens to be the 'format' pattern, replace it with the bit-wise inverse.

// This is because the 'format' pattern is used to denote 'file does not exist'.

if ( EZI_EFS_DISALLOW_CRC == *pcrc_in_out )

{

*pcrc_in_out = (EZI_EFS_CRC_T)(~ EZI_EFS_DISALLOW_CRC);

}

return *pcrc_in_out;

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 40 of 145

Page 41: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

14 File Date - datethisLabwindows/CVI only.

14.1 SynopsisThis function provides the date of a file as a string <yymmdd.hhmmss>. Deprecated for new code: use the Sortable Date/Time String Routines given below.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 41 of 145

Page 42: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

15 Date/Time String Routines - Sortable Format

15.1 SynopsisProvides several routines which format the Date and/or Time, using the Swedish format ofyyyy-mm-dd hh:mm:ss. Note: these function are not thread-safe.

15.2 Usage#include "alflb.h"

char *SortableDateTimeStr(

int time_too)

Returns:

Gets the current date & time from the OS, and formats it.TRUE or FALSE to include the time (as well as the date).A pointer to an internal static string. String format is:

0 1

0123456789012345678

===================

time_too FALSE => yyyy-mm-dd (do not forget '\0's)time_too TRUE => yyyy-mm-dd hh:mm:ss

char *SortableDateTimeStrTS(

TimeStamp *ts);

Returns:

As above, but the time is passed to the routine in the structure ts.Pointer to TimeStamp structure (contains separate values for year, month, day, hour, minute & second).As above.

char *SortableTimeStrTS(

TimeStamp *ts);

Returns:

As for SortableDateTimeStrTS, but only formats the time.Pointer as for SortableDateTimeStrTS.Pointer to an internal static string.

TimeStamp *GetDateTimeStamp(

TimeStamp *ts);

Returns:

Gets the current date & time from the OS into a TimeStamp structure.Pointer as for SortableDateTimeStrTS.Returns address of ts (useful if you want to embed this call).

TimeStamp *ElapsedTime24Hr(

TimeStamp *Start,

TimeStamp *End);

Returns:

Calculates time difference between two TimeStamp structures -- UP TO 24 HOURS ONLY.

Pointer to internal static TimeStamp structure containing difference between two times -- ONLY APPLICABLE UP TO 24 HOURS.

char *CompressedDateTimeStr(

void);

Returns:

Returns the current date & time in compressed, sortable format, ie, YYYYMMDD.hhmmss\0

Pointer to string, eg: 20031013.134459\0

alflb_20120306.odt © 2002-2012 Alf Lacis Page 42 of 145

Page 43: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

16 Directory Path Make - mkdirhierLabWindows/CVI and Borland C++ only:

mkdirhier

16.1 SynopsisThis function recursively creates a directory path. For example,

error = mkdirhier("C:\\temp\\MySuite\\MyApp");

would make the directories (if they did not exist) "temp", "MySuite" and "MyApp".

16.2 Usage#include "alflb.h"

int mkdirhier(

char *dirname)

Returns:

the path as a string.0 on success, any other value indicates an error

16.3 Examplechar WorkingPath[] = "c:\\temp\\flahs\\upgrader\\";

if ( 0 != (error = mkdirhier(WorkingPath)) )

return -1;

alflb_20120306.odt © 2002-2012 Alf Lacis Page 43 of 145

Page 44: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

17 Display a numeric string with commas - i_commas

17.1 SynopsisThis routine is especially useful where you want to display large numeric values with commas to help the human reader break up the values into thousands, millions, etc. Unused comma positions to the left of the number are replaced with spaces.

17.2 Usage#include "alflb.h"

char *i_commas(

char * out,

int outlen,

char * in,

char comma);

Returns:

Function to insert commas into a string depicting a numberDestination stringmaximum length of output stringInput stringCharacter to use as comma, typically ',' or '.'.Copy of address of Destination String

17.3 ExampleIf in[] is " 123456789"

then: printf("%s\n", i_commas(out, sizeof(out-1), in, ','));

out is " 123,456,789"

alflb_20120306.odt © 2002-2012 Alf Lacis Page 44 of 145

Page 45: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

18 Do Loop Statement - DOLOOP

18.1 SynopsisThis macro implements the equivalent of a Fortran do-loop. The macro was designed so that the same kind of functionality is available as per the Fortran equivalent, including automatic direction adjustment (i.e., increasing or decreasing loop variable). This kind of loop structure is useful, because it is different from anything else that C offers. However, you can still use break to terminate the loop early.

Because the arguments are typeless, you are not restricted to integers: you can use longs, floats, doubles, etc.

WARNING on the terminating test: this is "less than or equal to" (or "greater than or equal to" depending on direction). Simply put, this means we include the last value in the loop. E.g., in DOLOOP(a,0,10,1), the loop is executed 11 times (unless we break earlier).

18.2 Usage#include "alflb.h"

DOLOOP(

loop_var,

from,

to,

step)

Returns:

Note that there is no type associated with DOLOOP and its parameters. Being a macro, the arguments are whatever type the programmer wishes.this is effectively the loop variablethe first value that the loop variable is set tothe last value that the loop variable is set tothis is the increment or step for the loop. It can be positive or negative!No return. This is a replacement for the C statement for.

18.3 ExampleOriginal Fortran code:

COMMENT 'STEP' CAN BE +VE OR -VE

DO 600 POS = FIRST, LAST, STEP

CALL SGET ( STRING, POS, TEMPRY )

. . .

600 CONTINUE

Equivalent C code using the DOLOOP macro:

/* step can be +ve or -ve */

DOLOOP(pos, first, last, step)

{

tempry = string[pos];

. . .

}

18.4 BugAs for any macro, beware of side-effects in macro expansion. I have prevented some side-effects, but not all, by using lots of parentheses. Similar warnings as for common macros like MIN and MAX should be heeded. Here is the code for DOLOOP, so you can check for possible side-effects:

#define DOLOOP(a,b,c,d) for(a=(b); (d)>0?(a)<=(c):(a)>=(c); a+=(d))

alflb_20120306.odt © 2002-2012 Alf Lacis Page 45 of 145

Page 46: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

19 Error Check and Return MacrosGotoErrorCheck, GotoErrorSet, GotoStatusCheck, GotoErrorCheckCat, GotoErrorCheckCatEzi,

ReturnErrorCheck, ReturnErrorSet, ReturnStatusCheck, ReturnErrorCheckCat,

ReturnErrorCheckCatEzi

19.1 SynopsisThis suite provides a consistent way of handling error or status returns, and provides a consistent way of bailing-out of a group of calls, which might otherwise require long jumps, bare gotos, or other mechanisms.

The xxxCatxxx macros also provide the analogy of a run-time stack trace, where an error trace can propagate back up through deeply nested functions, with a concatenated list of locations created in ErrMessPtr or EziErrMessPtr. Typically catenate is 0 (FALSE) for the lowest level call, and non-zero (TRUE) for all other calls.

All macros need to update the variable error, so this must be available as a local or global variable.

To use the GotoXxx macros, there needs to be a label Error:, typically at the bottom of your function where the GotoXxx macros are used. See the examples for clarification.

19.2 Usage#include "errorcheck.h"

<void> GotoErrorCheck(

MatchCode,

Fcall)

Set error to the function call Fcall return value, and if it does not match the required value MatchCode, then go to the Error: label.

<void> GotoErrorSet(

SetThisError,

MatchCode,

Fcall)

Similar to GotoErrorCheck, except that if the function call Fcall return value does not match the required value MatchCode, then set error to SetThisError before going to the Error label.

<void> GotoStatusCheck(

MatchCode,

Fcall)

Similar to GotoErrorCheck, except that the assignment error = (Fcall) is wrappered with the function or macro EVENT_STATUS, i.e., EVENT_STATUS(error = (Fcall)).

<void> GotoErrorCheckCat(

MatchCode,

Fcall,

ErrMessPtr,

ErrMess,

catenate)

Similar to GotoErrorCheck, except the string ErrMessPtr has ErrMess concatenated if the function call Fcall return value does not match the required value MatchCode. Uses sprintf and strlen to provide this capability.

<void>

GotoErrorCheckCatEzi(

MatchCode,

FCall,

EziErrMessPtr,

ErrMess,

catenate)

Similar to GotoErrorCheck, except the concatenated destination string is an Ezi-String (see elsewhere in this document), and does not use sprintf and strlen, but ezi_cat_raw and ezi_cpy_raw.

<void> ReturnErrorCheck(

MatchCode,

Fcall)

Set error to the function call Fcall return value, and if it does not match the required value MatchCode, then return with this error value.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 46 of 145

Page 47: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

<void> ReturnErrorSet(

SetThisError,

MatchCode,

Fcall)

Similar to ReturnErrorCheck, except that if the function call Fcall return value does not match the required value MatchCode, then set error to SetThisError before returning this value.

<void> ReturnStatusCheck(

MatchCode,

Fcall)

Similar to ReturnErrorCheck, except that the assignment error = (Fcall) is wrappered with the function or macro EVENT_STATUS, i.e., EVENT_STATUS(error = (Fcall)).

<void>

ReturnErrorCheckCat(

MatchCode,

FCall,

ErrMessPtr,

ErrMess,

catenate)

Similar to ReturnErrorCheck, except the string ErrMessPtr has ErrMess concatenated if the function call Fcall return value does not match the required value MatchCode. Uses sprintf and strlen to provide this capability.

<void>

ReturnErrorCheckCatEzi(

MatchCode,

FCall,

EziErrMessPtr,

ErrMess,

catenate)

Similar to ReturnErrorCheck, except the concatenated destination string is an Ezi-String (see elsewhere in this document), and does not use sprintf and strlen, but ezi_cat_raw and ezi_cpy_raw.

19.3 BugsAs for any macros, beware of side-effects in macro expansion. Similar warnings as for common macros like MIN and MAX should be heeded.

19.4 GotoXxx ExampleThis example has been taken from real life, but much non-example code has been stripped, and the function and variable names have been changed.

int DevOnDemandInit( void )

{

int error;

ezi_cpy_raw(devOnDemandIdSave, "error reading DEV");

GotoErrorCheck(0, dev_comms(dev_addr, "VERSION" , answer))

if ( answer->len )

ezi_cpy(version, answer);

GotoErrorCheck(0, dev_comms(dev_addr, "COM1,9600,8,N,1", answer))

GotoErrorCheck(0, dev_comms(dev_addr, "DTR=ON" , answer))

GotoErrorCheck(0, dev_comms(dev_addr, "ECHO=OFF" , answer))

GotoErrorCheck(0, dev_comms(dev_addr, "GETID" , answer))

if ( answer->len )

ezi_cpy(devOnDemandIdSave, answer);

devOnDemandAccOk = 0;

Error: // fall through.....

devOnDemandState = IDLE;

if ( error || answer->str[0] )

{

trace("Device DEV returned error=%d, string=%s\r\n", error, answer->str);

}

return error;

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 47 of 145

Page 48: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

19.5 ReturnXxx ExampleThis example has been taken from real life, but much non-example code has been stripped, and the function and variable names have been changed.

static int Panel(int icon, char *title, char *msg, char *errStr)

{

int error = -1;

int panel = -1;

...

ReturnErrorCheckCat(-1, (panel = LoadPanel(0, "panel.dat", PANEL)),

errStr, "LoadPanel", 0);

ReturnErrorCheckCat(-1, SetAttr (panel, TITLE, title ), errStr, "SetAttr", 0);

ReturnErrorCheckCat(-1, ResetBox(panel, TEXT , "" ), errStr, "ResetBox", 0);

ReturnErrorCheckCat(-1, SetCtrl (panel, ICON , VISIBLE), errStr, "SetCtrl" , 0);

...

DisplayPanel(panel);

RunInterface();

DiscardPanel(panel);

return proceed;

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 48 of 145

Page 49: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

20 Ezi Endian Byte TransposalEZI_ENDIAN_COPY, EZI_ENDIAN_SITU, ezi_endian

20.1 SynopsisThis suite provides endian transposal for both 2-byte(ANSI short) and 4-byte(ANSI long) values. The intention is that the normal API consists of the two wrapper macros, EZI_ENDIAN_COPY and EZI_ENDIAN_SITU, defined in ezi_endian.h, i.e., not to use ezi_endian directly, although that is not prohibited.

To simplify your code, the macros provide useful casting to the required types, and in the case of EZI_ENDIAN_COPY, ensures (via a compile-time assert) that the output and input variables are of the same size.

Depending on the macro, the bytes are copied to a new variable, or swapped in situ (in place).

20.2 Usage#include "ezi_endian.h"

void EZI_ENDIAN_SITU(

<2 or 4 byte signed

or unsigned integer>

variable)

Transpose the 2 or 4-byte integer in situ (in place).Note that the specifies the variable by name, not by address.

void EZI_ENDIAN_COPY(

<2 or 4 byte signed

or unsigned integer>

out_variable,

<2 or 4 byte signed

or unsigned integer>

in_variable)

Copy the transposed 2 or 4-byte integer to the output variable.The output variable. Note that the macro specifies both variables by name, not by address.

The input variable. If the size of the two variables disagrees, then a compile-time error is generated.

void ezi_endian(

UCHAR *out_variable,

UCHAR *in_variable,

size_t size)

The address of the output variable, cast as a pointer to a UCHAR array.The address of the input variable, cast as a pointer to an UCHAR array.The size of the output variable.

20.3 BugsAs for any macros, beware of side-effects in macro expansion. Similar warnings as for common macros like MIN and MAX should be heeded.

Since the variables in the macros are passed by value, which then have their addresses taken in the macros, you cannot use these macros with functions in the data positions. I.e., this will not work:

EZI_ENDIAN_COPY(some_time, timenow()); // WRONG!

In this case, the endian swap has to proceed in two statements via an intermediate variable:

my_time = timenow(); // OK.

EZI_ENDIAN_COPY(some_time, my_time); // OK.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 49 of 145

Page 50: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

20.4 ExampleTo build a test application, compile ezi_endian.c with this command line:

$ gcc -DTEST_APP_EZI_ENDIAN=1 -Wall -o ezi_endian ezi_endian.c

The test application from ezi_endian.c is:

int main(int argc, char *argv[])

{

long rsl, sl = 0x87654321;

short rss, ss = 0x8765;

ULONG rul, ul = 0x87654321;

USHORT rus, us = 0x8765;

EZI_ENDIAN_COPY(rsl, sl);

EZI_ENDIAN_COPY(rss, ss);

EZI_ENDIAN_COPY(rul, ul);

EZI_ENDIAN_COPY(rus, us);

printf("COPY:...\n");

printf(" signed long 0x%lX -> 0x%lX\n", sl, rsl);

printf(" signed short 0x%X -> 0x%X\n" , ss, rss);

printf("unsigned long 0x%lX -> 0x%lX\n", ul, rul);

printf("unsigned short 0x%X -> 0x%X\n" , us, rus);

EZI_ENDIAN_SITU(sl);

EZI_ENDIAN_SITU(ss);

EZI_ENDIAN_SITU(ul);

EZI_ENDIAN_SITU(us);

printf("IN SITU:...\n");

printf(" signed long 0x%lX\n", sl);

printf(" signed short 0x%X \n", ss);

printf("unsigned long 0x%lX\n", ul);

printf("unsigned short 0x%X \n", us);

EZI_ENDIAN_COPY(rsl, sl);

EZI_ENDIAN_COPY(rss, ss);

EZI_ENDIAN_COPY(rul, ul);

EZI_ENDIAN_COPY(rus, us);

printf("COPY:...\n");

printf(" signed long 0x%lX -> 0x%lX\n", sl, rsl);

printf(" signed short 0x%X -> 0x%X\n" , ss, rss);

printf("unsigned long 0x%lX -> 0x%lX\n", ul, rul);

printf("unsigned short 0x%X -> 0x%X\n" , us, rus);

EZI_ENDIAN_SITU(sl);

EZI_ENDIAN_SITU(ss);

EZI_ENDIAN_SITU(ul);

EZI_ENDIAN_SITU(us);

printf("IN SITU:...\n");

printf(" signed long 0x%lX\n", sl);

printf(" signed short 0x%X \n", ss);

printf("unsigned long 0x%lX\n", ul);

printf("unsigned short 0x%X \n", us);

return 0;

}

#endif

alflb_20120306.odt © 2002-2012 Alf Lacis Page 50 of 145

Page 51: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

20.5 Output from the Example$ ./ezi_endian

COPY:...

signed long 0x87654321 -> 0x21436587

signed short 0xFFFF8765 -> 0x6587

unsigned long 0x87654321 -> 0x21436587

unsigned short 0x8765 -> 0x6587

IN SITU:...

signed long 0x21436587

signed short 0x6587

unsigned long 0x21436587

unsigned short 0x6587

COPY:...

signed long 0x21436587 -> 0x87654321

signed short 0x6587 -> 0xFFFF8765

unsigned long 0x21436587 -> 0x87654321

unsigned short 0x6587 -> 0x8765

IN SITU:...

signed long 0x87654321

signed short 0xFFFF8765

unsigned long 0x87654321

unsigned short 0x8765

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 51 of 145

Page 52: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

21 File Descriptor Set Operationsfd_set_or(), fd_set_and()

21.1 SynopsisThese routines provide a way of 'OR'ing or 'AND'ing two 'file descriptor sets' of type fd_set. fd_sets are used for sockets and files in POSIX-like systems and sockets in Windows.

fd_set_and() 'AND's two fd_sets together.

fd_set_or() 'OR's two fd_sets together.

These work regardless of whether the fd_sets are Unix-style (bit array) or Windows (struct containing a count plus an int array). The fd_set output can be one of the input fd_sets. The Unix versions simply use the bitwise '&' or '|' operator. The Windows versions of these functions do this by mallocing a temporary buffer & replacing output at the end of the function. The fd_set output can be a NULL pointer, in which case only the 1/0 output of the function is returned.

ASSUMPTION: that 'output' is large enough to contain the result.

21.2 Usage#include "fd_set_ops.h"

int fd_set_and( Perform a logical 'AND' of two fd_sets. fd_set *output, Output fd_set, may also be NULL or either of the two inputs. size_t num_elements, Number of elements in the sets: this is typically FD_SETSIZE. fd_set *left, One input fd_set. fd_set *right); The other input fd_set. Returns: 1 if the 'AND' set has at least one value, 0 otherwise.

int fd_set_or( Perform a logical 'OR' of two fd_sets. fd_set *output, Output fd_set, may also be NULL or either of the two inputs. size_t num_elements, Number of elements in the sets: this is typically FD_SETSIZE. fd_set *left, One input fd_set. fd_set *right); The other input fd_set. Returns: 1 if the 'OR' set has at least one value, 0 otherwise.

21.3 ExampleHere's the test app from the source code:void pfd(char *name, fd_set *obj) { size_t ii; printf("%s=", name); if ( obj == NULL ) printf("<nul>"); else for ( ii = 0; ii < 32; ii++ ) if ( FD_ISSET(ii, obj)) printf("%u ", ii); }

int main(int argc, char **argv) { int res; fd_set left; fd_set right; fd_set output;

FD_ZERO(&left); FD_ZERO(&right); FD_SET(11, &left); FD_SET(17, &left); FD_SET(31, &left);

alflb_20120306.odt © 2002-2012 Alf Lacis Page 52 of 145

Page 53: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

FD_SET(9 , &right); FD_SET(17, &right); FD_SET(30, &right); FD_ZERO(&output); res = fd_set_or(&output, FD_SETSIZE, &left, &right); pfd("OR:separate output: left", &left); pfd(" right", &right); pfd(" ORd", &output); printf(" result=%d\n", res); res = fd_set_or(NULL, FD_SETSIZE, &left, &right); pfd("OR:NULL output: left", &left); pfd(" right", &right); pfd(" ORd", NULL); printf(" result=%d\n", res); res = fd_set_or(&left, FD_SETSIZE, &left, &right); pfd("OR:output==left: left<<", &left); pfd(" right", &right); printf(" result=%d\n", res); res = fd_set_or(&right, FD_SETSIZE, &left, &right); pfd("OR:output==right: left", &left); pfd(" right<<", &right); printf(" result=%d\n\n", res);

FD_ZERO(&left); FD_ZERO(&right); res = fd_set_or(&left, FD_SETSIZE, &left, &right); pfd("OR:output==left: left<<", &left); pfd(" right", &right); printf(" result=%d\n", res); res = fd_set_or(&right, FD_SETSIZE, &left, &right); pfd("OR:output==right: left", &left); pfd(" right<<", &right); printf(" result=%d\n\n", res);

FD_ZERO(&left); FD_ZERO(&right); FD_SET(11, &left); FD_SET(17, &left); FD_SET(31, &left); FD_SET(9 , &right); FD_SET(17, &right); FD_SET(30, &right); FD_ZERO(&output); res = fd_set_and(&output, FD_SETSIZE, &left, &right); pfd("AND:separate output: left", &left); pfd(" right", &right); pfd(" ANDd", &output); printf(" result=%d\n", res); res = fd_set_and(NULL, FD_SETSIZE, &left, &right); pfd("AND:NULL output: left", &left); pfd(" right", &right); pfd(" ANDd", NULL); printf(" result=%d\n", res); res = fd_set_and(&left, FD_SETSIZE, &left, &right); pfd("AND:output==left: left<<", &left); pfd(" right", &right); printf(" result=%d\n", res); res = fd_set_and(&right, FD_SETSIZE, &left, &right); pfd("AND:output==right: left", &left); pfd(" right<<", &right); printf(" result=%d\n\n", res);

FD_ZERO(&left); FD_SET(9 , &right); FD_SET(17, &right); FD_SET(30, &right); res = fd_set_and(&left, FD_SETSIZE, &left, &right); pfd("AND:output==left: left<<", &left); pfd(" right", &right); printf(" result=%d\n", res); res = fd_set_and(&right, FD_SETSIZE, &left, &right); pfd("AND:output==right: left", &left); pfd(" right<<", &right); printf(" result=%d\n\n", res); return 0; }

Compile and run as shown:$ gcc -Wall -DFD_TEST_APP -o test_fd_set_ops fd_set_ops.c

$ ./test_fd_set_ops OR:separate output: left=11 17 31 right=9 17 30 ORd=9 11 17 30 31 result=1 OR:NULL output: left=11 17 31 right=9 17 30 ORd=<nul> result=1 OR:output==left: left<<=9 11 17 30 31 right=9 17 30 result=1 OR:output==right: left=9 11 17 30 31 right<<=9 11 17 30 31 result=1

OR:output==left: left<<= right= result=0 OR:output==right: left= right<<= result=0

AND:separate output: left=11 17 31 right=9 17 30 ANDd=17 result=1 AND:NULL output: left=11 17 31 right=9 17 30 ANDd=<nul> result=1 AND:output==left: left<<=17 right=9 17 30 result=1 AND:output==right: left=17 right<<=17 result=1

AND:output==left: left<<= right=9 17 30 result=0 AND:output==right: left= right<<= result=0

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 53 of 145

Page 54: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

22 File-in-memory Vs File-on-disk - FileHasChangedLabwindows/CVI only.

22.1 SynopsisThis routine compares the previous timestamp of a file (using the TimeStamp typedef) against the timestamp of that named file on disk.

The routine returns 1 (TRUE) if the timestamp of the file on disk is older *or* newer than the timestamp in the TimeStamp structure in memory.

If there is a file error, for example, the file does not exist, then a negative error code will be returned.

22.2 Usage#include "alflb.h"

int FileHasChanged(

char *FileName, File name of file on disk which is to have its timestamp compared with the previous timestamp stored in memory.

TimeStamp *Previous); This is the timestamp of the buffer in memory. This value is typically obtained from a previous call to this routine! See example below.

Returns: 1 -> if different - also updates Previous value 0 -> if current-ve -> error code

alflb_20120306.odt © 2002-2012 Alf Lacis Page 54 of 145

Page 55: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

22.3 Example#include "alflb.h"

int main(int argc, char *argv[])

{

TimeStamp BufTimeStamp;

char FileName[] = "myname.bin";

int status;

... /* Buffer the file, etc, etc, etc */

/* Get the Timestamp for the file FOR THE FIRST TIME, and IGNORE the return value */

FileHasChanged(FileName, &BufTimeStamp);...

do

{

/* Wait for user input. During this time, "myname.bin" may or may not

* have been updated on disk. */

...

if ( (status = FileHasChanged(FileName, &BufTimeStamp)) == 1 )

{

/* Re-buffer the file, etc, etc, etc */

}

else if ( status < 0 )

{

/* Process the file error */

}

/* Do something with file. */

}

while ( keep_looping == 1 );

...

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 55 of 145

Page 56: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

23 File Name / Path - Splitting & Merging Routines - fnsplit, fnmerge

23.1 SynopsisThese routines are from DJ Delorie.The fnsplit routine splits a file name into its component parts. It correctly handles file names and paths with dots in them, such as ".emacs", and such paths as "c:/path/." or "c:/path/.." The fnmerge routine, as the name implies, rejoins the component parts of the file name.

23.2 Usage#include "alflb.h"

int fnsplit( Split a path into component parts: const char *path, Source pathname char *drive, destination drive char *dir, destination subdirectory path char *name, destination main part of filename char *ext); destination extension part of filename Returns: An integer bitmap containing the following flags if the item was

correctly found: DRIVE

DIRECTORY

FILENAME

EXTENSION

WILDCARDS

void fnmerge( Joins component parts of a path into one string char *path, Destination pathname string const char *drive, Source drive const char *dir, Source subdirectory path const char *name, Source main part of filename const char *ext); Source extension part of filename

23.3 BugIf your directory string does not contain a '\\', then the fnmerge routine assumes the use of the Unix filename separator '/'. E.g., fnmerge("c:","dir","filename","ext"); => "c:dir/filename.ext" <- WRONG

but: fnmerge("c:","\\dir","filename","ext"); => "c:\dir\filename.ext" <- OK

alflb_20120306.odt © 2002-2012 Alf Lacis Page 56 of 145

Page 57: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

24 File Name or Path Changes - Change_File, Change_Ext

24.1 SynopsisThe Change_File function provides a simple way of changing only a small part of a file name. The original typical use was changing the Extension, which is in the deprecated function Change_Ext, but this is now handled along with all the other parts of the name in Change_File.

24.2 Usage#include "alflb.h"

char *Change_Ext(

char *to,

char *from,

char *ext,

int to_max_len);

Deprecated - do not use for new code.

char *Change_File(

char *to,

char *from,

char *new_thing,

int THING_TO_CHANGE);

Returns:

Change part of a file name (actually copies new string to to).Destination string for newly constructed name.Original name.A string containing the new object to be inserted.A flag describing the thing to change. These flags are the same ones from the Borland C dir.h, but only set one of them: DRIVE

DIRECTORY

FILENAME

EXTENSION

A copy of the pointer of the destination to string: useful if you want to embed Change_File in another call, e.g.: send_message(Change_File(to, from, "bin", EXTENSION));

24.3 Example'input' is:

"c:\path\path\filename.c"

Change_File(to, input, "obj", EXTENSION);

'to' becomes:

"c:\path\path\filename.obj"

alflb_20120306.odt © 2002-2012 Alf Lacis Page 57 of 145

Page 58: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

25 Flash Programmer Boot Code Address Setup - MSBXxxx

MSBCopyLong, MSBCopyChar, MSBSetLongParm

25.1 SynopsisThese provide a short-hand, consistent way of building up parts of a buffer to be send to the Boot ROM code in 430 Handsets. These are probably best shown with the Typical Usage example below.

25.2 Usage#include "alflb.h"

uchar *MSBCopyLong( Places a long into the output (destination) address. uchar *pdest, Destination Buffer long value); long value -- NOTE!!! ANSI C defines long as 4 bytes Returns: Address of next destination byte, suitable for concatenating the output

buffer.

uchar *MSBCopyChar( Places a char into the output (destination) address. uchar *pdest, Destination Buffer uchar value); char value: 1 byte Returns: Address of next destination byte, suitable for concatenating the output

buffer.

uchar *MSBSetLongParm( Places a handset address and a long into the output (destination) address.

uchar *pdest, Destination Buffer long address, Address that handset will use when it gets the buffer long parm); long value -- NOTE!!! ANSI C defines long as 4 bytes Returns: Address of next destination byte, suitable for concatenating the output

buffer.

25.3 ExampleTaken from serialpc.c:

ptr = Header;

ptr = MSBCopyChar (ptr, START_BYTE); // start register load loop

ptr = MSBSetLongParm(ptr, 0x40000000, (long)BAUD); // baud rate to switch to

ptr = MSBSetLongParm(ptr, 0x40000004, (long)Crystal26MHz); // crystal rate to switch to

ptr = MSBCopyLong (ptr, 0L); // end register load loop

// with address=zero

ptr = MSBCopyLong (ptr, 0x40000008L); // address to start boot

// code from

ptr = MSBCopyLong (ptr, (long)SmallBootCodeSize); // length of download code

len = ptr - Header; // length of buffer to send

alflb_20120306.odt © 2002-2012 Alf Lacis Page 58 of 145

Page 59: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

26 Base-36 Checker - hex36rangehex36range

26.1 SynopsisThis provides the conversion from a byte to a base-36 character, with suitable range-checking. The following can be changed via global variables (no accessor functions, yet):

● if the byte is not in the value 0...35, then the function returns global variable hex36_range_error, default value '?';

● the maximum base can also be changed from the default value 36 via hex36_range_base.

26.2 Usage#include "alflb.h"

char hex36range(

char value);

Returns:

Range-checks and returns the ASCII representation of value.The byte to check and convert.Returns the base-36 (or hex36_range_base) representation of value, or hex36_range_error (default '?') if there is an error.

26.3 Example printf("The value (base-36) is '%c'.\n", hex36range(value));

alflb_20120306.odt © 2002-2012 Alf Lacis Page 59 of 145

Page 60: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

27 Human-Readable Time Period - 'Since When'ezi_since_when

27.1 SynopsisThis provides a human-readable time difference string, based on the difference between two time_t values. The values chosen for the break-points were based on how I think about time-periods such as days, months, etc.

The string can be up to 6 characters (default build) with the break-point values (default build) and formats:

"future" report if 'now' & 'then' are reversed"%.0fs" less than 3 minutes as "Ns" seconds "%.1fm" less than 2 hours as "N.Nm" minutes "%.1fh" less than 2 days as "N.Nh" hours "%.1fd" less than 2.5 weeks as "N.Nd" days "%.1fw" less than 2.1 months as "N.Nw" weeks "%.1fM" less than 1.58 years

(19 months) as "N.NM" months "%.1fy" default: report as "N.Ny" years

The smaller dividers are 60, 60, 24 and 7 for minutes, hours, days and weeks respectively. The months divider is taken as 365/12ths of a year, and the years divider is taken as a non-leap-year 365 days.

Returns a copy of the Ezi String out pointer.

27.2 Usage#include "alflb.h"

EZISTR_T *ezi_since_when(

EZISTR_T *out,

time_t now,

time_t then);

Returns:

Updates the Ezi String out with a human-readable time difference string as shown above.

Returns a copy of the Ezi String out pointer.

27.3 ExampleThis shows the output of a test program where then was set to 100 seconds since the epoch, and now was geometrically increased.

now string 99 "future"←reversed 108 "8s" ←8 seconds 159 "59s"

233 "133s"

341 "4.0m" ←4.0 minutes 500 "6.7m"

732 "10.5m"

1072 "16.2m"

1570 "24.5m"

4928 "80.5m"

7216 "118.6m"

10565 "2.9h" ←2.9 hours 15468 "4.3h"

22647 "6.3h"

48546 "13.5h"

71077 "19.7h"

104064 "28.9h"

152360 "42.3h"

326597 "3.8d" ←3.8 days 478172 "5.5d"

700091 "8.1d"

1025004 "11.9d"

1500708 "17.4d"

2197187 "3.6w" ←3.6 weeks 3216902 "5.3w"

4709866 "7.8w"

6895715 "2.6M" ←2.6 months

10096017 "3.8M"

14781579 "5.6M"

21641710 "8.2M"

31685628 "12.1M"

46390928 "17.7M"

67920957 "2.2y" ←2.2 years 99443074 "3.2y"

145594605 "4.6y"

213165061 "6.8y"

312094966 "9.9y"

456938240 "14.5y"

669003277 "21.2y"

979487699 "31.1y"

1735222207 "55.0y" ←55.0 years

alflb_20120306.odt © 2002-2012 Alf Lacis Page 60 of 145

Page 61: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

28 Indexes - The Ezi Index SuiteC or C++:

NEXT, NEXT_N, PREV, PREV_N, DISTANCE, JOG, IS_FULL, IS_EMPTY,

NEXT_GP, PREV_GP,

NEXT_MACRO, PREV_MACRO, DISTANCE_MACRO,

ezi_index_next, ezi_index_prev, ezi_index_distance, ezi_index_freedom, ezi_index_next_n,

ezi_index_prev_n

C++:ezi_index<TYPE>::ezi_index, ~ezi_index, capacity(void), distance, freedom, is_empty,

is_full, jog, next, prev, next_n, prev_n, next_gp, prev_gp

28.1 SynopsisThis suite provides the ability to index through indexed list entries.

Types: The default suite uses macros and these are not restricted to a variable type. To save space, e.g. in an embedded microcontroller, these can be converted to a function library of one of the types ULONG, USHORT or size_t(default): see the following subsection. The C++ version uses a template class to provide type flexibility.

Index Values: The suite uses C-style indexes, i.e., from 0 to capacity-1.

The various 'next_n' and 'prev_n' versions are for situations where the list index may not start at zero. The list entries are defined as first thru capacity-1.

Capacity: The number of available entries in an Ezi Index is actually 1 less than the value of capacity: in other words:

(DISTANCE(...) + FREEDOM(...)) == (capacity - 1)

so if you want a list with 10 available entries, capacity must be set to 10+1.

Side-effect: Be careful that capacity+tail_new, index+places or index+capacity do not overflow your variable's type.

Stipulation: The tail_new and head_old definitions are based on numbering from a low head_old index, to a high tail_new index. For the calculation to work, only one of either head_old or tail_new (depending on how you use your list indexes) must be empty, otherwise you have to add 1 to the index calculated here. E.g., for the following list:

tail_new 2 << position of next *empty* entry

head_old 18 << oldest entry

DISTANCE returns capacity+tail_new-head_old = 20 + 2 - 18 = 4.

FREEDOM returns the number of free entries: which is equal to capacity – DISTANCE - 1.

JOG(index, capacity) is shorthand for index = NEXT(index, capacity).

alflb_20120306.odt © 2002-2012 Alf Lacis Page 61 of 145

Page 62: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

28.2 Macros vs Functions for NEXT, PREV & DISTANCEIf you prefer to use functions - code-space saving is possible when you have a large number of NEXT, PREV, etc, calls at the expense of calling functions - then you should define one of the following in your project or Makefile before compiling your code, e.g., with a -D compiler switch:

INDEXED_LIST_ULONG to have ULONG versions of the functions

INDEXED_LIST_USHORT to have USHORT versions of the functions

INDEXED_LIST_SIZE_T to have size_t versions of the functions (default)

This replaces the in-line macro code in NEXT, NEXT_N, PREV, PREV_N and DISTANCE with function calls to code in indexed_list.c, which you should add to your project or Makefile. Notwithstanding, the macros themselves are still available, if you still need them, e.g. for speed, via the following macro-only calls: NEXT_MACRO, NEXT_N_MACRO, PREV_MACRO, PREV_N_MACRO, DISTANCE_MACRO.

28.3 C++ template <class TYPE> ezi_index<TYPE>::This template provides the best way to use this suite from C++ applications. The interface is straightforward with no surprises. In this template, the capacity, once instantiated in the object's constructor, remains hidden, although available via an accessor.

28.4 Usage#include "alflb.h"

/type/ NEXT(

/type/ index,

/type/ capacity)

Returns:

Calculates the next (current+1) index number in the list. Wraps from capacity-1 back to 0.

Returns the next index number in the list.

/type/ NEXT_N(

/type/ places,

/type/ index,

/type/ capacity)

Returns:

Calculates the (current+places) index number in the list. Wraps from capacity-1 back to 0.

Returns the current+places index number in the list.

/type/ PREV(

/type/ index,

/type/ capacity)

Returns:

Calculates the previous (current-1) index number in the list. Wraps from 0 to capacity-1.

Returns the previous index number in the list.

/type/ PREV_N(

/type/ places,

/type/ index,

/type/ capacity)

Returns:

Calculates the (current-places) index number in the list. Wraps from 0 to capacity-1.

Returns the current-places index number in the list.

/type/ DISTANCE(

/type/ tail_new,

/type/ head_old,

/type/ capacity)

Returns:

Returns the number of entries in the list, allowing for wrap-around. Read the Side-effect and Stipulation above regarding DISTANCE.

The number of entries in the list.

/type/ FREEDOM(

/type/ tail_new,

/type/ head_old,

/type/ capacity)

Returns:

Returns the number of free entries available in the list, allowing for wrap-around. Read the Side-effect and Stipulation above regarding DISTANCE.

The number of entries in the list.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 62 of 145

Page 63: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

/type/ JOG(

/type/ index,

/type/ capacity)

Returns:

Used to jog a sequence number from 0 to capacity-1 & back to 0. If you want to use it, returns the new value of index, however JOG is typically used without the return value, e.g. printf("New index record: %d\n", JOG(index, capacity));

New value of index, but is typically unused.

int IS_EMPTY(

/type/ tail_new,

/type/ head_old)

Returns:

Tests if the list is empty.

1 if empty, 0 otherwise.

int IS_FULL(

/type/ tail_new,

/type/ head_old,

/type/ capacity)

Returns:

Tests if the list is full.

1 if full, 0 otherwise.

/type/ PREV_GP and NEXT_GP

/type/ (index,

/type/ first,

/type/ capacity)

Returns:

These are 'General Purpose' numbered-list navigators. They are based on PREV and NEXT above. They are useful for going up or down thru a numbered list, with a NON-zero-offset. The list entries are defined as first thru capacity-1.The value of the previous or next index as requested.

NEXT_MACRO()

NEXT_N_MACRO()

PREV_MACRO()

PREV_P_MACRO()

DISTANCE_MACRO()

Macro-only calls which have the relevant Indexed List functionality. These will never be replaced with functions.

template <class TYPE>

class ezi_index

{

public:

ezi_index(

TYPE this_capacity);

~ezi_index();

C++ Ezi Index template class.

Constructor & destructor. Note: The number of available entries in an Ezi Index is actually 1 less than the value of capacity, I.e., if you need 10 entries, pass in 10+1.

TYPE distance(

TYPE tail_new,

TYPE head_old);

Returns the number of used entries in the list, allowing for wrap-around. Read the Side-effect and Stipulation above regarding DISTANCE.

TYPE freedom(

TYPE tail_new,

TYPE head_old);

Returns the number of free entries available in the list, allowing for wrap-around. Read the Side-effect and Stipulation above regarding DISTANCE.

bool is_empty(

TYPE tail_new,

TYPE head_old);

Returns true if the list is empty.

bool is_full(

TYPE tail_new,

TYPE head_old);

Returns true if the list is full.

void jog(

TYPE &index);

Note: pass-by-reference. This adds 1 to index. Wraps from capacity-1 back to 0.

TYPE next(

TYPE index);

Calculates the next (current+1) index number in the list. Wraps from capacity-1 back to 0.Returns the next index number in the list.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 63 of 145

Page 64: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

TYPE prev(

TYPE index);

Calculates the current-places index number in the list. Wraps from 0 to capacity-1.Returns the current-places index number in the list.

TYPE next_n(

TYPE places,

TYPE index);

Calculates the (current+places) index number in the list. Wraps from capacity-1 back to 0.Returns the current+places index number in the list.

TYPE prev_n(

TYPE places,

TYPE index);

Calculates the (current-places) index number in the list. Wraps from 0 to capacity-1.Returns the current-places index number in the list.

TYPE next_gp(

TYPE index,

TYPE first);

This is a 'General Purpose' numbered-list navigator, similar to next above. It is useful for a numbered list with a NON-zero-offset: list entries are defined as first thru capacity-1.Returns the value of the next index, suitably wrapped.

TYPE prev_gp(

TYPE index,

TYPE first);

This is a 'General Purpose' numbered-list navigator, similar to prev above. It is useful for a numbered list with a NON-zero-offset: list entries are defined as first thru capacity-1.Returns the value of the previous index, suitably wrapped.

TYPE capacity(void); Return the capacity of the index object. Remember, the number of available entries will be one less than this number.

private:

TYPE capacity;

};

28.5 Examples - SnippetsThis shows the use of two NEXT macros in the one function:

int get_next_valid_machine(int prev)

{

int machine = NEXT(prev, MACHINES_MAX); // Get the next index

// Check if the next machine is OK: if not, then keep incrementing our index

// until we get to a working machine:

// while not valid & not full circle:

while ( device[machine].status != 0 && machine != prev )

machine = NEXT(machine, MACHINES_MAX);

return machine;

}

This shows the use of a non-zero minimum. port[addr].seq_next wraps around at maxSequence-1 to minSequence (this example from real life has maxSequence==0x7F and minSequence==0x32):

if ( pbits->bit.err == STATUS_OK )

{

port[addr].seq_next = NEXT_GP(port[addr].seq_next, minSequence, maxSequence);

trace("Acc: next SeqNum %d\r\n", port[addr].seq_next);

return 0;

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 64 of 145

Page 65: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

28.6 Example - Test App 1 - Refer to ezi_index_cpp.cpp#ifdef TEST_APP_INDEX_1 #define LOOPS 12 #define START 2ul #define CAPACITY 5ul int main(int argc, char *argv[]) { ULONG idx = 0ul; ULONG ii; ULONG dist; ULONG free; ezi_index<ULONG> list(CAPACITY);

cout << argv[0] << " " __DATE__ " " __TIME__ "\ntest NEXT functionality\n"; for ( ii = 0; ii < LOOPS; ii++ ) { idx = list.next(idx); dist = list.distance(idx, START); free = list.freedom(idx, START); cout << "idx=" << idx << " dist=" << dist << " free=" << free << "\n"; } cout << "test PREV functionality\n"; for ( ii = 0; ii < LOOPS; ii++ ) { idx = list.prev(idx); dist = list.distance(idx, START); free = list.freedom(idx, START); cout << "idx=" << idx << " dist=" << dist << " free=" << free << "\n"; } cout << "test NEXT_N functionality\n"; for ( ii = 0; ii < LOOPS; ii++ ) { idx = list.next_n(ii % list.capacity(), START); dist = list.distance(idx, START); free = list.freedom(idx, START); cout << "idx=" << idx << " dist=" << dist << " free=" << free << "\n"; } cout << "test PREV_N functionality\n"; for ( ii = 0; ii < LOOPS; ii++ ) { idx = list.prev_n(ii % list.capacity(), START); dist = list.distance(idx, START); free = list.freedom(idx, START); cout << "idx=" << idx << " dist=" << dist << " free=" << free << "\n"; } return 0; } #endif

$ g++ -DTEST_APP_INDEX_1 -o index_test_1 -g -Wall -O0 ezi_index_cpp.cpp$ ./index_test_1 ./index_test_1 Sep 1 2008 22:27:56 test NEXT functionality idx=1 dist=4 free=0 idx=2 dist=0 free=4 idx=3 dist=1 free=3 idx=4 dist=2 free=2 idx=0 dist=3 free=1 idx=1 dist=4 free=0 idx=2 dist=0 free=4 idx=3 dist=1 free=3 idx=4 dist=2 free=2 idx=0 dist=3 free=1 idx=1 dist=4 free=0 idx=2 dist=0 free=4

alflb_20120306.odt © 2002-2012 Alf Lacis Page 65 of 145

Page 66: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

test PREV functionality idx=1 dist=4 free=0 idx=0 dist=3 free=1 idx=4 dist=2 free=2 idx=3 dist=1 free=3 idx=2 dist=0 free=4 idx=1 dist=4 free=0 idx=0 dist=3 free=1 idx=4 dist=2 free=2 idx=3 dist=1 free=3 idx=2 dist=0 free=4 idx=1 dist=4 free=0 idx=0 dist=3 free=1 test NEXT_N functionality idx=2 dist=0 free=4 idx=3 dist=1 free=3 idx=4 dist=2 free=2 idx=0 dist=3 free=1 idx=1 dist=4 free=0 idx=2 dist=0 free=4 idx=3 dist=1 free=3 idx=4 dist=2 free=2 idx=0 dist=3 free=1 idx=1 dist=4 free=0 idx=2 dist=0 free=4 idx=3 dist=1 free=3 test PREV_N functionality idx=2 dist=0 free=4 idx=1 dist=4 free=0 idx=0 dist=3 free=1 idx=4 dist=2 free=2 idx=3 dist=1 free=3 idx=2 dist=0 free=4 idx=1 dist=4 free=0 idx=0 dist=3 free=1 idx=4 dist=2 free=2 idx=3 dist=1 free=3 idx=2 dist=0 free=4 idx=1 dist=4 free=0$

28.7 Example - Test App 2 - Refer to ezi_index_cpp.cpp#ifdef TEST_APP_INDEX_2 #include <stdio.h> #define CAPACITY 5ul int main(int argc, char *argv[]) { int head = 0; int emtail = 0; ezi_index<int> list((int)CAPACITY); int ih; int it; cout <<argv[0] <<" "__DATE__" "__TIME__"\ncapacity==" << list.capacity() << "\n";

for ( ih = 0ul; ih < list.capacity(); ih++, list.jog(head) ) { for ( it = 0ul; it < list.capacity(); it++, list.jog(emtail) ) { cout << "distance(" << emtail << ',' << head << ")==" << list.distance(emtail, head) << " freedom(..)==" << list.freedom(emtail, head) << " is_full()==" << (list.is_full (emtail, head) ? "TRUE" : "----") << " is_empty()==" << (list.is_empty(emtail, head) ? "TRUE" : "----") << "\n"; } cout << "\n"; } return 0; } #endif

alflb_20120306.odt © 2002-2012 Alf Lacis Page 66 of 145

Page 67: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

$ g++ -DTEST_APP_INDEX_2 -o index_test_2 -g -Wall -O0 ezi_index_cpp.cpp $ ./index_test_2 ./index_test_2 Sep 1 2008 22:30:46 capacity==5 distance(0,0)==0 freedom(..)==4 is_full()==---- is_empty()==TRUE distance(1,0)==1 freedom(..)==3 is_full()==---- is_empty()==---- distance(2,0)==2 freedom(..)==2 is_full()==---- is_empty()==---- distance(3,0)==3 freedom(..)==1 is_full()==---- is_empty()==---- distance(4,0)==4 freedom(..)==0 is_full()==TRUE is_empty()==----

distance(0,1)==4 freedom(..)==0 is_full()==TRUE is_empty()==---- distance(1,1)==0 freedom(..)==4 is_full()==---- is_empty()==TRUE distance(2,1)==1 freedom(..)==3 is_full()==---- is_empty()==---- distance(3,1)==2 freedom(..)==2 is_full()==---- is_empty()==---- distance(4,1)==3 freedom(..)==1 is_full()==---- is_empty()==----

distance(0,2)==3 freedom(..)==1 is_full()==---- is_empty()==---- distance(1,2)==4 freedom(..)==0 is_full()==TRUE is_empty()==---- distance(2,2)==0 freedom(..)==4 is_full()==---- is_empty()==TRUE distance(3,2)==1 freedom(..)==3 is_full()==---- is_empty()==---- distance(4,2)==2 freedom(..)==2 is_full()==---- is_empty()==----

distance(0,3)==2 freedom(..)==2 is_full()==---- is_empty()==---- distance(1,3)==3 freedom(..)==1 is_full()==---- is_empty()==---- distance(2,3)==4 freedom(..)==0 is_full()==TRUE is_empty()==---- distance(3,3)==0 freedom(..)==4 is_full()==---- is_empty()==TRUE distance(4,3)==1 freedom(..)==3 is_full()==---- is_empty()==----

distance(0,4)==1 freedom(..)==3 is_full()==---- is_empty()==---- distance(1,4)==2 freedom(..)==2 is_full()==---- is_empty()==---- distance(2,4)==3 freedom(..)==1 is_full()==---- is_empty()==---- distance(3,4)==4 freedom(..)==0 is_full()==TRUE is_empty()==---- distance(4,4)==0 freedom(..)==4 is_full()==---- is_empty()==TRUE

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 67 of 145

Page 68: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

29 Integers to ASCII Conversion (non-sprintf suite)Fully-specified interfaces:

sctoa, sitoa, sltoa, sstoa, uctoa, uitoa, ultoa, ustoa

Old interfaces:itoa, ltoa, stoa, utoa

Underlying functions:sltoa_direction, ultoa_direction

29.1 SynopsisA family of functions for converting various integer types to an ASCII string representation, in any base from 2 to 36. The old interfaces are available if you want them. The underlying interfaces provide the ability to have the final representation in the normal forwards direction, or the reverse direction. [The number is formatted in reverse, since this provides for very small code, then a string-reversal function reversen (see elsewhere in this document) is applied to the final output string.]

Note: the interfaces are all macros wrappered around the two functions sltoa_direction and ultoa_direction. From a code-footprint-size perspective, this means that the full suite of integer handling is available with only two functions.

29.2 Overflow WarningNo check is made to limit any overflow on the string str parameter. For example:

● a long in base 2 requires 33 characters including the trailing '\0'.● a long in base 10 requires 12 characters including the trailing '\0': "-2147483648"

29.3 Usage#include "alflb.h"

All the prototypes are similar to this:char *<name>(

/type/ value,

char *str,

int radix);

Returns:

Named function for /type/ integer to ASCII converter.Typed value to convert.String to accept the conversion.The radix used in the conversion.Returns a pointer to the string str, useful for embedding the call.

The prototypes are:char *sctoa(SCHAR value, char *str, int radix);

char *sitoa(SINT value, char *str, int radix);

char *sltoa(long value, char *str, int radix);

char *sstoa(short value, char *str, int radix);

char *uctoa(UCHAR value, char *str, int radix);

char *uitoa(UINT value, char *str, int radix);

char *ultoa(ULONG value, char *str, int radix);

char *ustoa(USHORT value, char *str, int radix);

The following use the older names for the functions:char *itoa(int value, char *str, int radix);

char *ltoa(long value, char *str, int radix);

char *stoa(short value, char *str, int radix);

char *utoa(UINT value, char *str, int radix);

alflb_20120306.odt © 2002-2012 Alf Lacis Page 68 of 145

Page 69: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

The following functions are typically not used by themselves, unless it is required that the string be in the reverse direction, e.g., for adding leading zeros (to the right-hand end), and then performing a manual reversal, see reversen elsewhere in this document:char *sltoa_direction(

long value,

char *str,

int radix,

int forwards);

Returns:

Signed long to ASCII converter.Signed long value to convert.String to accept the conversion.The radix used in the conversion.If non-zero, the string runs in the normal direction.If zero, the string is left in the reverse direction.Returns a pointer to the string str, useful for embedding the call.

char *ultoa_direction(

ULONG value,

char *str,

int radix,

int forwards);

Returns:

Unsigned long to ASCII converter.Unsigned long value to convert.String to accept the conversion.The radix used in the conversion.If non-zero, the string runs in the normal direction.If zero, the string is left in the reverse direction.Returns a pointer to the string str, useful for embedding the call.

29.4 ExampleThe simple_itoa.c file contains an example application:

int main (int argc, char *argv[]){ unsigned long ul[] = { 0xffffffff, 0x80000000, 0x7fffffff, 0 }; unsigned short us[] = { 0xffff , 0x8000 , 0x7fff , 0 }; unsigned char uc[] = { 0xff , 0x80 , 0x7f , 0 }; unsigned int ui[] = { 0xffffffff, 0x80000000, 0x7fffffff, 0 }; long *l = ( long * )ul; short *s = ( short* )us; char *c = ( char * )uc; int *i = ( int * )ui; char sa[( sizeof( unsigned long )*8+2 )]; char sb[( sizeof( unsigned long )*8+2 )]; char sc[( sizeof( unsigned long )*8+2 )]; char sd[( sizeof( unsigned long )*8+2 )]; int ii; char fmt[] = "%s: b10:%-12s b16:%-10s b2:%-33s b36:%-7s\n";

for ( ii = 0; ii < ( sizeof( ul ) / sizeof( ul[0] ) ); ii++ ) { ultoa ( ul[ii], sa, 10 ); ultoa ( ul[ii], sb, 16 ); ultoa ( ul[ii], sc, 2 ); ultoa ( ul[ii], sd, 36 ); printf( fmt, "ultoa", sa, sb, sc, sd ); } printf( "\n" ); for ( ii = 0; ii < ( sizeof( ul ) / sizeof( ul[0] ) ); ii++ ) { sltoa ( l[ii], sa, 10 ); sltoa ( l[ii], sb, 16 ); sltoa ( l[ii], sc, 2 ); sltoa ( l[ii], sd, 36 ); printf( fmt, "sltoa", sa, sb, sc, sd ); } printf( "\n" ); for ( ii = 0; ii < ( sizeof( us ) / sizeof( us[0] ) ); ii++ ) { ustoa ( us[ii], sa, 10 ); ustoa ( us[ii], sb, 16 ); ustoa ( us[ii], sc, 2 ); ustoa ( us[ii], sd, 36 ); printf( fmt, "ustoa", sa, sb, sc, sd ); } printf( "\n" ); for ( ii = 0; ii < ( sizeof( us ) / sizeof( us[0] ) ); ii++ ) { sstoa ( s[ii], sa, 10 ); sstoa ( s[ii], sb, 16 ); sstoa ( s[ii], sc, 2 ); sstoa ( s[ii], sd, 36 ); printf( fmt, "sstoa", sa, sb, sc, sd ); }

alflb_20120306.odt © 2002-2012 Alf Lacis Page 69 of 145

Page 70: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

printf( "\n" ); for ( ii = 0; ii < ( sizeof( uc ) / sizeof( uc[0] ) ); ii++ ) { uctoa ( uc[ii], sa, 10 ); uctoa ( uc[ii], sb, 16 ); uctoa ( uc[ii], sc, 2 ); uctoa ( uc[ii], sd, 36 ); printf( fmt, "uctoa", sa, sb, sc, sd ); } printf( "\n" ); for ( ii = 0; ii < ( sizeof( uc ) / sizeof( uc[0] ) ); ii++ ) { sctoa ( c[ii], sa, 10 ); sctoa ( c[ii], sb, 16 ); sctoa ( c[ii], sc, 2 ); sctoa ( c[ii], sd, 36 ); printf( fmt, "sctoa", sa, sb, sc, sd ); } printf( "\n" ); for ( ii = 0; ii < ( sizeof( ui ) / sizeof( ui[0] ) ); ii++ ) { utoa ( ui[ii], sa, 10 ); utoa ( ui[ii], sb, 16 ); utoa ( ui[ii], sc, 2 ); utoa ( ui[ii], sd, 36 ); printf( fmt, "utoa ", sa, sb, sc, sd ); } printf( "\n" ); for ( ii = 0; ii < ( sizeof( uc ) / sizeof( uc[0] ) ); ii++ ) { itoa ( i[ii], sa, 10 ); itoa ( i[ii], sb, 16 ); itoa ( i[ii], sc, 2 ); itoa ( i[ii], sd, 36 ); printf( fmt, "itoa ", sa, sb, sc, sd ); } return 0;}

29.5 Output from ExampleCompile & run the test application with these commands:

$ gcc -Wall -DTEST_APP_SIMPLE_ITOA reversen.c hex36.c -g simple_itoa.c -o simple_itoa

$ ./simple_itoa

ultoa: b10:4294967295 b16:FFFFFFFF b2:11111111111111111111111111111111 b36:1Z141Z3

ultoa: b10:2147483648 b16:80000000 b2:10000000000000000000000000000000 b36:ZIK0ZK

ultoa: b10:2147483647 b16:7FFFFFFF b2:1111111111111111111111111111111 b36:ZIK0ZJ

ultoa: b10:0 b16:0 b2:0 b36:0

sltoa: b10:-1 b16:-1 b2:-1 b36:-1

sltoa: b10:-2147483648 b16:-80000000 b2:-10000000000000000000000000000000 b36:-ZIK0ZK

sltoa: b10:2147483647 b16:7FFFFFFF b2:1111111111111111111111111111111 b36:ZIK0ZJ

sltoa: b10:0 b16:0 b2:0 b36:0

ustoa: b10:65535 b16:FFFF b2:1111111111111111 b36:1EKF

ustoa: b10:32768 b16:8000 b2:1000000000000000 b36:PA8

ustoa: b10:32767 b16:7FFF b2:111111111111111 b36:PA7

ustoa: b10:0 b16:0 b2:0 b36:0

sstoa: b10:-1 b16:-1 b2:-1 b36:-1

sstoa: b10:-32768 b16:-8000 b2:-1000000000000000 b36:-PA8

sstoa: b10:32767 b16:7FFF b2:111111111111111 b36:PA7

sstoa: b10:0 b16:0 b2:0 b36:0

uctoa: b10:255 b16:FF b2:11111111 b36:73

uctoa: b10:128 b16:80 b2:10000000 b36:3K

uctoa: b10:127 b16:7F b2:1111111 b36:3J

uctoa: b10:0 b16:0 b2:0 b36:0

alflb_20120306.odt © 2002-2012 Alf Lacis Page 70 of 145

Page 71: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

sctoa: b10:-1 b16:-1 b2:-1 b36:-1

sctoa: b10:-128 b16:-80 b2:-10000000 b36:-3K

sctoa: b10:127 b16:7F b2:1111111 b36:3J

sctoa: b10:0 b16:0 b2:0 b36:0

utoa : b10:4294967295 b16:FFFFFFFF b2:11111111111111111111111111111111 b36:1Z141Z3

utoa : b10:2147483648 b16:80000000 b2:10000000000000000000000000000000 b36:ZIK0ZK

utoa : b10:2147483647 b16:7FFFFFFF b2:1111111111111111111111111111111 b36:ZIK0ZJ

utoa : b10:0 b16:0 b2:0 b36:0

itoa : b10:-1 b16:-1 b2:-1 b36:-1

itoa : b10:-2147483648 b16:-80000000 b2:-10000000000000000000000000000000 b36:-ZIK0ZK

itoa : b10:2147483647 b16:7FFFFFFF b2:1111111111111111111111111111111 b36:ZIK0ZJ

itoa : b10:0 b16:0 b2:0 b36:0

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 71 of 145

Page 72: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

30 Interprocess Communication, Debugging & Monitoring - the ezi_opt suiteCurrently (20090620) Linux, Cygwin and Win32 only. Main library functions:

ezi_opt_init, ezi_opt_st/ezi_opt_snprintf, ezi_opt_msg, ezi_opt, ezi_opt_byte,

ezi_opt_8,

Library functions, typically used by trace routines and supervisory programs:

ezi_opt_set_bit, ezi_opt_set_byte, ezi_opt_set_1, ezi_opt_set_8, ezi_opt_kill

Helper programs:

opt Set & display option bits and visually monitor the run status of programs.

opt_alive May only be required for Windows: this keeps the shared memory area alivewhen no ezi_opt-enabled programs are running. Although not required forCygwin2 or Linux, is is useful for sanity checking.

opt_shell Schedules or reschedules apps based on their running status. Currently(20090620) Linux & Cygwin only.

30.1 SynopsisThe ezi_opt suite is primarily a debugging, testing and tweaking tool for program development and system changes on multi-process systems, e.g., Linux, Cygwin and the various Win32 platforms.

Once an application has connected to the shared memory, using the inter-process mechanism provided by the ezi_opt suite, accessing a flag bit or value is the same as accessing a local memory pointer, although the library functions hide this implementation detail.

No signals, semaphore locking or other mechanisms are required, since the write-functionality of the shared memory area is separated into two main sections:- from the Helper Programs to the Developer's Programs, and- from the Developer's Programs to the Helper Programs.

2 From Cygwin's Implementation Notes Compatibility, http://cygwin.com/: The XSI IPC functions [including the shared memory functions] ... are only available when cygserver is running and the CYGWIN environment variable is set so that it contains the string server.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 72 of 145

Page 73: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

30.1.1 Comms from the Helper Programs to the Developer's Programs

This essentially consists of a series of bit-flags that the opt helper program can set. As a developer's program is running, it can check the state of an option bit (or several bits together) and turn on a newly-added functionality, tracing or other testing.

For example: an important change is required to be made to ProgX by developer Ted. The newly-added code can be protected by testing bit 15, and showing a trace using bit 16, as in this illustration:

. . .

if ( ezi_opt(15) ) // now comes Ted's important change

{

result = new_function(new_code);

if ( ezi_opt(16) )

trace("ProgX: result from new_function() is %d\n", result);

}

else // this was old code that Ted wants to replace.

{

crappy_old_way(of_doing_something);

}

. . .

Ted can start the newly-modified ProgX, and can wait until it is finished initialising and it has settled down, and he is ready to commence testing.

At the point where Ted is going to test the new code, while ProgX is actually running, Ted uses the opt helper program to turn on bit 16 to enable trace messages, and then turn on bit 15 to enable the new functionality. Ted then uses opt to monitor how ProgX is doing either using his pre-existing monitoring code or via ezi_opt_st or ezi_opt_msg, provided as part of the ezi_opt suite.

When Ted is happy with the results, Ted can disable the 16th bit he used for tracing, just leaving bit 15 still on.

Finally, in a system boot-up script, Ted can insert a schedule of the opt helper application into the boot-up scripts, thus effectively enabling bit 15 for the life of the system.

At any point in the future if there is a problem with the new functionality, Ted can re-enable the trace bit 16, check what is going on, even disabling the new functionality, without laying hands on ProgX at all.

30.1.2 Comms from the Developer's Programs to the Helper Programs

Comms back the other way, from the developer's programs is concerned with monitoring status and run frequency which can be read with the opt helper program.

Every time that the developer's program calls ezi_opt_st or ezi_opt_msg, the following are updated:- a pid (process ID) counter, incremented with each program restart/initialise;- the last pid;- a counter, incremented with each call;- the time of the last call;- the time of the previous call;- a status or trace string.

Also, as a sanity check, the opt helper program can display a table of all option bits.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 73 of 145

Page 74: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

30.2 Using the opt Helper ProgramThe opt helper program uses a very short argument format, for quick typing of new commands, so can be a little cryptic when first used.

Usage 1 is: opt [@|nnn|name|h [s|t|u|d|q|R|@|mmm [1|0|value]]]

Usage 2 is: opt [s|r|R|v] filename [s|t]

Where in usage 1:1st group: @ Operate on all programs (default)

nnn Operate only on this program number

name Operate on the first program identified by name, case-sensitive

h Help (this text)

2nd group: s Show bits (default)

t Show times & status

u Show updated 'diff' times & status

d Turn all bits on

q Turn all bits off

R Reset status info

@ Set "all bits" to 'value'.

mmm A bit number from 0 to 39 (default build)

3rd group: 1 set bit mmm on

0 reset bit mmm off - DEFAULT

value If "all bits" is '@', enter the value in hexadecimal, & leading

00's are significant, and there should be an even number of

digits, e.g.

f00081 is different from

00f00081 << This sets the next higher byte to zeros.

Where in usage 2 (supervisor application data not is not saved nor restored):1st group: s Save the memory block to the named file

r Read the option bits back from the named file

R Read everything back from the named file (not usually recommended)

v View the saved file's data

2nd group: filename to read or write

3rd group: s For 'v' mode, show bits (default)

t For 'v' mode, show times & status

alflb_20120306.odt © 2002-2012 Alf Lacis Page 74 of 145

Page 75: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

The best way of seeing how these parameters work together is to give examples that the author uses:

$ opt @ s For all table entries, show the option bits in binary & hex.

39____32 31____24 23____16 15_____8 7______0 hex_______ Num Name________ Last_Status_Reported...

.......1 ........ .....111 1....... .......1 0100078001 0 www_filter normal periodic tick

........ ........ ........ ........ .......1 0000000001 1 lb_parent respawned lb_child

........ ........ ........ ........ .......1 0000000001 2 lb_child processed 703 msgs so

far

........ ........ ........ ........ ........ 0000000000 100 opt

........ ........ ........ ........ .......1 0000000001 101 opt_alive

$ opt @ t For all table entries, show the time and status information.

Prev Last

__pid __pid_cntr ______cntr mmdd.HHMMSS mmdd.HHMMSS Num Name________ Last_Status_Reported...

1122 1 4527800 0101.123456 0101.123456 0 www_filter normal periodic tick

5633 1 55 0101.111415 0101.111733 1 lb_parent respawned lb_child

6984 422 4352 0101.111734 0101.111740 2 lb_child processed 703 msgs so far

4916 8 281 0617.104846 0617.105134 100 opt 101 @ 0x40000001

2264 1 49 0617.105126 0617.105131 101 opt_alive

$ opt @ u As above, but showing the times as differences from 'now' in human-readableformat. The 'last' time is the time since 'now', but the 'prev' time is the timesince 'last'. The time on the top header line is in mmdd.HHMMSS format.

_0804.222959_

__pid __pid_cntr ______cntr __prev __last Num Name________ Last_Status_Reported...

1122 1 4527806 1s 1s 0 www_filter normal periodic tick

5633 1 56 3.4m 7.6m 1 lb_parent respawned lb_child

6984 422 4356 2s 3s 2 lb_child processed 703 msgs so far

7766 1 1 ?? 2.3h 76 forward Initialised

7780 143 159 8s 0s 100 opt 101 0 0

14174 2 16768 5s 9.4m 101 opt_alive

$ opt 99 0 1 For entry 99, set the 0th bit to 1.

39____32 31____24 23____16 15_____8 7______0 hex_______ Num Name________ Last_Status_Reported...

>........ ........ ........ ........ .......1 0000000001 99

$ opt 50 31 0 For entry 50, set the 31st bit to 0.

39____32 31____24 23____16 15_____8 7______0 hex_______ Num Name________ Last_Status_Reported...

>........ ........ ........ ........ ........ 0000000000 50

$ opt dman Display information for the dman entry.

Prev Last

__pid __pid_cntr ______cntr mmdd.HHMMSS mmdd.HHMMSS Num Name________ Last_Status_Reported...

1122 1 11 0702.212345 0702.212359 22 dman table dMan could not be

opened

alflb_20120306.odt © 2002-2012 Alf Lacis Page 75 of 145

Page 76: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

The next examples are typically used from start-up or boot-up scripts:

$ opt r ~/option.bits Restore all the option bits from a previously saved file.

$ opt 50 @ 09F061 For entry 50, set the lower 24 option bits to hex 09F061 (must be an evennumber of digits) or in binary: 00001001 11110000 01100001. Note that thisis different from hex 0009F061 and 000009F061: see the following example.

39____32 31____24 23____16 15_____8 7______0 hex_______ Num Name________ Last_Status_Reported...

>........ 1....... ....1..1 1111.... .11....1 008009f061 50

^^^^^^^^ ^^^^^^^^ ^^^^^^^^<< only the bottom 24 bits are set

$ opt 50 @ 0009F061 For entry 50, set the lower 32 option bits to hex 0009F061 or in binary:00000000 00001001 11110000 01100001. Note the difference from theprevious example.

39____32 31____24 23____16 15_____8 7______0 hex_______ Num Name________ Last_Status_Reported...

>........ ........ ....1..1 1111.... .11....1 000009f061 50

^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^<< only the bottom 32 bits are set

Examples using the save/restore file are:

$ opt s option.bits Saves the shared memory block (but not supervisory items) to file 'option.bits'.

$ opt r option.bits Restores the option bits from a file to shared memory.

$ opt R option.bits Restores everything from a file to shared memory (not recommended).

$ opt v old.bin s Show the option bits from the old file 'old.bin'.

$ opt v old.bin t Show the status information from the old file 'old.bin'.

30.3 Using the opt_alive Helper ProgramThe opt_alive helper program may be required for WIN32-built target platforms. The Windows Shared Memory implementation says that when all programs have exited which had attached themselves to share memory, then the shared memory is deallocated, thus losing the currently set option bits and all the status and time information.

To prevent this, start up the opt_alive program in the background. The opt_alive helper program attaches itself to the 101st table entry (in the default build) and then sleeps for 5 seconds (default). Then it re-awakes, and calls ezi_opt_msg update its status and times. This status and times can be examined with the opt helper program.

Usage is:

opt_alive [seconds|h]

Where:

seconds Time to sleep for each cycle in range 1 to 600. h Display this help information.

When opt_alive is first run, it sets the 0th bit to 1 in its own table entry options, in other words, executes the equivalent of using the opt helper program: "opt 101 0 1".

alflb_20120306.odt © 2002-2012 Alf Lacis Page 76 of 145

Page 77: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

If for whatever reason, you actually do want to stop all the developer's programs, you can also stop opt_alive by either (1) killing it or (2) setting opt_alive's 0th bit to 0, by issuing the command: "opt 101 0 0". Every time that opt_alive awakes, it reexamines this 0th bit, and if the bit is 0, opt_alive will exit.

30.4 Using the opt_shell Helper ProgramThe opt_shell helper program may be useful for Linux-built or Cygwin-built target platforms. opt_shell can act as a general scheduler to schedule the developer's ezi_opt-aware programs. opt_shell has the added capability that if necessary it can kill and re-schedule these programs, based on idle times or run-away counters obtained from the time and counter information generated from calls to ezi_opt_st or ezi_opt_msg.

<This opt_shell helper program section to be documented further.>

30.5 Library UsageDefault build parameters are:

EZI_OPT_NAME_MAX 12 Brief human-readable nameEZI_OPT_LOG_MAX 120 Logged trace stringEZI_OPT_MAX_APS 100 Maximum number of communicating applicationsEZI_OPT_MAX_BITS (5*8) Maximum number of option bits: make this some multiple of 8.

#include "ezi_opt.h"

int ezi_opt_init(

int progdef,

char *name,

char *string);

This is the initialisation function. It obtains access to the shared memory.

name can be up to EZI_OPT_NAME_MAX characters.The reported status up to EZI_OPT_LOG_MAX characters, or may be NULL.

int ezi_opt_st(

char *fmt,

... );

This is first of two status-reporting functions.The argument list is similar to that used by the printf family, except that control characters are replaced with spaces.The run counter and last & previous run times are updated.The full entry-point (linker) name is actually ezi_opt_snprintf.

int ezi_opt_msg(

char *name,

char *string);

This is the second simpler status-reporting function.name can be up to EZI_OPT_NAME_MAX characters.name may be passed as NULL, in which case the name in shared memory is not updated.string is a simple string (not a format string) and may be passed as NULL, in which case the string in shared memory is not updated.In any case, the run counter and last & previous run times are updated.

int ezi_opt(

int bitnum);

This allows the developer's program to test a bit. Returns 1 if the bit is on.

UCHAR ezi_opt_byte(

int bytenum);

This allows the developer's program to test a byte. Returns the whole byte.

UCHAR ezi_opt_8(

int bytenum);

This allows the developer's program to test a byte. Returns the whole byte.

The following are typically only used by the supervisory, initialisation programs or a tracing library.

int ezi_opt_set_bit(

int bitnum,

ULONG value);

This allows the developer's program to set a bit: with 'natural' parameter ordering. value is normalised to 0 or 1.Note: the order of parameters is different from ezi_opt_set_1() below.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 77 of 145

Page 78: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

int ezi_opt_set_1(

ULONG value,

int bitnum);

This allows the developer's program to set a bit: with 'old' parameter ordering. value is normalised to 0 or 1.

int ezi_opt_set_byte(

int bytenum,

ULONG value);

This allows the developer's program to set a byte: with 'natural' parameter ordering. value is masked to 8 bits.Note: the order of parameters is different from ezi_opt_set_8() below.

int ezi_opt_set_8(

ULONG value,

int bytenum);

This allows the developer's program to set a byte: with 'old' parameter ordering value is masked to 8 bits.

int ezi_opt_kill(void); Typically used by a supervisory or helper program to deallocate the shared memory - usually only required for Linux and Cygwin.

30.6 ExampleExample, assumes EZI_OPT_DBKING is set to 11 in ezi_opt_slots.h:. . .

#include "ezi_opt.h"

#include "ezi_opt_slots.h"

. . .

int main(int argc, char *argv[])

{

. . .

if (ezi_opt_init(EZI_OPT_DBKING, "dbking", "starting up"))

{

fprintf(stderr,"opt: shared memory initialisation error\n");

fflush(stderr);

errno = ENOMEM;

return errno;

}

<<< read some records from 'Data' >>>

ezi_opt_st("opened %s, records:%lu\n", "Data", record_count);

. . .

Output from opt:

$ opt

Prev Last

__pid __pid_cntr ______cntr mmdd.HHMMSS mmdd.HHMMSS Num Name________ Last_Status_Reported...

1122 1 4527800 0101.123456 0101.123456 0 www_filter normal periodic tick

5633 1 55 0101.111415 0101.111733 1 lb_parent respawned lb_child

6984 422 4352 0101.111734 0101.111740 2 lb_child processed 703 msgs so far

2656 1 2 0617.152015 0617.152016 11 dbking opened Data, records:101326

4916 8 435 0617.152231 0617.152235 100 opt 101 @ 0x40000001

2264 1 49 0617.105126 0617.105131 101 opt_alive

alflb_20120306.odt © 2002-2012 Alf Lacis Page 78 of 145

Page 79: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

31 Logging Events (Encrypted) - alflog_write, etcalflog_open, alflog_close, alflog_write, alflog_flush, alflog_trim,

alflog_open_read, alflog_read

31.1 SynopsisThese routines provide for the creation and use of log files with a couple of particular extra requirements:

1. the log files are encrypted (selectable); and2. the events in the log file are protected by an internal CRC calculation.

Other, more typical specifications for these log routines are:1. specification of a maximum number of records;2. selectable automatic trim-on-open (recommended), trim-on-close (not recommended);3. selectable automatic flushing;4. the use of a separate 'event category' field.

As an adjunct, there is also a reader application.

31.2 Typical UsageThe ability to add a log to an application is extremely easy. The three functions that you would mainly use are shown in this little flowchart:

+-----------------------------+

| Open log file for writing: | Place this near the beginning| alflog_open() | of the program start-up code+-----------------------------+

|

V

+-----------------------------+

| got an event to be logged? |

| alflog_write() or ALFLOG() |

| ... |

| alflog_write() or ALFLOG() |

| ... |

| alflog_write() or ALFLOG() |

+-----------------------------+

|

V

+-----------------------------+

| Release memory & close file:| Place this near the end of| alflog_close() | the program shutdown code+-----------------------------+

The other functions in this suite are mainly of concern to the log-reading application, or if you want to do your own file flushing, etc.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 79 of 145

Page 80: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

31.3 Typical Event Category or Event IDThe application programmer should make a list of the event categories or event IDs that he/she wants to use. This is a short, 7-character null-terminated string. It is helpful to set up a list in your application, for example:

#define L_START "START" /* program start & stop */#define L_STOP "FINISH"#define L_USER "user" /* user-initiated action, e.g., button click */#define L_DEVICE "device" /* device interrogation */#define L_EVENT "event" /* event during sequence of automated events */#define L_DB_PICK "db pick" /* result of database selection process */#define L_DB_READ "db read" /* result of database reading process */#define L_DB_PICKERR "DBP.ERR" /* Database pick errors */#define L_DEVERR "DEV.ERR" /* Device error, timeouts, etc */#define L_FILERR "FIL.ERR" /* File errors, etc */#define L_MEMERR "MEM.ERR" /* Memory allocation error */

Note the usage of CAPITAL letters that would make some events stand out when the log is displayed.

31.4 Simplifying the alflog_write FunctionSince you may be calling the alflog_write function quite a lot, it is also a good idea for the application programmer to simplify even further the use of the alflog_write function call through the use of a macro. The predefined one in alflog.h is this:

#define ALFLOG(id,msg) do { if ( plog ) { alflog_write(plog,id, msg); } } while ( 0 )

Using this or your own macro has two benefits:1. it removes one of the parameters, pLog, from the visible code; and2. it uses the object pointer, plog, to determine whether or not to write the log.

31.5 Format of the Log FileInternally, the file is a straight text file, even if it has been encrypted. The only control characters you should see in the file are new-lines.

The encryption is performed by use of a 'mirror-substitution-table' with random seeds. A substitution-table cipher is very fast in that each character to be encrypted or decrypted is simply looked up in a table: in practice it is as fast as a non-assembler version of strcpy. A mirror-substitution-table means that if 'a' maps to '{', then '{' maps to 'a'. This means that a mirror cipher has the peculiar property that if you pass the data through the cipher process twice, you end up with plain text again!

Internally, after decryption, the file has variable-length records, with fixed-length fields at the beginning of each record. Separator is the space ' ' character. Non-printing characters are stripped from the event category and the record. The format is typically:

XYYYYMMDD.HHmmSScc CCCCCCCC Type___ Record.....

where:X Record identifier used as a mirror-substitution seedYYYYMMDD.HHmmSScc Year-month-day.hours-minutes-seconds-centiseconds.CCCCCCCC 32-bit CRC as an 8 character stringType Event category or event ID. Maximum 7 character string.Record..... Variable length record

For example:

x20100226.13324855 29365dr device COM port not ready

The maximum record length of 1024 + 1 bytes can be controlled by overriding the default value of alflogMAXmsg with your own value passed to alflog.h, e.g.:

#define alflogMAXmsg 2000 // write really big records to the log#include "alflog.h"

alflb_20120306.odt © 2002-2012 Alf Lacis Page 80 of 145

Page 81: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

31.6 Some Notes On TrimmingTypically, to prevent the log file becoming too cumbersome, the recommended practice is to trim the file on alflog_open by setting do_trim to 1, although the log file may additionally be trimmed on alflog_close by setting do_trim to 2 but this is not recommended.

If do_trim is non-zero, alflog_open will scan the file, and remove excess head entries prior to maxrec. In other words, if maxrec is 10000 and the file is 12000 records long, the first 2000 records are discarded, and records 2001 to 12000 are rewritten as records 1 to 10000. If do_trim is 2, not recommended, this also happens in alflog_close.

31.7 Usage#define alflogMAXmsg NNNNN Use this for a longer (>1024+1) maximum record size.#include "alflog.h"

alflog_t *alflog_open( Open a log, and set various internal flags for later. Returns a pointer to an alflog handle. A file opened for writing cannot be read to without closing and reopening with alflog_open_read().

const char *filename, File name for the log. int maxrec, Maximum number of record to keep in file during a trim. int do_flush, Do/do not auto-flush after each record added. Recommended to be

TRUE unless high-speed logging is required. Use alflog_flush() to do a manual flush in this case.

int trim_flag, An ORed flag: 0 => no trimming of log file is performed. | 1 => trim on alflog_open() only. Recommended. | 2 => trim on alflog_close(). Not recommended as you may lose early records.

int do_encrypt); Whether or not to encrypt the text part of the message. Simple mirror substitution table ciphers with random keys are used. 0 = no encryption !0 = do encryption

Returns: Success: pointer to newly opened log file handle.On error returns NULL.A Trim error sets errno to EACCES (=Permission denied)

alflog_t *alflog_open_read( Open a log file for reading, and set various internal flags. Returns a pointer to an alflog handle. A file opened for reading cannot be written to without closing and reopening with alflog_open().

const char *filename, As for alflog_open(). int do_encrypt); As for alflog_open().

int alflog_close( Used for both alflog_open() and alflog_open_read(), this closes the log & releases system resources. If opened for writing, auto-trims the log if do_trim was set to 2.

alflog_t *plog); Pointer to an alflog handle. Returns: Success: 0

EOF on End of file.EINVAL if plog is NULL or corrupt.

int alflog_write( Appends the log to the log file and adds a newline. If do_flush in alflog_open() was on, performs an alflog_flush() after writing.

alflog_t *plog, Pointer to an alflog handle. const char *id, A maximum 7-character string used for categorising your messages. const char *msg); Message to log. Nonprinting characters are replaced with blanks. Returns: 0 on success.

EOF on End of fileEINVAL if plog is NULL or corrupt.EBADF if alflog_open() not used to open file.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 81 of 145

Page 82: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

void ALFLOG( Shorter name and calling sequence as for alflog_write(), but assumes that the alflog handle is called plog.

const char *id, As for alflog_write(). const char *msg); As for alflog_write(). Returns: Void.

int alflog_flush( Typically not required if do_flush in alflog_open() was TRUE. Used if you wish to flush the output log to disk manually.

alflog_t *plog); Pointer to an alflog handle. Returns: Returns as for alflog_write().

int alflog_trim( Typically not required if do_trim in alflog_open was TRUE. This trims the log file as per the discussion above on Some Notes On Trimming. This is called automatically if the do_trim flag included the value 1 on alflog_open or included the value 2 on alflog_close.

alflog_t *plog); Pointer to an alflog handle. Returns: Returns as for alflog_write().

int alflog_read( Description: Reads and parses an alflog log record into the component parts which are returned. If do_encrypt is non-zero, then reverse-encryption is automatically applied.

alflog_t *plog, Pointer to an alflog handle. EZISTR_T *Eid,

EZISTR_T *Emsg,

EZISTR_T *Etimestamp);

Eid, Emsg and Etimestamp should be declared with the #defines from the header file, ie: EZISTREMPTY(Eid , alflogMAXid );

EZISTREMPTY(Emsg , alflogMAXmsg );

EZISTREMPTY(Etimestamp, alflogMAXtime);

And since they are Ezi Strings, they are overflow-safe. Returns: 0 on success

1 CRC error2 record does not appear to be an alflog record.EOF on End of fileEINVAL if plog is NULL or corrupt.EBADF if alflog_open_read() not used to open file.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 82 of 145

Page 83: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

31.8 ExampleThe example is taken from the test application built into the end of alflog.c:

#define __REV__ "1.0"#define FORMATDISP "%s %s %s"#define LOGMAX 20

static char MainStr [] = "TEST_APP_ALFLOG v" __REV__;static char BuildStr[] = __FILE__ " Compiled:" __DATE__ " " __TIME__;

int main(int argc, char *argv[]){ alflog_t *plog = NULL; EZISTREMPTY(tempStr, 1024); char LogFile[256 + 1] = "test_app_alflog.log";

if ( NULL == ( plog = alflog_open(LogFile, LOGMAX, 1, 1, 1))) return 3;

ezi_snprintf(tempStr, "%s %s", MainStr, BuildStr); ALFLOG("START" , tempStr->str); ALFLOG("event" , "never before has the Cheops pyramid been built"); ALFLOG("user" , "Non-printing chars: \n\n\n\b\r\t <here."); ALFLOG("user" , "8-bit chars: \x80\x81\x8F\xFF <here."); ezi_snprintf(tempStr, "%s %s error:%d %s", MainStr, BuildStr, ENOMEM, "No Memory"); ALFLOG("MEM.ERR", tempStr->str); ALFLOG("user" , "that was an error"); ALFLOG("FINISH" , "Good Bye."); alflog_close(plog);

return 0;}

Build the test application and run it twice:

$ gcc -g -Wall -DEZI_DBG_MAX=150 -DTEST_APP_ALFLOG -o test_app_alflog alflog.c ezi_sproc.c -L. -lalflb

$ ./test_app_alflog <<< first time creates the log$ ./test_app_alflog <<< second time appends to the log

Read the log back to stdout:

$ ./alflog_reader test_app_alflog.logFile:test_app_alflog.logRead:Wed Mar 17 23:28:35 201020100317.23282921 START TEST_APP_ALFLOG v1.0 ../alflog.c Compiled:Mar 17 2010 13:22:3420100317.23282921 user Non-printing chars: <here.20100317.23282921 user 8-bit chars: ▒▒▒▒ <here.20100317.23282921 event never before has the Cheops pyramid been built20100317.23282921 MEM.ERR TEST_APP_ALFLOG v1.0 ../alflog.c Compiled:Mar 17 2010 13:22:34 error:12 No Memory20100317.23282921 user that was an error20100317.23282921 device COM port not ready20100317.23282921 FINISH Good Bye.20100317.23283159 START TEST_APP_ALFLOG v1.0 ../alflog.c Compiled:Mar 17 2010 13:22:3420100317.23283159 user Non-printing chars: <here.20100317.23283159 user 8-bit chars: ▒▒▒▒ <here.20100317.23283159 event never before has the Cheops pyramid been built20100317.23283159 MEM.ERR TEST_APP_ALFLOG v1.0 ../alflog.c Compiled:Mar 17 2010 13:22:34 error:12 No Memory20100317.23283159 user that was an error20100317.23283159 device COM port not ready20100317.23283159 FINISH Good Bye.<EOF>

Finally, dump the log using cat to show the encryption:

alflb_20120306.odt © 2002-2012 Alf Lacis Page 83 of 145

Page 84: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

$ cat test_app_alflog.log▒▒▒[▒▒▒[|▒[▒▒?v▒[b▒▒?[▒▒▒bKBZ▒BbbbB▒KB▒Z▒▒▒Z▒<▒:@b9[▒▒b▒▒m▒▒?▒Q▒Cbc▒/▒?=yO▒▒▒b[|b▒▒[▒b[▒O▒▒O▒Y^Z▒)▒▒B)▒▒)BZoZ▒Z)>▒▒f▒?))>'J▒;>>>>▒8▒▒▒;g▒+g▒i>▒▒▒;J%>[▒▒;?a▒▒▒▒▒?▒??U▒?▒▒▒▒y▒Cj▒j▒▒S▒y?▒▒▒U;~]?j▒#?▒▒▒▒▒?▒▒y▒y▒▒▒[▒[[+▒▒8▒+▒.▒K?b▒▒?▒▒ b??▒bbb▒??b ▒;}▒▒b▒?b▒▒▒bk▒▒}:▒b:▒▒▒▒▒Yb ▒?b *▒A▒▒*S▒SS▒▒▒&▒▒*▒*D*▒▒▒S▒▒?*▒?▒µ▒&▒,,▒▒▒0▒Q▒▒▒Q▒?▒{u▒?&S▒&&;▒▒▒▒▒▒&▒▒▒▒▒?▒X▒I▒y▒▒▒▒*S▒S▒▒▒I**I▒▒▒X▒▒▒▒I▒*▒(▒▒▒X?▒▒▒▒!▒▒▒!▒▒!▒▒▒▒*▒!Z▒!?▒▒?Z▒`▒▒ZZZZ$y▒$Z▒▒`Z▒▒Z▒▒?▒▒'E▒EE▒▒▒j▒▒'c'6'▒*▒▒▒8c9▒▒*▒▒O+8▒**▒v▒*▒P▒#*▒P#*?!▒▒rM▒▒▒▒:▒6/▒:MUM▒M▒▒▒V▒:o▒▒V▒k▒▒▒▒▒▒▒ccV▒▒▒▒/▒▒▒▒▒▒▒▒?▒▒?▒?▒F?▒▒▒r▒▒?▒▒▒▒r▒▒▒[[▒▒▒5▒▒▒▒▒▒▒▒▒▒▒▒▒N▒N▒?▒▒w▒▒▒▒N▒▒!▒▒S▒▒?▒▒▒▒▒▒!▒▒!▒$▒▒▒[▒▒▒[|▒[▒▒?[?vb [▒CC▒|▒b}▒=▒bbbb▒▒{▒▒▒▒{▒▒{QbC▒▒▒▒ObF▒=▒=▒O▒'q''▒qE\q▒▒▒▒q&jy▒▒`▒q▒`Ey▒▒?yyyy▒▒▒▒▒y`B▒▒▒▒y▒t▒dy▒B?▒\y4▒K▒▒▒K▒▒K▒4)▒Ks?c▒c▒42gs▒cwc▒O▒▒▒▒cwc▒▒▒cB▒▒c▒▒▒5▒O▒c▒M▒c▒/5▒/▒▒▒A▒g▒▒cc▒▒▒▒▒|O▒▒y▒yyo▒nr▒o▒ o▒▒▒8L▒y▒L▒L▒8▒▒▒r▒▒▒8▒▒▒▒▒▒~~▒▒c▒c▒▒8t▒ry8rr▒▒▒▒▒3▒rL8C3▒▒e▒i▒▒▒▒.8▒n8▒y▒y8▒o▒▒▒▒o▒8i..3.?▒8<38▒i▒3.00h?▒▒`▒'T▒`he`▒kL▒e▒▒▒▒L'▒▒S#8▒▒▒▒▒▒2▒▒▒▒▒#▒▒g▒8▒▒]▒0h?▒▒`▒'T▒`he`▒kL▒eF▒▒▒`8`▒▒8|▒▒8▒▒%▒▒▒J]▒▒▒g]?8▒▒N▒▒?▒▒W▒{ ▒W▒^W▒!▒.{*▒?▒▒^.▒▒▒▒▒▒..▒▒▒▒.▒▒k

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 84 of 145

Page 85: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

32 Large Character FunctionsFunctions:

chr16x12(), chr12x7(), chr9x5(), chr7x5(), chr7x4()

Data:LTR16x12[][], LTR12x7[][], LTR9x5[][], LTR7x5[][], LTR7x4[][]

lgspace16x12, lgspace12x7, lgspace9x5, lgspace7x5, lgspace7x4

32.1 SynopsisThese functions provide a method of generating strings containing bit-mapped character strings in various styles: here is 4 of the 6 fonts, generated using the program 'lgchr' which uses the large character library:16 high x 12 wide or 12 high x 12 wide (if only UPPER CASE is required): @@@@ @@@@@@ @@@ @@ @@@@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@@ @@ @@@ @@@@ @@@@@ @@@ @@@@@@@ @@ @@ @@@@ @@@@@ @@ @@@ @@@@ @@@@@ @@ @@@@@@ @ @@@@@ @@@@@@@ @@@ @@@@ @@@@@@@ @@ @@@@@@@@@ @@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@ @@@@@@@@ @@@@@@@@@ @@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@ @@@@@@@@@ @@@@@@@@ @@@@@@@@@ @@ @@ @@@ @@@ @@ @@ @@@ @@ @@ @@ @@@ @@ @@ @@@ @@@ @@ @@ @@@ @@ @@ @@ @@ @@ @@@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@@@@@@ @@ @@@@@@@@@ @@ @ @@ @@@ @@ @@ @@@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@ @@ @@ @@ @@ @@ @@@@@@@@@ @@@@@@@@@ @@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@ @@ @@ @@@@@@@@@ @@ @@@@@@@@@ @@@@@@@@@ @@@@ @@@@@@@@@ @@ @@@@@@@@@ @@@@@@@@@@ @@@@@ @@@ @@@ @@@@@ @@ @@@@@@@ @@@@@@ @@@ @@@ @@@@@ @@@ @@@ @@@@@ @@@ @@@@@@@ @@@ @@@@@@@ @@@ @@@@@@@ @@ @@ @@ @@@@@@@@@ @@@@@@@

12 high x 7 wide: @ @@@@ @ @ @ @ @ @ @ @ @ @ @ @@@@ @@@@@ @@@@@ @@@@ @ @@@@@ @@@@ @@@@@ @@@@ @@@@ @@@@ @@@@ @@@@@ @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @ @ @ @ @ @ @@@@@@ @ @ @ @ @ @ @ @ @ @ @@@@@@ @ @@ @ @ @@ @ @ @@ @ @ @ @ @ @ @@ @ @ @@ @ @ @ @ @ @ @ @ @@@@@@ @@@ @ @ @@@ @ @@@@@ @@@@ @ @ @@@ @ @ @@@ @ @@@@ @@ @@@@@ @ @@@@ @ @ @ @@@@

9 high x 5 wide: @ @@ @ @ @ @ @ @ @ @@ @@ @@ @ @ @@ @@ @@ @@ @ @@ @ @@ @@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@@ @ @ @ @ @ @ @ @ @ @ @@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@@@ @@ @ @@ @@ @@ @ @ @@ @ @@ @ @ @@ @ @@ @ @@

7 high x 5 wide: @ @@ @@@ @@ @@@@ @@ @ @ @@ @@@ @@ @@ @@@@@ @@@@ @@@ @@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@@@ @ @@@ @ @@@@ @ @ @@@@ @ @ @ @ @@@ @@@@ @@ @ @@@@ @@ @ @@ @ @ @ @ @@@@ @@ @@@@ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@@@ @ @ @ @ @@ @@@@ @@ @ @ @ @ @ @ @ @ @@ @ @@@@ @ @ @@

The horizontal spacings between characters are controlled by the variables lgspace?x?. As of February 2012, there were no accessor functions for these: they are globals: to be done.

The output character ('@' in the examples above) is passed in.

32.2 UsageUsage involves making one call for each row of intended output, for example:

for (row = 0; row < 16; row++)

{

chr16x12(input, '@', out, row);

printf("%s\n", out->str);

}

Or more succinctly, using the returned pointer from the function directly:for (row = 0; row < 16; row++)

{

printf("%s\n", chr16x12(input,'@',out,row)->str);

}

Of course, if 'input' changes between calls, then you will get a mix of output strings.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 85 of 145

Page 86: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

32.3 Usage

32.3.1 Declaration (Instantiation) of Ezi-Strings

#include "lgchrlib.h" Includes alflb.h.

EZISTR_T *chr16x12(

EZISTR_T *in,

int flag,

EZISTR_T *out,

int row);

Used for 16x12 or 12x12 large characters. If only UPPER CASE is required, then only the first 12 rows need to be formated.

EZISTR_T *chr12x7(

EZISTR_T *in,

int flag,

EZISTR_T *out,

int row);

EZISTR_T *chr9x5(

EZISTR_T *in,

int flag,

EZISTR_T *out,

int row);

EZISTR_T *chr7x5(

EZISTR_T *in,

int flag,

EZISTR_T *out,

int row);

EZISTR_T *chr7x4(

EZISTR_T *in,

int flag,

EZISTR_T *out,

int row);

This is an UPPER CASE only font: the 'lower case' characters are special symbols, not lower case.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 86 of 145

Page 87: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

32.4 Example: The Program 'lgchr'Please see the source code for lgchr.c which provides probably the best example on how to use this suite of functions. lgchr is used to generate big names, typically used at the top of source files, but could also, for instance, be used in scripts to generate a big 'warning'. lgchr's 'help' text is shown below.

lgchr 4.1 (c) 1991-2012 Alf Lacis <20120304> Build:Mar 4 2012 22:12:18

lgchr: create headers in various sizes to include in source code, text files, etc.

Usage:

lgchr [-s style] [-b n] [-t value|a|i] [-c [c|r|b|d]] -w minw [-f file]|[string1 [string2...]] >out

Where:

STYLE CASE ASCII FIXED/PROP BLANKS

-s style ===== =========== ========= ============ ======

a 16x12 UPPER+lower 32 -> 127 proportional 1

b 12x12 UPPER ONLY 32 -> 95 proportional 1

c 12x7 UPPER+lower 32 -> 127 proportional 2

d 9x5 UPPER+lower(*) 32 -> 127 proportional 1

e 7x5 UPPER ONLY 32 -> 95 proportional 1

f 7x4 UPPER+special(#) 32 -> 96 fixed fixed

(*) Default style is d = 9x5.

(#) Non-ASCII characters are declared in 97 to 127.

-b n Number of blanks between letters.

-t a means use the character to make the large letter (default=@)

i means use the IBM square block character (decimal 219)

value a value in decimal for the character to be displayed

-c c C format, i.e., "/*..." Default is C++: "//..."

-c r raw format, i.e., just the text, not a C or C++ header.

-c b bash format, i.e., use '#' for the comment start.

-c d cmd format, i.e., use 'REM ' for the comment start.

-w minw Minimum width of top & bottom 'lines', default is 100

-f file Read rows of strings from this file

string1, string2, etc - strings to be converted

Example:

lgchr -s a -t i -w 110 -f labels.txt >temp.txt

Note: Maximum output line length as at Mar 6 2012 is 2048.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 87 of 145

Page 88: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

33 MAX/MIN-family Macros, ezi_max-family TemplatesMAX, MIN, MAX3, MIN3, MAX4, MIN4

C++: ezi_min, ezi_max

33.1 SynopsisThe macros provide typical implementations of MIN and MAX. The family also includes macros which find the maximum or minimum of both 3 and 4 arguments, e.g., MIN3, MAX4.

The C++ versions, ezi_min and ezi_max, are overloaded templates with up to four parameters.

33.2 Usage#include "alflb.h" Note that there is no type associated with these macros and their

parameters. Being macros, the arguments are whatever type the programmer wishes.

/type/ MAX(

/type/ arg1, first argument to compare /type/ arg2); second argument to compare Returns: the value of the argument which is larger

/type/ MIN(

/type/ arg1, first argument to compare /type/ arg2); second argument to compare Returns: the value of the argument which is smaller

/type/ MAX3() as for MAX, but with 3 arguments

/type/ MIN3() as for MIN, but with 3 arguments

/type/ MAX4() as for MAX, but with 4 arguments

/type/ MIN4() as for MIN, but with 4 arguments

C++: template <typename T> Overloaded C++ templates for finding the minimum of 2, 3, & 4 parameters.

T ezi_min(T const &a, T const &b);

T ezi_min(T const &a, T const &b, T const &c);

T ezi_min(T const &a, T const &b, T const &c, T const &d);

Overloaded C++ templates for finding the maximum of 2, 3, & 4 parameters.

T ezi_max(T const &a, T const &b);

T ezi_max(T const &a, T const &b, T const &c);

T ezi_max(T const &a, T const &b, T const &c, T const &d);

33.3 Macro BugsAs for any macro, beware of side-effects in macro expansion. I have prevented some side-effects, but not all, by using lots of parentheses. Here is the code for these, so you can check for possible side-effects:

#define MAX(a,b) ((a)>(b)?(a):(b))

#define MIN(a,b) ((a)<(b)?(a):(b))

#define MAX3(a,b,c) MAX(MAX((a),(b)),(c))

#define MIN3(a,b,c) MIN(MIN((a),(b)),(c))

#define MAX4(a,b,c,d) MAX(MAX((a),(b)),MAX((c),(d)))

#define MIN4(a,b,c,d) MIN(MIN((a),(b)),MIN((c),(d)))

alflb_20120306.odt © 2002-2012 Alf Lacis Page 88 of 145

Page 89: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

33.4 Example 1: SnippetFind the height of the tallest of the three main pyramids at Giza:

maxheight = MAX3(Cheops.ht, Chephren.ht, Mycerinus.ht);

33.5 Example 2: Test Applicationint main(int argc, char *argv[]) { cout << "C/C++ macros\n"; cout << "MIN(" << 1 << "," << 2 << ")=" << MIN(1,2) << "\n"; cout << "MIN(" << 2 << "," << 1 << ")=" << MIN(2,1) << "\n"; cout << "MAX(" << 1 << "," << 2 << ")=" << MAX(1,2) << "\n"; cout << "MAX(" << 2 << "," << 1 << ")=" << MAX(2,1) << "\n"; cout << "MIN3(" << 1 << "," << 2 << "," << 3 << ")=" << MIN3(1,2,3) << "\n"; cout << "MIN3(" << 2 << "," << 3 << "," << 1 << ")=" << MIN3(2,3,1) << "\n"; cout << "MIN3(" << 3 << "," << 1 << "," << 2 << ")=" << MIN3(3,1,2) << "\n"; cout << "MAX3(" << 1 << "," << 2 << "," << 3 << ")=" << MAX3(1,2,3) << "\n"; cout << "MAX3(" << 2 << "," << 3 << "," << 1 << ")=" << MAX3(2,3,1) << "\n"; cout << "MAX3(" << 3 << "," << 1 << "," << 2 << ")=" << MAX3(3,1,2) << "\n"; cout << "MIN4(" << 1 << "," << 2 << "," << 3 << "," << 4 << ")=" << MIN4(1,2,3,4) << "\n"; cout << "MIN4(" << 2 << "," << 3 << "," << 4 << "," << 1 << ")=" << MIN4(2,3,4,1) << "\n"; cout << "MIN4(" << 3 << "," << 4 << "," << 1 << "," << 2 << ")=" << MIN4(3,4,1,2) << "\n"; cout << "MIN4(" << 4 << "," << 1 << "," << 2 << "," << 3 << ")=" << MIN4(4,1,2,3) << "\n"; cout << "MAX4(" << 1 << "," << 2 << "," << 3 << "," << 4 << ")=" << MAX4(1,2,3,4) << "\n"; cout << "MAX4(" << 2 << "," << 3 << "," << 4 << "," << 1 << ")=" << MAX4(2,3,4,1) << "\n"; cout << "MAX4(" << 3 << "," << 4 << "," << 1 << "," << 2 << ")=" << MAX4(3,4,1,2) << "\n"; cout << "MAX4(" << 4 << "," << 1 << "," << 2 << "," << 3 << ")=" << MAX4(4,1,2,3) << "\n"; cout << "C++ template functions\n"; cout << "ezi_min(" << 1 << "," << 2 << ")=" << ezi_min(1,2) << "\n"; cout << "ezi_min(" << 2 << "," << 1 << ")=" << ezi_min(2,1) << "\n"; cout << "ezi_max(" << 1 << "," << 2 << ")=" << ezi_max(1,2) << "\n"; cout << "ezi_max(" << 2 << "," << 1 << ")=" << ezi_max(2,1) << "\n"; cout << "ezi_min(" << 1 << "," << 2 << "," << 3 << ")=" << ezi_min(1,2,3) << "\n"; cout << "ezi_min(" << 2 << "," << 3 << "," << 1 << ")=" << ezi_min(2,3,1) << "\n"; cout << "ezi_min(" << 3 << "," << 1 << "," << 2 << ")=" << ezi_min(3,1,2) << "\n"; cout << "ezi_max(" << 1 << "," << 2 << "," << 3 << ")=" << ezi_max(1,2,3) << "\n"; cout << "ezi_max(" << 2 << "," << 3 << "," << 1 << ")=" << ezi_max(2,3,1) << "\n"; cout << "ezi_max(" << 3 << "," << 1 << "," << 2 << ")=" << ezi_max(3,1,2) << "\n"; cout << "ezi_min(" << 1 << "," << 2 << "," << 3 << "," << 4 << ")=" << ezi_min(1,2,3,4) << "\n"; cout << "ezi_min(" << 2 << "," << 3 << "," << 4 << "," << 1 << ")=" << ezi_min(2,3,4,1) << "\n"; cout << "ezi_min(" << 3 << "," << 4 << "," << 1 << "," << 2 << ")=" << ezi_min(3,4,1,2) << "\n"; cout << "ezi_min(" << 4 << "," << 1 << "," << 2 << "," << 3 << ")=" << ezi_min(4,1,2,3) << "\n"; cout << "ezi_max(" << 1 << "," << 2 << "," << 3 << "," << 4 << ")=" << ezi_max(1,2,3,4) << "\n"; cout << "ezi_max(" << 2 << "," << 3 << "," << 4 << "," << 1 << ")=" << ezi_max(2,3,4,1) << "\n"; cout << "ezi_max(" << 3 << "," << 4 << "," << 1 << "," << 2 << ")=" << ezi_max(3,4,1,2) << "\n"; cout << "ezi_max(" << 4 << "," << 1 << "," << 2 << "," << 3 << ")=" << ezi_max(4,1,2,3) << "\n"; return 0; }

alflb_20120306.odt © 2002-2012 Alf Lacis Page 89 of 145

Page 90: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

$ g++ -o test_min_family -I.. -Wall -Os test_ezi_min.cpp -L.. -lalflb -Wl,-M >test_min_family.map$ ./test_min_familyC/C++ macrosMIN(1,2) => 1MIN(2,1) => 1MAX(1,2) => 2MAX(2,1) => 2MIN3(1,2,3) => 1MIN3(2,3,1) => 1MIN3(3,1,2) => 1MAX3(1,2,3) => 3MAX3(2,3,1) => 3MAX3(3,1,2) => 3MIN4(1,2,3,4) => 1MIN4(2,3,4,1) => 1MIN4(3,4,1,2) => 1MIN4(4,1,2,3) => 1MAX4(1,2,3,4) => 4MAX4(2,3,4,1) => 4MAX4(3,4,1,2) => 4MAX4(4,1,2,3) => 4C++ template functionsezi_min(1,2) => 1ezi_min(2,1) => 1ezi_max(1,2) => 2ezi_max(2,1) => 2ezi_min(1,2,3) => 1ezi_min(2,3,1) => 1ezi_min(3,1,2) => 1ezi_max(1,2,3) => 3ezi_max(2,3,1) => 3ezi_max(3,1,2) => 3ezi_min(1,2,3,4) => 1ezi_min(2,3,4,1) => 1ezi_min(3,4,1,2) => 1ezi_min(4,1,2,3) => 1ezi_max(1,2,3,4) => 4ezi_max(2,3,4,1) => 4ezi_max(3,4,1,2) => 4ezi_max(4,1,2,3) => 4$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 90 of 145

Page 91: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

34 Memory All the Same Value? - memall

34.1 SynopsisChecks that every char in the block is equal to value. Typically used to check if the block is RAM-empty ('\0') or ROM-empty (0xff).

Roughly based on strcmp from K&R The C Programming Language, 1st Ed, page 101.

34.2 Usage#include <stddef.h>

#include "alflb.h"

For size_t.

int memall(

const void *mem, pointer to memory to be tested int value, value to test memory against (Note: it is an int in the same style of the

ANSI-C function memset). size_ t count); number of bytes to compare Returns: Returns: 0 if memory is all the value,

else 1 if mismatch.

34.3 ExampleTest if a block of memory is all hexadecimal FF:

if ( memall(Flash_Block[ii], 0xff, (size_t)(Flash[ii+1] - Flash[ii])) != 0 )

{

sprintf(tuf,"ERROR: mem check block %d failed\r\n", ii ); trace(tuf);

ret = FLASH_ERASE_FAIL_2;

}

else

{

// sprintf(tuf,"ERROR: mem check block %d OK\r\n", ii ); trace(tuf);

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 91 of 145

Page 92: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

35 Memory Fill with Copies of the 'from' buffer - memfill

35.1 SynopsisThis works similarly to memset, but memset can only set one byte. memfill creates multiple copies of the from buffer in to, with suitable checks for overflow, etc.

35.2 Usage#include <stddef.h>

#include "alflb.h"

For size_t.

void *memfill(

void *to,

void *from,

size_t to_size,

size_t from_size);

Returns:

Fills to memory with copies of the from memory. If using this to fill a string, you need to add the terminating '\0' in your own code.

The address to.

35.3 Example#ifdef MEMFILL_TEST_APP

#include <stdio.h>

#include <string.h>

#define BUFSZ 22

int main(void)

{

char big[BUFSZ+1]; // note "+1"

char tiny[] = "World";

memfill(big, tiny, BUFSZ, strlen(tiny));

big[BUFSZ] = '\0';

printf("big is '%s'\n", big);

return 0;

}

#endif

$ gcc -Wall -DMEMFILL_TEST_APP -o memfill memfill.c

$ ./memfill

big is 'WorldWorldWorldWorldWo'

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 92 of 145

Page 93: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

36 Memory Function Wrappers - MEMSETSZ, etcMEMSETSZ, MEMCMPSZ, MEMCPYSZ, MEMMOVESZ, MEMCCPYSZ

36.1 SynopsisSome simple macros which automatically fill in the sizeof parameter for various standard C library functions.

36.2 Usage#include <stddef.h>

#include "alflb.h"

For size_t.

void *MEMSETSZ(

void *to,

int c)

Returns:

As for memset, fills sizeof(to) bytes in to with c.

returns the address to

int MEMCMPSZ(

void *s1,

void *s2)

Returns:

As for memcmp, compares sizeof(to) bytes between s1 & s2.

returns a negative negative, zero, or positive value.

void *MEMCPYSZ(

void *to,

void *from)

Returns:

As for memcpy, copies sizeof(to) bytes from from to to. Copying is overlap-unsafe.

returns the address to

void *MEMMOVESZ(

void *to,

void *from)

Returns:

As for memmove, copies sizeof(to) bytes from from to to. Copying is overlap-safe.

returns the address to

void *MEMCCPYSZ(

void *to,

void *from,

c)

Return:

As for memccpy, which copies bytes from from to to, stopping after the first occurrence of byte c.

a pointer to the byte after the copy of c in s1, or a NULL pointer if c was not found

36.3 ExampleCopy one array to another, first using memmove, then using MEMMOVESZ:

#define BUF_SIZE

char to[BUF_SIZE];

char from[BUF_SIZE];

...

memmove(to, from, sizeof(to);

MMEMOVESZ(to, from);

alflb_20120306.odt © 2002-2012 Alf Lacis Page 93 of 145

Page 94: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

37 Memory Backup Functions - mem_backup, etcmem_backup, mem_restore

37.1 SynopsisFunctions to back up & restore memory. Optionally, you can build the library with a CRC added to the restore to ensure safety of storage.

To build the library to use a CRC algorithm, #define MEM_BACKUP_CRC. The library will then use bytewisecrc32 by default. See Alf if you want these memory routines to use a different CRC algorithm.

mem_restore releases the memory allocated in mem_backup.

37.2 Usage#include <stddef.h>

#include "alflb.h"

For size_t.

void *mem_backup(

void **backup,

void *mem,

size_t length);

Returns:

Allocates & backs up memory.

NULL if memory could not be allocated.

int mem_restore(

void **backup,

void *mem,

size_t length) ;

Returns:

Restores memory, frees memory allocated in mem_backup).

1 if backup was NULL;2 if the CRC failed.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 94 of 145

Page 95: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

37.3 Example#ifdef MEM_BACKUP_TEST_APP

#include <stdio.h>

#define COUNT 70

int main(void)

{

char str[COUNT+1];

int ii;

void *backup;

for ( ii = 0; ii < COUNT; ii++ )

str[ii] = '!' + ii; // put characters '!', '"', '#', etc, into str[]

str[COUNT] = '\0';

printf("str is %s\n", str);

mem_backup(&backup, str, sizeof(str));

memset(str, '@', sizeof(str)-1); // overwrite string with '@'

printf("str is %s\n", str);

mem_restore(&backup, str, sizeof(str)); // restore the string

printf("str is %s\n", str);

return 0;

}

#endif

$ gcc -Wall -o mem_backup -DMEM_BACKUP_TEST_APP mem_backup.c

$ ./mem_backup

str is !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef

str is @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

str is !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 95 of 145

Page 96: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

38 Memory Search using the Boyer-Moore AlgorithmBoyerMoore_Find

38.1 SynopsisVery fast string search routine using the Boyer-Moore algorithm. Refer to programming texts or the web for a discussion of the algorithm.

A wonderful peculiarity of the Boyer-Moore Algorithm is that the longer the search string, the shorter the search time, i.e., the search time is inversely proportional to the key length.

The main search function was rewritten from scratch when P.Ko's original version was not found to be thread-safe, and the reverse search had an algorithm flaw.

NOTE: in limited-memory environments, note that the function uses a 'large' (everything is relative) array of 256 bytes, created on the stack, along with ½ dozen other variables required.

38.2 Usage#include "alflb.h"

void *BoyerMoore_Find(

void *vdata,

size_t data_len,

void *vpattern,

size_t patt_len);

Returns:

Tries to find the pattern requested in data.

Returns NULL if patt_len is not 1 through 256, or if the pattern is not found, otherwise returns the address of the beginning of pattern found in data.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 96 of 145

Page 97: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

38.3 Example: Test ApplicationThe test application contained within boyermoore.c searches for several strings in a large (100,000,000 byte) data array:

#ifdef TEST_APP_BOYERMOORE

#include <stdlib.h> // for malloc()

int main(int argc, char *argv[])

{

#define DMAX 100000000

#define NEAREND (DMAX - 500)

#define FROGHOLLOW "froghollow"

#define TREESTUMP "treestump"

#define VERYLAST "verylast"

char *data;

char *find;

char *found;

char *yes = "found \"%s\" adr(data):%p adr(found):%p delta=%d\n";

char *no = "not found \"%s\" adr(data):%p adr(found):%p\n";

if ( NULL == (data = malloc(DMAX)) )

return 1;

memset(data, 0, DMAX);

memcpy(data + 0, FROGHOLLOW, strlen(FROGHOLLOW));

memcpy(data + 10, FROGHOLLOW, strlen(FROGHOLLOW));

memcpy(data + NEAREND + 0, TREESTUMP , strlen(TREESTUMP ));

memcpy(data + NEAREND + 8, TREESTUMP , strlen(TREESTUMP )); // overlaps

memcpy(data + DMAX - strlen(VERYLAST), VERYLAST, strlen(VERYLAST));

find = FROGHOLLOW;

found = (char*)BoyerMoore_Find(data, DMAX, find, strlen(find));

if ( found ) printf(yes, find, data, found, found-data);

else printf(no , find, data, found);

find = TREESTUMP;

found = (char*)BoyerMoore_Find(data, DMAX, find, strlen(find));

if ( found ) printf(yes, find, data, found, found-data);

else printf(no , find, data, found);

find = VERYLAST;

found = (char*)BoyerMoore_Find(data, DMAX, find, strlen(find));

if ( found ) printf(yes, find, data, found, found-data);

else printf(no , find, data, found);

return 0;

}

#endif

38.4 OutputThe output from the test application is:

$ gcc -Wall -I.. -g -o test_boyermoore -Os -DTEST_APP_BOYERMOORE ../boyermoore.c

$ ./test_boyermoore

102(f)=9 103(g)=6 104(h)=5 108(l)=2 111(o)=1 114(r)=8

found "froghollow" adr(data):0xb1e70008 adr(found):0xb1e70008 delta=0

101(e)=5 109(m)=1 114(r)=7 115(s)=4 116(t)=3 117(u)=2

found "treestump" adr(data):0xb1e70008 adr(found):0xb7dcdf1c delta=99999508

97(a)=8 98(b)=4 99(c)=6 101(e)=1 104(h)=5 109(m)=9 111(o)=3 116(t)=7 120(x)=2

found "verylast" adr(data):0xb1e70008 adr(found):0xb7dce100 delta=99999992

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 97 of 145

Page 98: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

39 Memory X-Or - memxormemxor

39.1 SynopsisThis function Exclusive-Ors a buffer with a passed-in pattern.

39.2 Usage#include "alflb.h"

UCHAR *memxor(

UCHAR str[], Data buffer to be modified in situ, i.e., in place. size_t str_length, The length of the data buffer. UCHAR pattern[], The X-Or pattern to be applied to str. size_t pat_length); The length of the pattern buffer. Returns: A copy of the str address.

39.3 ExampleThe memxor.c file contains an example application:

#include <stdio.h>

void print(UCHAR data[], size_t len)

{

size_t ii;

for ( ii = 0; ii < len; ii++ )

{

printf("%02X ", data[ii]);

if ( ii & 1 )

printf(" ");

}

}

int main(void)

{

UCHAR buf[] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,

0x41, 0x41, 0x5A, 0x5A, 0xA5, 0xA5, 0xFF, 0xFF };

UCHAR pat[] = { 0xA5, 0x33 };

printf("Pattern is : "); print(pat, sizeof(pat)); printf("\n");

printf("Buffer before: "); print(buf, sizeof(buf)); printf("\n");

memxor(buf, sizeof(buf), pat, sizeof(pat));

printf("Buffer after : "); print(buf, sizeof(buf)); printf("\n");

return 0;

}

39.4 Output from ExampleCompile & run the test application with these commands:

$ gcc -Wall -Os -o memxor -DTEST_APP_MEMXOR memxor.c

$ ./memxor

Pattern is : A5 33

Buffer before: 00 00 01 01 02 02 03 03 41 41 5A 5A A5 A5 FF FF

Buffer after : A5 33 A4 32 A7 31 A6 30 E4 72 FF 69 00 96 5A CC

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 98 of 145

Page 99: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

40 Millisecond Timing: Real Time Clock Functionstimer_msec_get, timer_msec, timer_msec_ended, timer_msec_increment, TIMER_MSEC_FMT_SZ,

timer_msec_fmt, timer_msec_free_running_counter

40.1 SynopsisThis suite provides a 1 millisecond resolution timer, with associated timing functions. A formatting function is also available to those systems which have sprintf.

This suite is designed to be extremely low-impact: i.e., to have the absolute minimal amount of CPU processing performed in the ISR (Interrupt Service Routine). The target must have an ISR or other method of calling the lightweight macro timer_msec_increment every millisecond which increments a global variable called timer_msec_free_running_counter. Systems that do not have this resolution in the ISR will have to manually manipulate this global variable, e.g., for a 10-millisecond timer ISR, timer_msec_free_running_counter must be incremented by 10.

As a ULONG, the timer wraps around after every 232-1 or 4294967295 milliseconds which is equal to 49 days, 17 hours, 2 minutes, 47.295 seconds, however, the timing routines are designed to handle this wrap-around. In other words, you can have a timer which can be up to 49.something days in length.

40.2 Usage#include "timer_msec.h" This also includes alflb.h.

void

timer_msec_increment(void);

extern volatile ULONG

timer_msec_free_running_counter;

timer_msec_increment must be called by a timer ISR every millisecond, or alternately, the global variable timer_msec_free_running_counter must be manually manipulated by the ISR. E.g., for a 10-millisecond timer ISR, timer_msec_free_running_counter must be incremented by 10.

ULONG timer_msec_get(void); Effectively starts, or restarts, a timer by getting a copy of the current millisecond clock. E.g.: my_timer = timer_msec_get();

Returns: Returns a copy of timer_msec_free_running_counter. If timer_msec_free_running_counter has wrapped back to 0, will return the value 1 instead of 0.

ULONG timer_msec(

ULONG my_timer);

This returns the time since my_timer was started. Allows for the 49-day wrap-around. E.g.: a 45 day timer could be: if ( timer_msec(my_timer) >= (45ul * TIMER_MSEC_DAY) )

// do something

Returns: Returns time in milliseconds since my_timer was started.

int timer_msec_ended(

ULONG my_timer,

/type/ max_timer);

If my_timer is non-zero, tests if it has expired. By having a test for my_timer == zero, this can effectively turn the timer off. This is actually a macro wrapper around timer_msec_ended_private which has a cast for max_timer to a ULONG (which is why it is labelled /type/ in the prototype to the left). Since the value for max_timer is typeless, you can use types smaller than ULONG for intervals shorter than 65.535 seconds, e.g., USHORT, or even UCHAR (for intervals shorter than 0.255 seconds). E.g. a timer for 2 days: if ( timer_msec_ended(my_timer, 2ul * TIMER_MSEC_DAY) )

// do something

Returns: Returns 1 if expired, 0 otherwise.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 99 of 145

Page 100: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

#define TIMER_MSEC_FMT_SZ (13)

char *timer_msec_fmt(

char pstring[],

char suffix,

ULONG my_timer);

Formats a timer_msec time as the string nnnnnnn.nnn? using sprintf where ? is the suffix. pstring should be at least TIMER_MSEC_FMT_SZ in length. suffix can be '\0', but is typically also ' '(space) or some delimiter such as '>'. E.g.: char str[TIMER_MSEC_FMT_SZ];

printf("%s Err %d\n",

timer_msec_fmt(str, '>', timer_msec_get()),

err);

Returns: Returns a pointer to pstring.

40.3 ExampleThis shows the use of timer_msec_increment in an ISR:

__interrupt__(vector=176) void ISR_TIMER( void )

{

timer_msec_increment();

// Other timer-related stuff...

}

The following shows code from a state machine which was implemented as a switch statement:

...

...

case MOVE:

if ( STATUS_OK == move(xto, yto, xfrom, yfrom) )

{

wait = timer_msec_get(); // start the wait timer

state = WAITING;

}

break;

case HOLD_OFF:

hold_off = wait;

wait = 0ul; // prevents timer_msec_ended() below, returning TRUE

break;

case CARRY_ON:

wait = hold_off; // this continues the held-off timer immediately

break;

case WAITING:

if ( timer_msec_ended(wait, config.wait) ) // config.wait is a USHORT

{

state = CLOSE;

}

break;

case CLOSE:

...

...

alflb_20120306.odt © 2002-2012 Alf Lacis Page 100 of 145

Page 101: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

41 Nibble Array SuiteNIB_MAX_BYTES, NIB_DECLARE, NIB_SET, NIB_GET, NIB_ALL

41.1 SynopsisThis suite of functions and macros provide a method of manipulating nibbles in an array of nibbles, in a similar manner of manipulating a character or integer array. Useful for flags containing the values 0 through 0xF (1510). The resultant nibble array is ½ the size of an unsigned char array to hold the same 0 through 0xF values.

If used between threads for the same array, calls to the Nibble Array functions must be fenced between semaphores, critical sections or other mechanism.

41.2 Usage#include "nibblefs.h"

/typeless/ NIB_MAX_BYTES(

nib_max)

Macro for calculating the number of bytes to hold nib_max nibbles.

unsigned char NIB_DECLARE(

nib_array,

nib_max)

Macro for declaring an unsigned char array sufficiently large to hold nib_max nibbles. Uses NIB_MAX_BYTES.

void NIB_SET(

unsigned char *nib_array,

int value,

size_t nib_no);

Function to set the addressed nibble to value.

int NIB_GET(

unsigned char *nib_array,

size_t nib_no);

Function to get the addressed nibble.

unsigned char *NIB_ALL(

unsigned char *nib_array,

int value,

size_t nib_max);

Set the whole nibble array to value. Similar in concept to the C-Library function memset for byte arrays.

41.3 ExampleDeclare and use a large nibble array:

#define NIBMAX 256000UL

...

NIB_DECLARE(tidbits, NIBMAX); // declare the nibble array 'tidbits'

...

NIB_ALL(tidbits, 0xA, NIBMAX); // set the whole nibble array to the hex value A

...

NIB_SET(tidbits, 3, 200); // set the 201st element of tidbits to the value 3

...

// manipulate other nibbles

...

if ( NIB_GET(tidbits, 200) == 3 ) // check the value of this addressed nibble

// do something

alflb_20120306.odt © 2002-2012 Alf Lacis Page 101 of 145

Page 102: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

42 No-Operation Functionsnoop, nooploop, loopfunc

42.1 SynopsisSometimes, for whatever reason, you may need a 'no-operation' function. It may be for macro-substitution, timing, setting a break-point or other reason.

These two functions provide no-operation, and looped no-operation capabilities.

noop typically uses two opcodes: one for the Jump to Subroutine (JSR or branch depending on architecture), and the second opcode to Return. nooploop typically uses about ½ dozen opcodes: a couple to increment the loop counter; a couple to test the loop counter, and 2 to call noop. Check your compiler output if you need to know the exact number.

42.2 Usage#include "alflb"

void noop(void); No-operation: returns immediately.

void nooploop(

ULONG loops);

Actually a macro, this will call noop the requested number of times.

void loopfunc(

void_function_ptr vfptr,

ULONG loops)

Calls the requested void <name>(void) function the requested number of times.

42.3 ExamplesDeclare some timing function:

#define WAIT_FOR_EEPROM nooploop(SCALED_MICROSECOND*25) // Wait for about 25 microseconds

Use otherwise empty functions, when debugging is no longer required, but still provide the ability to set breakpoints using an IDE:

#ifdef DEBUGGING

#define debug_int(value) printf("%d", value)

#else

#define debug_int(value) noop() // Can still set breakpoints on this line of code

#endif

...

if ( value != 0 )

debug_int(value); // Can still set a breakpoint on this line of code

// otherwise the compiler may optimise and remove

// this whole block.

Simple blocking wait function which 'pats' the CPU's watchdog. The number 1736 was found through experimentation:

// multiplier found from stop-watch timing

#define ROUGH_WAIT(milliseconds) loopfunc(wdt_func(), milliseconds * 1736)

...

ROUGH_WAIT(10000ul); // Wait roughly 10 seconds.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 102 of 145

Page 103: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

43 Null Functionnull

43.1 SynopsisSometimes, for whatever reason, you may need a null function. It may be for macro-substitution, timing, setting a break-point or other reason. This function provides these capabilities, along with an int return which may be useful.

43.2 Usage#include "alflb"

extern int

null_default_return;

Default null return value. Initialised to 0. This global variable is not thread-safe.

int null(

void *junk,

... );

Returns:

Nearly empty function that returns immediately.ISO C requires a named argument before ...

The value of null_default_return.

43.3 Examples#ifdef DEBUGGING

#define debug_return() null(NULL)

#else

#define debug_return() STATUS_OK

#endif

...

return debug_int(); // Can still set a breakpoint in null(), and change the return

// value if required.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 103 of 145

Page 104: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

44 Percentage Progress CalculatorfProgCalc, ProgCalc

44.1 Synopsis & ExampleVery often, it is really nice to display a percentage complete or percent progress. However, difficulties arise if we are not doing the calculation from 0 to 100.

Using an example, where there are four stages:The first stage has 32 steps and takes, on average, 4 seconds.The second stage has 3 discrete (non-counting) steps over 4 seconds.The third stage has 2048 steps and takes, on average, say 120 seconds.The last stage has 64 steps and takes, on average, say 12 seconds.

You can use the following two routines like this. First, split the stages into percentages which are similar to seconds, but not exactly:

The first stage we will call 0 to 4 %The second stage we will call 5# to 7 %The third stage we will call 8# to 90 %The last stage we will call 91# to 100 %

# You can butt the start of the next stage to the end of the previous one, like this:0 to 4 %4 to 7 %7 to 90 %90 to 100 %

but it iss nicer to have a little jump in the output.

Next, in your stages, use the Percentage Progress Calculator like this. The first stage:

Max = 32;

for ( step = 0; step < Max; step++ )

{

display ( ProgCalc(step, Max, 0, 4) );

// DO SOMETHING

}

The second stage: we do not use the Progress Calculator, just discrete numbers:

// DO SOME DISCRETE STEP

display(5); // just display the numbers!

// DO SOME DISCRETE STEP

display(6);

// DO SOME DISCRETE STEP

display(7);

The third stage:

Max = 2048;

for ( step = 0; step < Max; step++ )

{

display ( ProgCalc(step, Max, 8, 90) );

// DO SOMETHING

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 104 of 145

Page 105: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

The last stage:

Max = 64;

for ( step = 0; step < Max; step++ )

{

display ( ProgCalc(step, Max, 91, 100) );

// DO SOMETHING

}

The actual calculation is this:

( Numerator )

JobPercentage = (------------ x (JobMaxPercentage - JobMinPercentage )) + JobMinPercentage

( Denominator )

The integer version ProgCalc is tailored so that truncation should not be a problem doing integer division by Denominator. The floating version follows the same structure, even though truncation is not a problem.

44.2 Usage#include "progcalc.h" Parameters are have identical purpose, although one has all float

parameters, and the other has all int parameters:

int ProgCalc( Integer version of routine int Numerator, this is like step in the above examples int Denominator, this is the maximum value for step int JobMinPercent, lower percent figure for range calculation int JobMaxPercent); upper percent figure for range calculation Returns: the calculated percentage

float fProgCalc( Floating point version of routine float Numerator,

float Denominator,

float JobMinPercent,

float JobMaxPercent);

Returns:

alflb_20120306.odt © 2002-2012 Alf Lacis Page 105 of 145

Page 106: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

45 Plural Selectorplural, plurals

45.1 SynopsisSimple routines to select a string based on a numeric value, typically for a user interface. It helps with the vagaries of the English language. For example:

There are no men.There is one man.There are many men.

45.2 Usage#include "alflb.h"

char *plural(

int value);

Returns:

Returns a pointer to "s" if plural or zero, and a pointer to "" if 1.

Address of static string "s" or ""

char *plurals(

int value,

char *zero,

char *one,

char *many);

Returns:

Returns the address of one of the strings zero, one or many depending on value.

Returns the address zero, one or many.

45.3 Example#include "alflb.h"

...

for ( ii = 0; ii < 4; ii++ )

{

printf("%d => There %s.\n", ii, plurals(ii, "are no men", "is one man", "are men"));

}

45.4 Output of Example0 => There are no men.

1 => There is one man.

2 => There are men.

3 => There are men.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 106 of 145

Page 107: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

46 Pointer - Casting and SettingCAST_PTR, CAST_SET

46.1 SynopsisThese macros provide a shorthand method of creating a pointer of a different type, but only having to specify the type once in the statement, not twice as is the usual situation, for example:

command_message_t *pmessage = (command_message_t*)buffer;

where "command_message_t *" is written twice.

Note: some compilers do not allow you to have two successive CAST_SET definitions, because this mixes declarations with instantiations, see note below.

46.2 Usage#include "alflb.h"

void CAST_PTR(

type_cast,

new_ptr,

old_address)

Returns: void

Creates a pointer of the type type_cast, and points it onto old_address.

void CAST_SET(

type_cast,

new_ptr,

old_address,

val)

Returns: void

Similar to above, but also performs a memset on the area of memory.

46.3 ExampleThe shorthand for these three lines:

command_receive_t *pRx = (command_receive_t *)rBuf;

command_transmit_t *pTx = (command_transmit_t *)tBuf;

memset(pTx, 0, sizeof(*pTx));

is the following two lines:

CAST_PTR(command_receive_t , pRx, rBuf);

CAST_SET(command_transmit_t, pTx, tBuf, 0);

46.4 Note: Successive DefinitionsSome compilers, e.g., Renesas HEW, do not allow you to do this. GNU GCC does allow this, since GCC allows mixing declarations with instantiations.

CAST_SET(his_type, aWoman, data, 0);

CAST_SET(her_type, aMan , data, 0);

alflb_20120306.odt © 2002-2012 Alf Lacis Page 107 of 145

Page 108: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

47 Pointer - return memory & nullify pointerNULLIFY

47.1 SynopsisThis macro provides a one-stop-shop for testing a pointer, freeing memory, then setting that pointer to the value NULL. Probably the main inspiration for this routine came when I wanted to know if any particular malloced (realloced, strduped, etc) memory had been freed or not. The ANSI free function does not set the value of the pointer to show that it is now longer used, i.e., e.g., NULL. (cannot! why? because the pointer is passed by value.) This macro routine helps fix that lack of functionality.

47.2 Usage#include "alflb.h" Note that there is no type associated with this macro and its

parameter.

void NULLIFY( Your one-stop-shop for freeing malloced, realloced, strduped, etc, memory.

void *ptr); Pointer to be freed, then flagged as freed. Returns: nothing.

47.3 ExampleDeclare and malloc some pointers:

char *pFred = NULL;

char *pSally = NULL;

if ( NULL == (pFred = malloc(FREDSIZE )) ) malloc_error(FREDSIZE );

if ( NULL == (pSally = malloc(SALLYSIZE)) ) malloc_error(SALLYSIZE);

pFred and pSally are used in our program. Now, nullify one of our pointers:

NULLIFY(pSally);

At this point, by inspecting pFred and pSally we can tell if the pointers are still pointing to valid memory or not, because NULLIFY sets them to NULL:

printf("pFred = %s\n" , pFred ? "valid": "returned to pool");

printf("pSally = %s\n\n", pSally? "valid": "returned to pool");

Now free everything, but it does not matter if a pointer is already NULL, because NULLIFY tests for this:

NULLIFY(pFred );

NULLIFY(pSally); // this is still allowed

printf("pFred = %s\n" , pFred ? "valid": "returned to pool");

printf("pSally = %s\n\n", pSally? "valid": "returned to pool");

47.4 Output from above examplepFred = valid

pSally = returned to pool

pFred = returned to pool

pSally = returned to pool

alflb_20120306.odt © 2002-2012 Alf Lacis Page 108 of 145

Page 109: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

48 Queues - The Ezi Queue Function Suiteeziq_init, eziq_check, eziq_empty, eziq_full, eziq_num, eziq_add, eziq_get, eziq_delete,

eziq_scan

C++: eziqueue::eziqueue, ~eziqueue, check, empty, full, num, add, get, del, scan_init,

scan

48.1 SynopsisThe Ezi Queue suite provides a highly reusable queue library. A queue is a FIFO (first in, first out) data structure.

The Ezi Queue structure, unlike some other queue libraries, actually contain the records within the queue structures: other libraries typically store only a pointer. This makes the Ezi Queue library ideal where structures may be allocated dynamically or statically, e.g. embedded programming environments.

Unlike many other queue libraries, the 'get' function does not consume the head of the queue. This means that the 'head' is available as often as needed to different parts of your program. Then, when you have acted on the 'head' entry, an explicit 'delete' function is called.

Most of the Ezi Queue library does not use malloc, etc, although the structures you create can be malloced before calling eziq-init and the other Ezi Queue functions. The exception is one of the C++ constructors: the constructor that does not pass the pstorage pointer uses malloc to create the storage buffer.

If used between threads for the same queue, calls to the Ezi Queue functions must be fenced between semaphores, critical sections or other mechanism.

Records stored in an Ezi Queue are variable in length, up to 255 bytes. The size of the an Ezi Queue memory buffer can be up to ULONG_MAX bytes long.

Here is a flow-chart which represents some typical usage:

___________________________ | EZIQUEUE_T queue; | | UCHAR storage[xx]; | |___________________________| | ______V________ Initialises queue structure. | eziq_init | Can also be used to purge |_______________| the queue completely. | ___________________________ | ______________________________________| | | | ____ || _V_____V_____V____V_ | || | eziq_add | | Adds to tail || |____________________| | || _____________| | |___| || | | || __________V____________ | || | marker = queue.head | | || | C++: use scan_init | | This is a get/delete loop || |_______________________| | _____________________________ || | ____ | | ____ | || _______V______V_ | Scans __V___V_____V_ | | || | eziq_scan | | through | eziq_get | | Reads head. | || |________________| | queue |______________| | (Multiple gets | || | | |___| | |___| read the same | ||________| |____________________________ | record) | | | | ___ | | ___V___V_______V_ | | | | eziq_delete | | Deletes | | |_________________| | head | | | | |___| | | | |___________________________| | |_________________________________|

alflb_20120306.odt © 2002-2012 Alf Lacis Page 109 of 145

Page 110: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

48.2 Usage#include "eziqueue.h"

EZIQUEUE_T <Ezi Queue name>;

#define SIZE nnn

UCHAR <storage[SIZE]>;

Typically, you need:- the Ezi Queue structure,- something describing the size of the data storage buffer, and- the UCHAR data storage buffer.

void eziq_init(

EZIQUEUE_T *peq,

size_t maxsize,

UCHAR *pstorage);

Initialises the Ezi Queue structure peq. Can also used to completely empty the queue. Does not use malloc.

int eziq_check(

EZIQUEUE_T *peq,

size_t maxsize,

UCHAR *pstorage);

Checks some variables to ensure the Ezi Queue's health, and scans through the Ezi Queue. Returns: 0 if everything is OK; -1 head marker corrupt -2 tail marker corrupt -3 number of records is corrupt -4 storage size has changed since initialisation -5 storage address has changed since initialisation -6 head & tail markers indicate queue is empty, but record number is not zeroTODO -7 number of records do not match scan-through countTODO -8 internal record markers are corrupt

int eziq_empty(

EZIQUEUE_T *peq);

Returns 1 if the Ezi Queue is empty.

int eziq_full(

EZIQUEUE_T *peq,

UCHAR size);

Returns 1 if the Ezi Queue is too full to hold the next record of size size.

size_t eziq_num(

EZIQUEUE_T *peq);

Returns number of records in the Ezi Queue.

int eziq_add(

EZIQUEUE_T *peq,

void *vrecord,

UCHAR size);

Adds a record, if room, to the tail of the Ezi Queue. Returns: 1 if the record could not be added to the Ezi Queue.

int eziq_get(

EZIQUEUE_T *peq,

void *vrecord,

UCHAR *size,

size_t sizeof_buf);

Gets a copy of the record at the head of the Ezi Queue. Does not delete it! Returns: 0 if record returned OK. 1 if the Ezi Queue is empty. -1 if the returned record could not fit in record, and has been truncated. -2 if the returned record size is greater than the whole queue => indicates corrupt queue structure.

int eziq_delete(

EZIQUEUE_T *peq);

Deletes the entry at the head of the Ezi Queue. Returns 1 if the Ezi Queue is now empty.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 110 of 145

Page 111: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

int eziq_scan(

EZIQUEUE_T *peq,

size_t *marker,

void *vrecord,

UCHAR *size,

size_t sizeof_buf);

Copies the marker record into the buffer, does not alter the Ezi Queue. marker is a pointer relative to the start of the Ezi Queue buffer. Before the first use, set *marker to the value of peq->head. Returns: 0 success 1 Tail reached -1 destination buffer not large enough -2 undefined error

class eziqueue

{

public:

eziqueue(

size_t maxsize,

UCHAR *pstorage);

eziqueue(

size_t maxsize);

~eziqueue();

C++ Ezi Queue class.

Two constructors, and a destructor. The first constructor allows you to pass in a storage buffer: the second constructor mallocs the storage buffer.

int check(

size_t maxsize,

UCHAR *pstorage);

int check(

size_t maxsize);

Two check functions: pick the one that matches the constructor that was used. See eziq_check above for return values.

int empty(); Returns true if the queue is empty.

int full(

UCHAR size);

Returns true if a record of size size will not fit.

size_t num(); Returns the number of entries in the queue.

int add(

void *vrecord,

UCHAR size);

Adds a record, if room, to the tail of the Ezi Queue. Returns: 1 if record could not be added to the Ezi Queue.

int get(

void *vrecord,

UCHAR *size,

size_t sizeof_buf);

Gets a copy of the record at the head of the Ezi Queue. Does not delete it! See eziq_get above for return values.

int del(); Deletes the entry at the head of the Ezi Queue. Returns 1 if the Ezi Queue is now empty.

size_t scan_init(); Sets up an internal state variable where the queue can be scanned with the following function, scan. Returns the number of entries in the queue.

int scan(

void *vrecord,

UCHAR *size,

size_t sizeof_buf);

};

Copies the next record into the buffer, does not alter the Ezi Queue. Before the first use, call scan_init. See eziq_scan above for return values.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 111 of 145

Page 112: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

48.3 Example 1#include <stdio.h>

#include "eziqueue.h"

#define MAXQBUF 80000

#define READMAX 10

int main(int argc, char *argv[])

{

EZIQUEUE_T myq;

UCHAR qbuffer[MAXQBUF];

char *hello[] = { "Hello", "World!!!", "How are you?", NULL };

int ii;

char record[READMAX+1];

UCHAR result_len;

int read_status;

eziq_init(&myq, MAXQBUF, qbuffer); // intialises the myq structure.

for ( ii = 0; hello[ii] != NULL; ii++ )

{

if ( eziq_add(&myq, hello[ii], strlen(hello[ii]) + 1) != 0 )

{

printf("eziq_add error\n");

return 1;

}

}

while ( (read_status = eziq_get(&myq, record, &result_len, READMAX)) != 1 )

{

printf("got record: '%s', returned length was %d, status was %d\n",

record, result_len, read_status);

eziq_delete(&myq); // do not forget to delete the head record!

}

return 0;

}

48.4 Output of Example 1$ ./eziq_test.exe

got record: 'Hello', returned length was 6, status was 0

got record: 'World!!!', returned length was 9, status was 0

got record: 'How are yo', returned length was 10, status was -1 <= this record was

bigger than the

receiving buffer

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 112 of 145

Page 113: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

48.5 Example 2 - Ezi Queue Test App#ifdef EZIQ_TEST_APP#include <stdio.h>#include <ctype.h>EZIQUEUE_T q;#define MAXSIZE (15)UCHAR myqbuff[MAXSIZE];const char hex[] = "0123456789ABCDEF";int ret;char out[MAXSIZE*2+1];int spos;int rpos;char ruler[] = "_t__h__ 0 1 2 3 4 5 6 7 8 91011121314__ret____________________________________\n";#define P printfvoid p(char str[]){ int ii; char temp[3];

for ( ii = 0; ii < MAXSIZE; ii++ ) { if ( isprint(myqbuff[ii]) ) { out[ii*2] = ' '; out[ii*2+1] = myqbuff[ii]; } else { sprintf(temp, "%2d", myqbuff[ii]); out[ii*2] = temp[0]; out[ii*2+1] = temp[1]; } out[ii*2+2] = '\0'; } sprintf(temp, "%2d", ret); P("%2lu %2lu \"%s\" %s %s", (ULONG)q.tail, (ULONG)q.head, out, ret == 0 ? " " : temp, str);}int main ( int argc, char *argv[] ){#define SZ ((char)6) UCHAR b[SZ+1]; UCHAR s;#define BIG (50) UCHAR bigread[BIG+1]; int ii = 0; size_t marker = 0;

P("%s Build:" __DATE__ " " __TIME__ "\n", argv[0]); eziq_init (&q, MAXSIZE, myqbuff);

for ( ii=0; ii < 16; ii++ ) { P(ruler); ret=eziq_add(&q,"abc",sizeof("abc")); p("add"); P(" \"%s\"\n","abc"); ret=eziq_add(&q,"def",sizeof("def")); p("add"); P(" \"%s\"\n","def"); ret=eziq_add(&q,"ghi",sizeof("ghi")); p("add (not enough room)"); P(" \"%s\"\n","ghi"); ret=eziq_add(&q,"jk" ,sizeof("jk" )); p("add"); P(" \"%s\"\n","jk" ); ret=eziq_check(&q,MAXSIZE,myqbuff); p("check"); P(" recs=%lu\n",(ULONG)eziq_num(&q) ); marker=q.head; while ( 0==(ret=eziq_scan(&q,&marker,bigread,&s,BIG)) ) { p("scan "); P("marker=%2d s=%d \"%s\"\n",marker,s,bigread); } ret=eziq_get(&q,b,&s,SZ); eziq_delete(&q); p("get+delete"); b[s]='\0'; P(" s=%d \"%s\"\n",s,b); ret=eziq_get(&q,b,&s,2 ); eziq_delete(&q); p("get+delete(short)"); b[2]='\0'; P(" s=%d \"%s\"\n",s,b); ret=eziq_get(&q,b,&s,SZ); eziq_delete(&q); p("get+delete"); b[s]='\0'; P(" s=%d \"%s\"\n",s,b); ret=eziq_get(&q,b,&s,SZ); eziq_delete(&q); p("get+delete(empty)"); b[s]='\0'; P(" s=%d \"%s\"\n",s,b); P("\n"); } ret=eziq_check (&q,MAXSIZE,myqbuff); P("\nfinal queue check returned %d\n",ret); return 0;}#endif // #ifdef TEST_APP

alflb_20120306.odt © 2002-2012 Alf Lacis Page 113 of 145

Page 114: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

48.6 Output of Example 2$ gcc -Wall d_string.c -o eziq_test ezi_str.c strncpyn.c -D EZIQ_TEST_APP eziqueue.c$ ./eziq_test.exe./eziq_test Build:May 12 2008 18:03:01_t__h__ 0 1 2 3 4 5 6 7 8 91011121314__ret____________________________________ 5 0 " 4 a b c 0 0 0 0 0 0 0 0 0 0 0" add "abc"10 0 " 4 a b c 0 4 d e f 0 0 0 0 0 0" add "def"10 0 " 4 a b c 0 4 d e f 0 0 0 0 0 0" 1 add (not enough room) "ghi"14 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" add "jk"14 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" check recs=314 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" scan marker= 5 s=4 "abc"14 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" scan marker=10 s=4 "def"14 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" scan marker=14 s=3 "jk"14 5 " 4 a b c 0 4 d e f 0 3 j k 0 0" get+delete s=4 "abc"14 10 " 4 a b c 0 4 d e f 0 3 j k 0 0" -1 get+delete(short) s=2 "de"14 14 " 4 a b c 0 4 d e f 0 3 j k 0 0" get+delete s=3 "jk"14 14 " 4 a b c 0 4 d e f 0 3 j k 0 0" 1 get+delete(empty) s=0 ""

_t__h__ 0 1 2 3 4 5 6 7 8 91011121314__ret____________________________________ 4 14 " a b c 0 0 4 d e f 0 3 j k 0 4" add "abc" 9 14 " a b c 0 4 d e f 0 0 3 j k 0 4" add "def" 9 14 " a b c 0 4 d e f 0 0 3 j k 0 4" 1 add (not enough room) "ghi"13 14 " a b c 0 4 d e f 0 3 j k 0 0 4" add "jk"13 14 " a b c 0 4 d e f 0 3 j k 0 0 4" check recs=313 14 " a b c 0 4 d e f 0 3 j k 0 0 4" scan marker= 4 s=4 "abc"13 14 " a b c 0 4 d e f 0 3 j k 0 0 4" scan marker= 9 s=4 "def"13 14 " a b c 0 4 d e f 0 3 j k 0 0 4" scan marker=13 s=3 "jk"13 4 " a b c 0 4 d e f 0 3 j k 0 0 4" get+delete s=4 "abc"13 9 " a b c 0 4 d e f 0 3 j k 0 0 4" -1 get+delete(short) s=2 "de"13 13 " a b c 0 4 d e f 0 3 j k 0 0 4" get+delete s=3 "jk"13 13 " a b c 0 4 d e f 0 3 j k 0 0 4" 1 get+delete(empty) s=0 ""

<SNIP>

_t__h__ 0 1 2 3 4 5 6 7 8 91011121314__ret____________________________________ 6 1 " 0 4 a b c 0 0 4 d e f 0 3 j k" add "abc"11 1 " 0 4 a b c 0 4 d e f 0 0 3 j k" add "def"11 1 " 0 4 a b c 0 4 d e f 0 0 3 j k" 1 add (not enough room) "ghi" 0 1 " 0 4 a b c 0 4 d e f 0 3 j k 0" add "jk" 0 1 " 0 4 a b c 0 4 d e f 0 3 j k 0" check recs=3 0 1 " 0 4 a b c 0 4 d e f 0 3 j k 0" scan marker= 6 s=4 "abc" 0 1 " 0 4 a b c 0 4 d e f 0 3 j k 0" scan marker=11 s=4 "def" 0 1 " 0 4 a b c 0 4 d e f 0 3 j k 0" scan marker= 0 s=3 "jk" 0 6 " 0 4 a b c 0 4 d e f 0 3 j k 0" get+delete s=4 "abc" 0 11 " 0 4 a b c 0 4 d e f 0 3 j k 0" -1 get+delete(short) s=2 "de" 0 0 " 0 4 a b c 0 4 d e f 0 3 j k 0" get+delete s=3 "jk" 0 0 " 0 4 a b c 0 4 d e f 0 3 j k 0" 1 get+delete(empty) s=0 ""

_t__h__ 0 1 2 3 4 5 6 7 8 91011121314__ret____________________________________ 5 0 " 4 a b c 0 0 4 d e f 0 3 j k 0" add "abc"10 0 " 4 a b c 0 4 d e f 0 0 3 j k 0" add "def"10 0 " 4 a b c 0 4 d e f 0 0 3 j k 0" 1 add (not enough room) "ghi"14 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" add "jk"14 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" check recs=314 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" scan marker= 5 s=4 "abc"14 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" scan marker=10 s=4 "def"14 0 " 4 a b c 0 4 d e f 0 3 j k 0 0" scan marker=14 s=3 "jk"14 5 " 4 a b c 0 4 d e f 0 3 j k 0 0" get+delete s=4 "abc"14 10 " 4 a b c 0 4 d e f 0 3 j k 0 0" -1 get+delete(short) s=2 "de"14 14 " 4 a b c 0 4 d e f 0 3 j k 0 0" get+delete s=3 "jk"14 14 " 4 a b c 0 4 d e f 0 3 j k 0 0" 1 get+delete(empty) s=0 ""

final queue check returned 0

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 114 of 145

Page 115: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

49 Range Checking and NormalisationNORMALISE_RANGE , IS_IN_RANGE , IS_IN_BETWEEN, IS_INDEX, IS_SPAN_OK, IS_IN_RANGE_SANE,

IS_IN_BETWEEN_SANE, IS_INDEX_SANE, IS_SPAN_SANE

49.1 SynopsisThese macros implement simple range checking and normalisation for typeless arguments.

NOTE: the macros without _SANE in the name do not test that min is less than max!

49.2 Usage

#include "alflb.h" Note that there is no type associated with these macros and their parameters.

/type/ NORMALISE_RANGE(

/type/ min,

/type/ max,

/type/ value)

Do not allow value to exceed the minimum or maximum specified. This should be optimised if extra speed required or side-effects need to be minimised.

Returns: Returns value, but restricted by min and max.

/type/ IS_IN_RANGE(

/type/ inc_min,

/type/ inc_max,

/type/ value)

Inclusive range checking of value against inc_max & inc_min values. NOTE: does not test that inc_min is less than inc_max.

Returns: 1 if value is in the range of inc_min to inc_max, otherwise 0

/type/ IS_IN_BETWEEN(

/type/ exc_min,

/type/ exc_max,

/type/ value)

Exclusive range checking of value against exc_max & exc_min values. NOTE: does not test that exc_min is less than exc_max.

Returns: 1 if value is in between exc_min and exc_max, otherwise 0

/type/ IS_INDEX(

/type/ inc_min,

/type/ exc_max,

/type/ value)

This is similar to IS_IN_RANGE and IS_IN_BETWEEN above, but uses the C/C++ standard method of checking an index using "A <= v < B"; i.e., inclusive-minimum and exclusive-maximum. NOTE: does not test that inc_min is less than exc_max.

Returns: 1 if value is in the index range of inc_min to exc_max, otherwise 0

/type/ IS_SPAN_OK(

/type/ req_inc_min,

/type/ req_inc_max,

/type/ value_min,

/type/ value_max)

Checks if span values are contained within the required range. Values are all inclusive. NOTE: does not test that 'min' is less than 'max' for either required range or span values!

Returns: 1 if values are in the correct ranges of min & max, otherwise 0

/type/ IS_IN_RANGE_SANE(

/type/ inc_min,

/type/ inc_max,

/type/ value)

Similar to IS_IN_RANGE, but also checks sanity of inc_min & inc_max values.

Returns: 1 if in range, and min & max are sane, otherwise 0

/type/ IS_IN_BETWEEN_SANE(

/type/ exc_min,

/type/ exc_max,

/type/ value)

Similar to IS_IN_BETWEEN, but also checks sanity of exc_min & exc_max values.

Returns: 1 if in between, and min & max are sane, otherwise 0

alflb_20120306.odt © 2002-2012 Alf Lacis Page 115 of 145

Page 116: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

/type/ IS_INDEX_SANE(

/type/ inc_min,

/type/ exc_max,

/type/ value)

Similar to IS_INDEX, but also checks sanity of inc_min & exc_max values.

Returns: 1 if index OK, and min & max are sane, otherwise 0

/type/ IS_SPAN_SANE(

/type/ req_inc_min,

/type/ req_inc_max,

/type/ value_min,

/type/ value_max)

Similar to IS_SPAN_OK, but also checks sanity of min & max values.

Returns: 1 if span OK, and min & max are sane, otherwise 0

49.3 ExamplesRange check: that value is in range 0 and 99 inclusively:

if ( IS_IN_RANGE(0, 99, value) ) /* check if value is 0 to 99 */

// do something

Range check: that value is in between -1 and 100 exclusively (these values are effectively equivalent to the previous example):

if ( IS_IN_BETWEEN(-1, 100, value) ) /* check if value is 0 to 99 */

// do something

Normalise value so it does not exceed its correct range of 0 to 99 inclusive:

value = NORMALISE_RANGE(0, 99, value);

49.4 BugsAs for any macro, beware of side-effects in macro expansion. I have prevented some side-effects, but not all, by using lots of parentheses. Similar warnings as for common macros like MIN and MAX should be heeded.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 116 of 145

Page 117: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

50 Replace Pattern Character in a String - replace, etcreplace, replacen

50.1 SynopsisThese functions replace occurrences of a pattern character in a string with a replacement character.

50.2 Usage#include "alflb.h"

char *replace( Replace characters in a string, stopping before the last '\0'. char str[], String to be modified. char pattern, Character to search for (does not work for '\0': use replacen instead). char replacement); Character to put into str[]. Returns: Address of str[]: useful so this function can be embedded in another

function, e.g.: printf("string is '%s'\n", replace(str,' ','_'));

char *replacen( As for above, but does not stop at '\0' characters. char str[], \ char pattern, > As for above. char replacement, / size_t length); Length of string str[]. Returns: As for above.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 117 of 145

Page 118: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

51 Reverse a String - reversenreversen

51.1 SynopsisThis function reverses a string in place.

51.2 Usage#include "alflb.h"

char *reversen( Reverse a string in place. char str[], String to be modified size_t size); Number of characters to swap. Returns: Address of str[]: useful to embed this function in another call, e.g.:

printf("Reversed:'%s'\n", reversen(str, strlen(str)));

alflb_20120306.odt © 2002-2012 Alf Lacis Page 118 of 145

Page 119: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

52 String Equality Checks - Variousstricmp, strnicmp, strcmpi, strncmpi, STREQUAL, STRNEQUAL, STRIEQUAL, STRNIEQUAL

52.1 SynopsisThese functions and macros provide a simple range of string equality checks.

stricmp should be part of the ANSI C/C++ library, although it was not included in LabWindows/CVI.

strnicmp, strcmpi, strncmpi are not ANSI C/C++, although they are available in the Borland C/C++ library and seem like logical extensions. strcmpi, strncmpi are implemented as macros for stricmp, strnicmp.

STREQUAL, STRNEQUAL, STRIEQUAL, STRNIEQUAL are macros which read better when doing a lot of string comparisons in your code. They use strcmp, strncmp, stricmp and strnicmp respectively, so have no extra processing overhead.

52.2 Usage#include "is_not.h"

#include "alflb.h"

int stricmp( Case insensitive string inequality if max lengths are unknownint strcmpi( Macro synonym for above function. char s[], First string to compare char t[]); Second string to compare Returns: Returns negative if s<t, 0 if s==t, positive if s>t

int strnicmp( Case insensitive string inequality if max length is knownint strncmpi( Macro synonym for above function. char s[], First string to compare char t[], Second string to compare int max); Max length Returns: Returns negative if s<t, 0 if s==t, positive if s>t

int STREQUAL( String equality if max lengths are unknown char s[], First string to compare char t[]); Second string to compare Returns: 1 if equal, 0 otherwise

int STRNEQUAL( String equality if max length is known char s[], First string to compare char t[], Second string to compare int max); Max length Returns: 1 if equal, 0 otherwise

int STRIEQUAL( Case insensitive string equality if max lengths are unknown char s[], First string to compare char t[]); Second string to compare Returns: 1 if equal, 0 otherwise

int STRNIEQUAL( Case insensitive string equality if max length is known char s[], First string to compare char t[], Second string to compare int max); Max length Returns: 1 if equal, 0 otherwise

alflb_20120306.odt © 2002-2012 Alf Lacis Page 119 of 145

Page 120: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

52.3 ExampleRather than show simply the usage of these macros, I have shown the equivalent code, using the stricmp and strnicmp routines first, and then shown how these read better when using the macros.

if ( stricmp(stra, "Token") == 0 ) // or strcmpi

ProcessToken();

if ( strnicmp(stra, "Value:", 6) == 0 ) // or strncmpi

ProcessValue(&stra[6]);

if ( strnicmp(stra, "key:" , 4) == 0 )

ProcessKey(&stra[4]);

if ( stricmp(stra, "Pair") == 0 )

ProcessPair();

if ( STRIEQUAL(stra, "Token") )

ProcessToken();

if ( STRNIEQUAL(stra, "Value:", 6) )

ProcessValue(&stra[6]);

if ( STRNIEQUAL(stra, "key:" , 4) )

ProcessKey(&stra[4]);

if ( STRIEQUAL(stra, "Pair") )

ProcessPair();

alflb_20120306.odt © 2002-2012 Alf Lacis Page 120 of 145

Page 121: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

53 Case-insensitive strstr - strcasestrstrcasestr

53.1 SynopsisCase-insensitive strstr, ripped from the web, original source unknown.

strcasestr scans str1 for the first occurrence of the substring str2, case-insensitive.

53.2 Usage#include "alflb.h"

char *strcasestr(

char *str1,

char *str2)

Returns: Pointer to the element in str1, where str2 can be found. If str2 does not occur in str1, strcasestr returns NULL.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 121 of 145

Page 122: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

54 Fast String Catenate, Returned Length - strcatlen, etc

strcatlen, strncatlen

54.1 SynopsisFast functions like strcat with returned length - no strlen required. These routines increase the functionality of the strcat function by determining the destination's new string length without resorting to an extraneous call to strlen. Fast when used properly, because these routines save the second loop inside strlen. When used for the first time on a new, empty dest string, *outlen must initially be set to 0.

54.2 Usage#include "alflb.h" For size_t, included by strcatlen.h if not already included.

char *strcatlen(

char *dest, destination string address size_t *outlen, returned new length of destination char *src); null-terminated source string Returns: Address of dest; useful for function embedding.

char *strncatlen( always null-terminates the destination string char *dest, destination string address size_t *outlen, returned new length of destination char *src, null-terminated source string size_t inlenmax); maximum length of input string Returns: Address of dest; useful for function embedding.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 122 of 145

Page 123: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

54.3 Example#ifdef TEST_NEWCAT

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

int main(int argc, char *argv[])

{

char dest1[] = ".....................";

char dest2[] = ".....................";

size_t len1 = 0, len2 = 0;

char temp[sizeof(dest1)*4+1];

char src[10] = "fred";

int ii;

size_t olen;

for ( ii = 6; ii >= 0; ii-- )

{

src[ii] = '\0';

strcatlen (dest1, &len1, src);

printf("ii=%d dest1=%s len1=%d\n", ii, d_string_safe(temp,&olen,sizeof(temp)-1,

dest1,sizeof(dest1)), len1);

}

strcpy(src,"fred");

for ( ii = 6; ii >= 0; ii-- )

{

strncatlen(dest2, &len2, src, ii);

printf("ii=%d dest2=%s len2=%d\n", ii, d_string_safe(temp,&olen,sizeof(temp)-1,

dest2,sizeof(dest2)), len2);

}

return 0;

}

#endif

54.4 Output from above example$ gcc -Wall -o strcatlen d_string.c ezi_str.c strncpyn.c -DTEST_NEWCAT strcatlen.c

$ ./strcatlen

ii=6 dest1=fred\0................\000 len1=4

ii=5 dest1=fredfred\0............\000 len1=8

ii=4 dest1=fredfredfred\0........\000 len1=12

ii=3 dest1=fredfredfredfre\0.....\000 len1=15

ii=2 dest1=fredfredfredfrefr\0...\000 len1=17

ii=1 dest1=fredfredfredfrefrf\0..\000 len1=18

ii=0 dest1=fredfredfredfrefrf\0..\000 len1=18

ii=6 dest2=fred\0................\000 len2=4

ii=5 dest2=fredfred\0............\000 len2=8

ii=4 dest2=fredfredfred\0........\000 len2=12

ii=3 dest2=fredfredfredfre\0.....\000 len2=15

ii=2 dest2=fredfredfredfrefr\0...\000 len2=17

ii=1 dest2=fredfredfredfrefrf\0..\000 len2=18

ii=0 dest2=fredfredfredfrefrf\0..\000 len2=18

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 123 of 145

Page 124: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

55 Safe String N-Copy with Trailing Null - strncpyn, etcstrncpyn, strncpyprintn

55.1 SynopsisThese functions provide a maximal string copy, but also append a trailing '\0' (which is missing on the standard C library call strncpy) at position last_index. strncpyprintn stops also at the first non-printing character (which includes '\0').

The functions return a pointer to the destination string, so the functions can be used as an argument in another function requiring a character string.

Note the usage of size_t for last_index.

55.2 Usage#include "alflb.h"

char *strncpyn( Maximal string copy routine char to[], Destination string char from[], Source string size_t last_index); Max length Returns: Address of destination string; useful if you want to embed this call in

another function.

char *strncpyprintn( Like strncpyn, but only adds printable characters. char to[], Destination string char from[], Source string size_t last_index); Max length Returns: Address of destination string; useful if you want to embed this call in

another function.

55.3 Examplesprintf("String is '%s'\n", strncpyn(to, from, sizeof(to)-1));

alflb_20120306.odt © 2002-2012 Alf Lacis Page 124 of 145

Page 125: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

56 String Processor Suiteezi_sproc, ezi_squash, ezi_printable

56.1 SynopsisOriginal Fortran code Alf Lacis circa 1984. Rewritten from scratch 2010.This function provides a single routine that will optionally:– shift to UPPER or lower case.– remove non-printing characters in a variety of ways.– squashes blanks leaving either only one blank or none.

56.2 Usage#include "alflb.h"

EZISTR_T *ezi_sproc( The main 'string processor' functionality.. EZISTR_T *string, The Ezi character string to be modified. int params, Group of function flags, ORed together. Refer to params below. char replacement); This character will be used (if you have specified SP_MASK_NONP or

SP_8BIT_NONP) to replace non- printing chars. Returns: Address of string.

EZISTR_T *ezi_squash( Smaller, 'squash'-functionality-only part of ezi_sproc(). EZISTR_T *string, The Ezi character string to be modified. int params); Group of function flags, ORed together. Refer to params below. Returns: Address of string.

EZISTR_T *ezi_printable( Smaller, 'printable'-functionality-only part of ezi_sproc(). EZISTR_T *string, The Ezi character string to be modified. int params, Group of function flags, ORed together. Refer to params below. char replacement); This character will be used (if you have specified SP_MASK_NONP or

SP_8BIT_NONP) to replace non- printing chars. Returns: Address of string.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 125 of 145

Page 126: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

56.3 paramsparams is a group of function flags, ORed together.

CASE-SHIFTING:

SP_UPSHIFT 0100 String will be up-shifted, eg "Fred Dagg" >> "FRED DAGG"SP_DNSHIFT 0200 String will be down-shifted, eg "Fred Dagg" >> "fred dagg"

If both are specified, string is down-shifted.

NON-PRINTING CHARACTER HANDLING:

The method varies importantly upon whether you specify SP_MASK_NONP, SP_8BIT_NONP or SP_DISC_NONP:

SP_MASK_NONP 010 then the eighth bit is cleared to 0, THEN the remaining bits are tested to see if it isnon-printing.

SP_8BIT_NONP 020 the eighth bit is NOT altered and the character is tested anyway. Characters in the range0x80 to 0xFF (cast as unsigned) are regarded as printable.

SP_DISC_NONP 040 non-printing characters are discarded, not replaced.

If mix specified, SP_DISC_NONP supersedes SP_8BIT_NONP supersedes SP_MASK_NONP.WARNING: SP_DISC_NONP may shrink the string even if SP_NO_BLANKS or SP_ONE_BLANK have *not* been specified.

BLANK-REMOVAL:

SP_NO_BLANKS 2 All blanks will be deleted.SP_ONE_BLANK 1 All leading and trailing blanks are removed, and extraneous embedded blanks will be

removed, leaving just one blank.EXAMPLE INPUT STRING BITMASK: RESULT:

" Fred Dagg " SP_NO_BLANKS "FredDagg"

" Fred Dagg " SP_ONE_BLANK "Fred Dagg"

If both are specified, all blanks are removed.

56.4 Example 1input will have its non-printing chars removed, be shifted to upper case, and have all embedded blanks removed by moving the string to the left.

ezi_sproc(input, SP_UPSHIFT | SP_MASK_NONP | SP_NO_BLANKS, ' ');

alflb_20120306.odt © 2002-2012 Alf Lacis Page 126 of 145

Page 127: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

56.5 Example 2: Test Application#ifdef SPROC_TEST_APPchar *sopts(EZISTR_T *ostr, int params){ ezi_clr(ostr); if ( TESTMASK(params, SP_UPSHIFT ) ) ezi_cat_raw(ostr, "UP " ); else ezi_cat_raw(ostr, "---- " ); if ( TESTMASK(params, SP_DNSHIFT ) ) ezi_cat_raw(ostr, "DOWN " ); else ezi_cat_raw(ostr, "---- " ); if ( TESTMASK(params, SP_MASK_NONP) ) ezi_cat_raw(ostr, "| MASK "); else ezi_cat_raw(ostr, "| ---- "); if ( TESTMASK(params, SP_8BIT_NONP) ) ezi_cat_raw(ostr, "8BIT " ); else ezi_cat_raw(ostr, "---- " ); if ( TESTMASK(params, SP_DISC_NONP) ) ezi_cat_raw(ostr, "DISC " ); else ezi_cat_raw(ostr, "---- " ); if ( TESTMASK(params, SP_ONE_BLANK) ) ezi_cat_raw(ostr, "| 1BLK "); else ezi_cat_raw(ostr, "| ---- "); if ( TESTMASK(params, SP_NO_BLANKS) ) ezi_cat_raw(ostr, "0BLK " ); else ezi_cat_raw(ostr, "---- " ); return ostr->str;}

void do_it(char *str, int params){ EZISTREMPTY(ostr, 80); EZISTREMPTY(ezi, 76); EZISTREMPTY(dbgi, 300); EZISTREMPTY(dbgo, 300);

ezi_cpy_raw(ezi, str); ezi_dbg(dbgi,ezi); ezi_sproc(ezi,params,' '); ezi_dbg(dbgo,ezi); printf("@%s@ opts=0%04o=%s->0x%02x\n@%s@\n\n", dbgi->str,params,sopts(ostr,params),ezi->len,dbgo->str);}

int main(int argc, char *argv[]){ do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0 ); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0100); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0200); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0110); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0120); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0012); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0011); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0022); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0021); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0040); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0041); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0042); printf("All parameter bits set:\n"); do_it(" Ab \1\2 E æ\x80\x91\xA0 Ij ",0777); return 0;}#endif

alflb_20120306.odt © 2002-2012 Alf Lacis Page 127 of 145

Page 128: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

$ gcc -g -Wall -DEZI_DBG_MAX=150 -DSPROC_TEST_APP -o ezi_sproc_test_app ezi_sproc.c -L. -lalflb

$ ./ezi_sproc_test_app@ Ab \1\2 E \346\200\221\240 Ij @ opts=00000=---- ---- | ---- ---- ---- | ---- ---- ->0x16@ Ab \1\2 E \346\200\221\240 Ij @

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00100=UP ---- | ---- ---- ---- | ---- ---- ->0x16@ AB \1\2 E \346\200\221\240 IJ @

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00200=---- DOWN | ---- ---- ---- | ---- ---- ->0x16@ ab \1\2 e \346\200\221\240 ij @

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00110=UP ---- | MASK ---- ---- | ---- ---- ->0x16@ AB E F IJ @

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00120=UP ---- | ---- 8BIT ---- | ---- ---- ->0x16@ AB E \346\200\221\240 IJ @

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00012=---- ---- | MASK ---- ---- | ---- 0BLK ->0x06@AbEfIj@

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00011=---- ---- | MASK ---- ---- | 1BLK ---- ->0x09@Ab E f Ij@

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00022=---- ---- | ---- 8BIT ---- | ---- 0BLK ->0x09@AbE\346\200\221\240Ij@

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00021=---- ---- | ---- 8BIT ---- | 1BLK ---- ->0x0c@Ab E \346\200\221\240 Ij@

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00040=---- ---- | ---- ---- DISC | ---- ---- ->0x14@ Ab E \346\200\221\240 Ij @

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00041=---- ---- | ---- ---- DISC | 1BLK ---- ->0x0c@Ab E \346\200\221\240 Ij@

@ Ab \1\2 E \346\200\221\240 Ij @ opts=00042=---- ---- | ---- ---- DISC | ---- 0BLK ->0x09@AbE\346\200\221\240Ij@

All parameter bits set:@ Ab \1\2 E \346\200\221\240 Ij @ opts=00777=UP DOWN | MASK 8BIT DISC | 1BLK 0BLK ->0x09@abe\346\200\221\240ij@

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 128 of 145

Page 129: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

57 Strip Trailing Bytes - StrippedSize

57.1 SynopsisDetermines how long a buffer is after skipping past all occurrences of the search-byte.

57.2 Usage#include "alflb.h"

int StrippedSize(

void *pData, Any valid pointer to data. int InitialSize,

unsigned char

StripThisByte );

Returns:

57.3 ExampleThisSize = MIN(ChunkLen, OriginalLen - offset);

TrimmedSize = StrippedSize((((uchar *)OriginalBuf) + offset), ThisSize, 0xff);

if (0 != (error = writebuf(TempName, (((uchar *)OriginalBuf) + offset), TrimmedSize)))

alflb_20120306.odt © 2002-2012 Alf Lacis Page 129 of 145

Page 130: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

58 'Swedish' Equivalent for __DATE__ & __TIME__swedish_build

58.1 SynopsisWhen the build date and time are required, especially for file names or sorting requirements, the yankee format __DATE__ and __TIME__ macros are inadequate. swedish_build converts the yankee format macros into a useful YearMonthDay HourMinuteSecond format (also know as Swedish format) string of the form:

YYYYMMDD_HHMMSS with separator passed as '_'.

YYYYMMDDHHMMSS with separator passed as '\0' (0x00).

The separator may be any character, e.g. '_', '.', etc. If the separator is passed in as '\0', then no separator is used, making the resulting string 1 character shorter.

58.2 Usage#include "alflb.h"

#define SWEDISH_BUILD_SIZE 16 #defined in alflb.h. Can be used with swedish_build below: YYYYMMDD_HHMMSS implies 8 chars + 1 separator + 6 chars +

1 '\0' = 16

char *swedish_build(

char swedish[],

size_t sizeof_swedish,

char separator,

char yankee_date[],

char yankee_time[] );

Returns:

Buffer to hold result: should be SWEDISH_BUILD_SIZE or longer.Typically SWEDISH_BUILD_SIZE.Any non-nul character. The nul character '\0' means 'no separator'.This is __DATE__.This is __TIME__.Pointer to passed in resulting string.

58.3 ExampleThe example test application is contained within swedish_build.c and can be built with the switch SWEDISH_TEST_APP. Test app from swedish_build.c is:

#ifdef SWEDISH_TEST_APP#include <stdio.h>int main(int argc, char *argv[]){ char buf[SWEDISH_BUILD_SIZE]; printf("Build date & time: yankee :'%s' '%s'\n", __DATE__, __TIME__); printf("Build date & time: swedish:'%s'\n", swedish_build(buf, SWEDISH_BUILD_SIZE, '.', __DATE__, __TIME__));}#endif

58.4 Output from Example$ gcc -DSWEDISH_TEST_APP -o swedish_build swedish_build.c replace.c

$ ./swedish_build

Build date & time: yankee :'Jul 21 2007' '17:08:35'

Build date & time: swedish:'20070721.170835'

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 130 of 145

Page 131: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

59 Tagged Variable Search - TS_Info, etcTS_Info, TS_InfoQual, TagStringMakePrefix, TagStringFind

59.1 SynopsisTS_Info searches for "Tagged Variables". For all discussion refer to document _____.

TS_InfoQual performs the same search, but also returns the Qualifier string for the Tagged Variable, if it exists.

TagStringMakePrefix, TagStringFind are described if you want finer control.

59.2 Returned Length and Pointer ValuesIf TS_Info does not return TS_FoundOK (== 0), pVariable_Len is set to 0 (zero) and ppVariable is set to NULL.

If TS_InfoQual does not return TS_FoundOK (== 0), pVariable_Len is set to 0 (zero) and ppVariable is set to NULL. If the Tagged Variable is not found, or found but has no Qualifier, then pQualifier_Len is set to 0 (zero) and ppQualifier is set to NULL.

59.3 Usage#include "ts_find.h" TS_Find.h includes BoyerMor.h and TagField.h

int TS_Info( This routine searches for a Tagged Variable as defined in the above doco. LPSTR *ppVariable, Note: Pointer to pointer. Returns address of Tagged Variable (not the

Tagged Field) if found. long *pVariable_Len, Returns length of Tagged Variable if found. LPSTR Search_Space, Address for start of search. long Search_Space_Len, Number of bytes in search space. LPSTR TagString) The bare Tag String to search for (without the Prefix, Midfix, etc - refer

to above document). Returns: Returns one of TR_Return_e enumerated values:

TS_FoundOK (0) if the Tagged Variable was correctly foundTS_TagStringNotFound if the Tag Prefix was not foundTS_SuffixNotFound Warning: the Tagged Variable was found,

but there was no closing Tag Suffix!TS_SearchSpaceNULL if SearchSpace was a NULL pointerTS_SetUpFailureVariable if BoyerMoore_SetPattern failed on the

Tagged VariableTS_SetUpFailureSuffix if BoyerMoore_SetPattern failed on the

Suffix

int TS_InfoQual(

LPSTR *ppVariable, As for TS_Info. long *pVariable_Len, As for TS_Info. LPSTR *ppQualifier, Note: Pointer to pointer. Returns address if the TV's Qualifier if found,

else NULL. long *pQualifier_Len, Returns length of the TV's Qualifier if found, including trailing '\0', else

0. LPSTR Search_Space, As for TS_Info. long Search_Space_Len, As for TS_Info. LPSTR TagString); As for TS_Info. Returns: As for TS_Info, and may also return:

TS_SetUpFailureQualFix if BoyerMoore_SetPattern failed on the Qualifier Suffix

alflb_20120306.odt © 2002-2012 Alf Lacis Page 131 of 145

Page 132: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

void TagStringMakePrefix( This routines assembles the full Prefix, Tag String and Midfix into a complete string, called the Tag Field, ready for use in a Tagged Variable search scenario.

LPSTR dest_TagString, The complete string containing Prefix, Tag String and Midfix is returned here.

int *tlen_minus_nul, The length, not including the trailing '\0' is returned here. LPSTR Tag_String) A string containing the original Tag String, eg, "prodIMEI".

int TagStringFind( This routine performs a search, within the SearchSpace, of the Tag Field. If the Tag Field is found, a secondary search looks for the next Tag Suffix, which delineates the end of the Tagged Variable. If both searches are successful, the address of the Tagged Variable (not the Tag Field) and the Tagged Variable's length are returned.

LPSTR *ppVariable, As for TS_Info. long *pVariableLen, As for TS_Info. LPSTR SearchSpace, As for TS_Info. long SearchSpaceLen, As for TS_Info. LPSTR TagField, The assembled Tag Field typically as returned from TagStringMakePrefix. int tlen_minus_nul, The Tag Field length typically as returned from TagStringMakePrefix. LPSTR block_256) This is a pointer to a block of 256 bytes used temporarily by the

underlying Boyer-Moore routines to generate the Boyer-Moore skip table.

Returns: Refer to TS_Info return values above.

59.4 Exampleif ( TSFoundOK == (error = TS_InfoQual(&pVar, &Len, &pQual, &QLen, Buffer, BufLen, Name)))

{

if ( pQual != NULL )

{

printf("Tag Var '%s' found, Variable='%s', Qualifier='%s'\n", Name, pVar, pQual);

}

else

{

printf("Tag Var '%s' found, Variable='%s', no Qualifier\n", Name, pVar);

}

}

else

{

printf("Tag Var '%s' not found, error=%d\n", Name, error);

}

alflb_20120306.odt © 2002-2012 Alf Lacis Page 132 of 145

Page 133: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

60 Text Size Routines - ShorterName, GetPixelSizesLabwindows/CVI only.

60.1 SynopsisThe routine ShorterName is used to shorten a very long path name usually for display only by checking if a given string fits within the bounds of a LabWindows/CVI "Text Message". If the string is too long, the directory path of the filename is replaced with "\\..." and stored in a temporary variable. This routine calls GetPixelSize described next.

The routine GetPixelSizes returns the bounding box dimensions for the "Text Message" control and the initially desired string. This routine does not handle the string especially as if it was a path-name.

60.2 Usage#include "alflb.h"

char *ShorterName( Returns the candidate path-name if the length is OK, else returns a shortened path-name as described above.

int SN_panel, Value of LabWindows/CVI panel handle. int SN_control, Value of LabWindows/CVI control. char *SN_path, Initial candidate path-name string to be tested for pixel-length. char *SN_temp); Returned string, which may be shortened if original path-name would not fit

into the Text Message control. If not shortened, a copy of the original string. Returns: The address of SN_temp, for easy embedding in another function.

int GetPixelSizes( GetPixelSize makes various LabWindows/CVI calls to find out the bounding values of the "Text Message" box, and the candidate string.

int panel, Value of LabWindows/CVI panel handle. int control, Value of LabWindows/CVI control. char *string, Candidate string to be tested for pixel-length. int *pbox_height, Returned value of the "Text Message" control's height. int *pbox_width, Returned value of the "Text Message" control's width. int *ptext_height, Returned value of the candidate string's height. int *ptext_width); Returned value of the candidate string's width. Returns: 0 if no error returned, negative error code otherwise:

-1 GetCtrlAttribute(...ATTR_WIDTH, pbox_width) failed-2 GetCtrlAttribute(...ATTR_HEIGHT, pbox_height) failed-3 GetCtrlAttribute(...ATTR_TEXT_FONT, font) failed-4 GetTextDisplaySize(...) failed

60.3 ExampleIf you are truncating your pathname untidily, in the case where FileName is too long, instead of: SetCtrlVal(panel, PANEL_FILE, FileName);

use this: SetCtrlVal(panel, PANEL_FILE, ShorterName(panel, PANEL_FILE, FileName, tempstr));

Note: You do not use tempstr in this example for any other purpose than just to display the shortened string. It does not make sense to keep the variable tempstr as it may have lost the directory-path information in comparison to the variable FileName above.

60.4 BugsThis is the kind of functionality that should really have been available in LabWindows/CVI, perhaps via a flag in the "Text Message" control.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 133 of 145

Page 134: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

61 'Uniquify' a Pre-Sorted List - uniquify

61.1 SynopsisThis routine 'uniquifies' a pre-sorted list. uniquify's parameter list has been deliberately chosen to be identical to qsort or quicksort, available from any good software library.

Unlike qsort (which has no return value), uniquify returns the new number of elements after non-unique elements have been stripped.

WARNING: If you have elements in the list which are not part of the key, and are non-unique, THEN YOU WILL LOSE THEM! For example:

Data in table, NOT

part of the key

Data in table, IS

part of the key

Data in table, NOT

part of the key

Australia Lacis, Alfredo 14 Brisbane Street

Spain Lacis, Alfredo 99 Madrid Terrace

Korea, South Smith, John 11 Seoul Street

China Smith, John 21 Beijing Street

Peru Toms, Sally 12 Machu Pichu Crest

USA Toms, Sally 13 Detroit Road

will appear as the following after uniquify:

Australia Lacis, Alfredo 14 Brisbane Street

Korea, South Smith, John 11 Seoul Street

Peru Toms, Sally 12 Machu Pichu Crest

THEREFORE: Do not use uniquify on lists with non-key data in them, which you wish to retain. If necessary, provide a new cmp function which would use more of the (originally) non-key data as key data.

Also: If the list was created using a malloc/realloc/etc pointer, it is the calling application's responsibility to realloc or free the unrequired memory.

61.2 Usage#include "uniquify.h"

size_t uniquify(

void *const pbase, Points to the base (0th element) of the table size_t total_elems, The number of entries in the table size_t size, The size of each entry in the table, in bytes int (*cmp)(

const void *r1,

const void *r2));

The comparison function, with the same parameters as compare function for qsort.

Returns: Number of entries in the (possibly shortened) list. Always positive for a non-empty list.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 134 of 145

Page 135: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

61.3 ExampleSort our array of structures, LangEntry_t pp[], then use uniquify to get rid of duplicate entries:

static int Compare_DisplayList(const void *row1, const void *row2)

{

return strcmp(((LangEntry_t*)row1)->Code, ((LangEntry_t*)row2)->Code);

}

. . . . .

qsort (&pp, nn, sizeof(pp[0]), Compare_DisplayList);

nn = uniquify(&pp, nn, sizeof(pp[0]), Compare_DisplayList);

alflb_20120306.odt © 2002-2012 Alf Lacis Page 135 of 145

Page 136: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

62 Write & Read a Buffer 'Safely' To/From a Filewritebuf_ver, writebuf, readbuf_ver, readbuf

62.1 SynopsisThese functions provide a one-line ability to save any chunk of memory to a binary file, and read it back. The Safely-part of this suite's functionality is that the file is protected with marker flags, length, version string and a CRC checksum. The file is not kept open between calls.

readbuf_ver and readbuf do not delete the file.

62.2 Usage

#include "alflb.h"

Return values: 0 OK (no error)-1 Could not open file for binary read or write-2 Could not read or write file-3 CRC does not match data (readbuf, readbuf_ver)-4 Framing markers wrong or missing (readbuf, readbuf_ver)-5 Version string does not match (readbuf_ver)

int writebuf_ver(

char *filename,

char *version,

void *buff,

size_t length);

Returns:

Function to write a buffer to a file with a version string.Filename. Created if it does not exist.A version string to save to the file, up to 20 characters.Pointer to memory which you want to write to fileNumber of bytes to writeSee Return values above.

int readbuf_ver(

char *filename,

char *version,

void *buff,

size_t length);

Returns:

Function to read a buffer from a file with a version string check.Filename. File must exist.A version string to compare against the file, up to 20 characters.Pointer to memory chunk to be overwritten from fileNumber of bytes to readSee Return values above.

int writebuf(

char *filename,

void *buff,

size_t length);

As for writebuf_ver without a passed-in version string.

int readbuf(

char *filename,

void *buff,

size_t length);

As for readbuf_ver without a passed-in version string.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 136 of 145

Page 137: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

62.3 Example embedded in w_r_buf.c#ifdef WR_TEST_APP

#include <stdio.h>

#include "alflb.h"

int main(int argc, char *argv[])

{

#define TEMP "temp.tmp"

#define BUF 50

UCHAR buf1[BUF];

UCHAR buf2[BUF];

int error;

memfill(buf1, "hello\n", BUF, 6);

if ( ( error = writebuf(TEMP, buf1, BUF)) < 0 )

{

printf("error writing %s -> %d\n", TEMP, error);

return error;

}

if ( ( error = readbuf(TEMP, buf2, BUF)) < 0 )

{

printf("error reading %s -> %d\n", TEMP, error);

return error;

}

printf("success: data saved and recovered OK\n");

return 0;

}

#endif

62.4 Output from the Example$ gcc -c -I.. -g -Wall -Os -I. -I../. -o test_w_r_buf.o -DWR_TEST_APP ../w_r_buf.c

$ gcc -g -o test_w_r_buf test_w_r_buf.o -L.. -lalflb

$ ./test_w_r_buf

success: data saved and recovered OK

$ hexd temp.tmp

+ od -A x -t x1z -v temp.tmp

000000 32 00 00 00 6e 6f 20 76 65 72 73 69 6f 6e 00 00 >2...no version..<

000010 00 00 00 00 00 00 00 00 00 00 cc b2 9e 68 65 6c >.............hel<

000020 6c 6f 0a 68 65 6c 6c 6f 0a 68 65 6c 6c 6f 0a 68 >lo.hello.hello.h<

000030 65 6c 6c 6f 0a 68 65 6c 6c 6f 0a 68 65 6c 6c 6f >ello.hello.hello<

000040 0a 68 65 6c 6c 6f 0a 68 65 6c 6c 6f 0a 68 65 74 >.hello.hello.het<

000050 61 69 6c 20 65 6e 64 20 63 68 61 72 6c 69 65 00 >ail end charlie.<

000060

$

alflb_20120306.odt © 2002-2012 Alf Lacis Page 137 of 145

Page 138: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

63 Zeros - All TypesC versions:

char_zero, int_zero, long_zero, short_zero, uchar_zero, uint_zero, ulong_zero,

ushort_zero

Camel versions:charZero, intZero, longZero, shortZero, ucharZero, uintZero, ulongZero, ushortZero

63.1 SynopsisSometimes a NULL pointer is not enough: you need a valid pointer to a memory location containing the value 0. These global variables all point to the same 4 bytes of memory containing, you guessed it, 4 zero bytes. If need arises, this will be expanded to 8 bytes for long long types.

This is assembler code, and there are currently two versions available, GNU GCC and Renesas HEW. See Alf for details.

63.2 Usage#include "alflb.h"

extern const char char_zero ;

extern const int int_zero ;

extern const long long_zero ;

extern const short short_zero ;

extern const UCHAR uchar_zero ;

extern const UINT uint_zero ;

extern const ULONG ulong_zero ;

extern const USHORT ushort_zero;

#define charZero char_zero

#define intZero int_zero

#define longZero long_zero

#define shortZero short_zero

#define ucharZero uchar_zero

#define uintZero uint_zero

#define ulongZero ulong_zero

#define ushortZero ushort_zero

63.3 Examples#include "alflb.h"

...

int *ptr = &int_zero; // the variable ptr will now contain the address of

// int_zero, not NULL

...

if ( *ptr == 0 ) // if what ptr points to, is zero, then do something...

{

<do something>

alflb_20120306.odt © 2002-2012 Alf Lacis Page 138 of 145

Page 139: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

64 Appendix 1 - GNU LicencesThese licences obtained 28-8-2007 from www.gnu.org. See this document's front page for applicability of these licences to ALFLB. I thank all those at GNU + elsewhere who made such a licence possible.

GNU GENERAL PUBLIC LICENSEVersion 2, June 1991Copyright (C) 1989, 1991 Free Software Foundation, Inc.51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USAEveryone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.PreambleThe licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.The precise terms and conditions for copying, distribution and modification follow.TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.NO WARRANTY11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

alflb_20120306.odt © 2002-2012 Alf Lacis Page 139 of 145

Page 140: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.END OF TERMS AND CONDITIONS

GNU LESSER GENERAL PUBLIC LICENSEVersion 2.1, February 1999Copyright (C) 1991, 1999 Free Software Foundation, Inc.51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USAEveryone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]PreambleThe licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.

The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:a) The modified work must itself be a software library.b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.This option is useful when you wish to copy part of the code of the Library into a program that is not a library.4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:

alflb_20120306.odt © 2002-2012 Alf Lacis Page 140 of 145

Page 141: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.END OF TERMS AND CONDITIONS

alflb_20120306.odt © 2002-2012 Alf Lacis Page 141 of 145

Page 142: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

IndexAddress Setup - MSBXxxx.............................................58alflog_close......................................................................79alflog_flush......................................................................79alflog_open......................................................................79alflog_open_read.............................................................79alflog_read.......................................................................79alflog_trim.......................................................................79alflog_write......................................................................79Allocate and Access Variables.........................................19Array entries, number of..................................................26ASCII Conversion from Integers.....................................68ASCII-Hex to Raw Binary Data......................................20asciihex2binary................................................................20Base-36 Checker..............................................................59Binary Data, Raw to ASCII-Hex.....................................20binary2asciihex................................................................20Bit-Array Suite................................................................22Bit-Map Suite..................................................................22Bit-Masks (Visual) - 4-, 8- & 16-bit Versions.................25BM_ALL.........................................................................22BM_ALLOC....................................................................22BM_ANY........................................................................22BM_ASSIGN,.................................................................22BM_CLR.........................................................................22BM_DECLARE..............................................................22BM_FREE.......................................................................22BM_MAX_BYTES.........................................................22BM_SET..........................................................................22BM_TEST.......................................................................22Boyer-Moore Algorithm..................................................96BoyerMoore_Find...........................................................96Byte Transposal (Endian)................................................49bytewisecrc16..................................................................39bytewisecrc32..................................................................39C-String and Debug-String Functions.............................34C-String Escape Sequences.............................................34c2str.................................................................................27CAPACITY_OF..............................................................26Case-insensitive strstr - strcasestr..................................121CAST_PTR....................................................................107CAST_SET....................................................................107Change_Ext.....................................................................57Change_File.....................................................................57char_zero.......................................................................138Character to String Converter..........................................27chr12x7............................................................................85chr16x12..........................................................................85chr7x4..............................................................................85chr7x5..............................................................................85chr9x5..............................................................................85Comma/Tab Separated Variable (csv/tsv) Files - Reading.........................................................................................28commas in numeric string...............................................44COMPILE_TIME_ASSERT...........................................32Compile-Time Asserts.....................................................32CompressedDateTimeStr()..............................................42ConvertEscapeSequencesSafe.........................................34CRC.................................................................................39

csvfield............................................................................28csvfieldbyname................................................................28csvgetline.........................................................................28csvgetlinebyname............................................................28csvnfield..........................................................................28csvreset............................................................................28Cyclic Redundancy Check Functions..............................39d_string_always_convert.................................................35d_string_fmt....................................................................35d_string_safe....................................................................35d_string_special...............................................................35Date/Time String Routines - Sortable Format.................42datethis() - *deprecated*.................................................41Debug String Routines....................................................35decode_asciihex_char_pair..............................................20Directory Path Make........................................................43DISTANCE......................................................................61DISTANCE_MACRO.....................................................61DOLOOP.........................................................................45ElapsedTime24Hr().........................................................42Encrypted Logging Events..............................................79Endian Byte Transposal...................................................49Error Check.....................................................................46Ezi Queue Function Suite..............................................109EZI_ACCESS..................................................................19ezi_ah2b.....................................................................11, 20ezi_ah2b_raw.............................................................11, 20EZI_ALLOCATE............................................................19ezi_asciihex2binary...................................................11, 20ezi_asciihex2binary_raw...........................................11, 20ezi_b2ah.....................................................................11, 20ezi_b2ah_raw.............................................................11, 20ezi_binary2asciihex...................................................11, 20ezi_binary2asciihex_raw...........................................11, 20ezi_calloc.........................................................................11ezi_cat..............................................................................11ezi_cat_raw......................................................................11ezi_ch...............................................................................11ezi_clr..............................................................................11ezi_cpy.............................................................................11ezi_cpy_cat......................................................................11ezi_cpy_cat_raw..............................................................11ezi_cpy_raw.....................................................................11ezi_dbg.......................................................................11, 35ezi_dbg_raw.....................................................................11EZI_E..............................................................................19ezi_endian........................................................................49EZI_ENDIAN_COPY.....................................................49EZI_ENDIAN_SITU.......................................................49ezi_esc.......................................................................11, 34EZI_EXTERN.................................................................19ezi_fill..............................................................................11EZI_I................................................................................19ezi_index_distance..........................................................61ezi_index_freedom..........................................................61ezi_index_next.................................................................61ezi_index_next_n.............................................................61ezi_index_prev................................................................61

alflb_20120306.odt © 2002-2012 Alf Lacis Page 142 of 145

Page 143: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

ezi_index_prev_n............................................................61ezi_index<TYPE>::~ezi_index()....................................61ezi_index<TYPE>::capacity(void)..................................61ezi_index<TYPE>::distance().........................................61ezi_index<TYPE>::ezi_index.........................................61ezi_index<TYPE>::freedom().........................................61ezi_index<TYPE>::is_empty().......................................61ezi_index<TYPE>::is_full()............................................61ezi_index<TYPE>::jog().................................................61ezi_index<TYPE>::next_gp().........................................61ezi_index<TYPE>::next_n()...........................................61ezi_index<TYPE>::next()...............................................61ezi_index<TYPE>::prev_gp().........................................61ezi_index<TYPE>::prev_n()...........................................61ezi_index<TYPE>::prev()...............................................61EZI_INIT.........................................................................19ezi_len..............................................................................11ezi_ltrim...........................................................................11ezi_opt.............................................................................72ezi_opt_8,........................................................................72ezi_opt_byte....................................................................72ezi_opt_init......................................................................72ezi_opt_kill......................................................................72EZI_OPT_LOG_MAX....................................................77EZI_OPT_MAX_APS.....................................................77EZI_OPT_MAX_BITS...................................................77ezi_opt_msg.....................................................................72EZI_OPT_NAME_MAX................................................77ezi_opt_set_1...................................................................72ezi_opt_set_8...................................................................72ezi_opt_set_bit.................................................................72ezi_opt_set_byte..............................................................72ezi_opt_snprintf...............................................................72ezi_opt_st.........................................................................72ezi_printable............................................................11, 125ezi_realloc........................................................................11ezi_rtrim...........................................................................11ezi_salloc.........................................................................11ezi_salloc, ezi_calloc, ezi_realloc...................................11ezi_since_when................................................................60ezi_since_when().............................................................60ezi_snprintf......................................................................11ezi_sproc..................................................................11, 125ezi_squash................................................................11, 125ezi_trunc..........................................................................11ezi_vsnprintf....................................................................11Ezi-String Function Suite................................................11Ezi-Types.........................................................................10eziq_add.........................................................................109eziq_check.....................................................................109eziq_delete.....................................................................109eziq_empty....................................................................109eziq_full.........................................................................109eziq_get..........................................................................109eziq_init.........................................................................109eziq_num.......................................................................109eziq_scan.......................................................................109eziqueue::~eziqueue()....................................................109eziqueue::add()..............................................................109eziqueue::check()...........................................................109eziqueue::del()...............................................................109eziqueue::empty()..........................................................109

eziqueue::eziqueue........................................................109eziqueue::full()..............................................................109eziqueue::get()...............................................................109eziqueue::num().............................................................109eziqueue::scan_init()......................................................109eziqueue::scan().............................................................109EZISTR............................................................................11EZISTR_T.......................................................................10EZISTR_T* type.............................................................11EZISTRBASIC................................................................11EZISTREMPTY..............................................................11fd_set_and().....................................................................52fd_set_or().......................................................................52File Descriptor Set Operations........................................52File Name / Path - Splitting & Merging Routines...........56File Name or Path Changes.............................................57FILE_SCOPED_COMPILE_TIME_ASSERT...............32File-in-memory Vs File-on-disk - FileHasChanged........54FileHasChanged..............................................................54fnmerge............................................................................56fnsplit...............................................................................56fProgCalc.......................................................................104GetDateTimeStamp().......................................................42GetPixelSizes.................................................................133GotoErrorCheck..............................................................46GotoErrorCheckCat.........................................................46GotoErrorCheckCatEzi....................................................46GotoErrorSet....................................................................46GotoStatusCheck.............................................................46Hex Checker....................................................................59hex36range......................................................................59Human-Readable Time Period - 'Since When'................60i_commas.........................................................................44Indexes - The Ezi Index Suite.........................................61int_zero..........................................................................138Integers to ASCII Conversion.........................................68Interprocess Communication, Debugging & Monitoring72IS_EMPTY......................................................................61IS_FULL..........................................................................61IS_IN_BETWEEN........................................................115IS_IN_BETWEEN_SANE............................................115IS_IN_RANGE..............................................................115IS_IN_RANGE_SANE.................................................115IS_INDEX.....................................................................115IS_INDEX_SANE.........................................................115IS_SPAN_OK................................................................115IS_SPAN_SANE...........................................................115itoa...................................................................................68JOG..................................................................................61Large Character Functions..............................................85lgspace.............................................................................85lgspace*...........................................................................85Logging Events (Encrypted)............................................79long_zero.......................................................................138loopfunc.........................................................................102ltoa...................................................................................68LTR..................................................................................85LTR*................................................................................85Make Directory Path........................................................43MAX................................................................................88MAX3..............................................................................88MAX4..............................................................................88

alflb_20120306.odt © 2002-2012 Alf Lacis Page 143 of 145

Page 144: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

mem_backup....................................................................94mem_restore....................................................................94memall.............................................................................91MEMCCPYSZ................................................................93MEMCMPSZ..................................................................93MEMCPYSZ...................................................................93memfill............................................................................92MEMMOVESZ...............................................................93Memory All the Same Value?..........................................91Memory Backup & Restore Functions............................94Memory Fill with Copies.................................................92Memory Function Wrappers - MEMSETSZ, etc............93Memory X-Or - memxor.................................................98MEMSETSZ....................................................................93memxor............................................................................98Millisecond Timing.........................................................99MIN.................................................................................88MIN3...............................................................................88MIN4...............................................................................88mkdirhier.........................................................................43MSBCopyChar................................................................58MSBCopyLong................................................................58MSBSetLongParm...........................................................58NEXT..............................................................................61NEXT_GP.......................................................................61NEXT_MACRO..............................................................61NEXT_N..........................................................................61NIB_ALL......................................................................101NIB_DECLARE............................................................101NIB_GET......................................................................101NIB_MAX_BYTES......................................................101NIB_SET.......................................................................101Nibble Array Suite.........................................................101No-Operation Functions................................................102noop...............................................................................102nooploop........................................................................102Normalisation................................................................115NORMALISE_RANGE................................................115null.................................................................................103NULLIFY......................................................................108Number of Entries in an Array........................................26numeric string with commas...........................................44opt....................................................................................72opt helper program..........................................................74opt_alive..........................................................................72opt_alive helper program.................................................76opt_shell..........................................................................72opt_shell helper program.................................................77Path or File Name Changes.............................................57Percentage Progress Calculator.....................................104plural..............................................................................106plurals............................................................................106Pointer - Casting and Setting.........................................107Pointer - return memory & nullify pointer....................108PREV...............................................................................61PREV_GP........................................................................61PREV_MACRO..............................................................61PREV_N..........................................................................61Processor, String, Suite..................................................125ProgCalc........................................................................104Queues - The Ezi Queue Function Suite.......................109Range Checking.............................................................115

Read a Buffer From a File.............................................136readbuf...........................................................................136readbuf_ver....................................................................136Real Time Clock Functions.............................................99replace............................................................................117Replace Pattern Character in a String - replace, etc......117replacen..........................................................................117Return Macros.................................................................46ReturnErrorCheck............................................................46ReturnErrorCheckCat......................................................46ReturnErrorCheckCatEzi.................................................46ReturnErrorSet.................................................................46ReturnStatusCheck..........................................................46Reverse a String - reversen............................................118reversen..........................................................................118SCHAR............................................................................10sctoa.................................................................................68short_zero......................................................................138ShorterName..................................................................133SINT................................................................................10sitoa..................................................................................68SLL..................................................................................10SLONG............................................................................10sltoa..................................................................................68sltoa_direction.................................................................68SortableDateTimeStr().....................................................42SortableDateTimeStrTS()................................................42SortableTimeStrTS().......................................................42SSHORT..........................................................................10sstoa.................................................................................68stoa...................................................................................68strcasestr........................................................................121strcatlen..........................................................................122strcmpi...........................................................................119STREQUAL..................................................................119stricmp...........................................................................119STRIEQUAL.................................................................119String Catenate..............................................................122String Equality Checks - Various...................................119String N-Copy with Trailing Null – strncpyn(), etc......124String Processor Suite....................................................125StrippedSize...................................................................129strncatlen........................................................................122strncmpi.........................................................................119strncpyn.........................................................................124strncpyprintn..................................................................124STRNEQUAL...............................................................119strnicmp.........................................................................119STRNIEQUAL..............................................................119swedish_build................................................................130Tab/Comma Separated Variable (csv/tsv) Files - Reading...................................................................................28, 32Tagged Variable Search - TS_Info, etc..........................131TagStringFind................................................................131TagStringMakePrefix....................................................131timer_msec......................................................................99timer_msec_ended...........................................................99timer_msec_fmt...............................................................99TIMER_MSEC_FMT_SZ...............................................99timer_msec_free_running_counter..................................99timer_msec_get................................................................99timer_msec_increment....................................................99

alflb_20120306.odt © 2002-2012 Alf Lacis Page 144 of 145

Page 145: ALFLB Library Functions - Netspacealfredo4570.customer.netspace.net.au/src/alflb_doco/alflb.pdf · ALFLB Library Functions Issue Date Nature of Amendment 20070925 Changed public interface

ALFLB Library Functions

TS_Info..........................................................................131TS_InfoQual..................................................................131UCHAR...........................................................................10uchar_zero.....................................................................138uctoa................................................................................68UINT................................................................................10uint_zero........................................................................138uitoa.................................................................................68ULL.................................................................................10ULLSZ.............................................................................10ULONG...........................................................................10ulong_zero.....................................................................138ULONGSZ......................................................................10ultoa.................................................................................68ultoa_direction.................................................................68uniquify..........................................................................134USHORT.........................................................................10ushort_zero....................................................................138USHORTSZ.....................................................................10ustoa.................................................................................68utoa..................................................................................68Write a Buffer To a File.................................................136writebuf..........................................................................136writebuf_ver..................................................................136Zeros..............................................................................138_xxxx, _xxxx_xxxx, _xxxx_xxxx_xxxx_xxxx...............25

alflb_20120306.odt © 2002-2012 Alf Lacis Page 145 of 145