*Apologies to Mark Knopfler!
My library software follows certain conventions that you might find useful to know when using or examining the software:
obj_util.c") is a package of functions that operate on a particular type of object; e.g., a network connection, a hash table, etc. Associated with each package is a header file ("
obj_util.h") which defines an opaque handle for objects of the given type, any global variables, and function prototypes for public functions in the package.
objCreate()creates a particular type of object and returns a handle that is passed to other functions in the package.
objDestroy()destroys an object.
objDelete()add and delete items in a container object; e.g., elements of a list, entries in a hash table, etc.
objGet()retrieve items by name and by index, respectively, from a container object.
objClose()create and destroy, respectively, objects of the given type.
objFd()returns the underlying UNIX file descriptor for an I/O object.
objIsUp()poll an I/O object.
objName()returns the name of an I/O object.
objWrite()perform actual I/O on an object.
EINVALindicates an invalid argument, etc.
obj_util_debugvariable that can be set to a non-zero value to enable debug output to
stdout. There's usually a command-line option, "
-debug", to enable normal debug output and "
-Debug" to enable more detailed output when applicable. (See the
aperror()is a perror(3)-like function that formats and prints a user error message on
stderr, followed by the system error message corresponding to the current value of
aperror()output is enabled by setting a global variable,
aperror_print, to a non-zero value. (See the
aperror()to report errors (in addition to returning an error code). A rather primitive mechanism for reporting errors? You betcha—but at least it's there!
aperror_printis initialized to zero, you normally won't see any error messages. My programs sometimes enable
aperror()output during initialization (when configuration errors and such like may occur) and disable it thereafter.
obj_util_debugdebug logging and
aperror()error reporting described above, I later implemented configurable, C Preprocessor-based error and debug logging. Macros defined in
pragmatics.hare combined in high-level macros
LGIfor logging information and
LGEfor logging errors; for example:
LGI "(rex_match) Scanning \"%s\" for \"%s\"\n", &target[first], pattern->expression) ; ... LGE "(rex_replace) Error duplicating source string, \"%s\"\nstrdup: ", source) ;These macros were inspired by similar macros in the GNU Nana package. I couldn't use Nana itself because it depends on GCC's extension for C Preprocessor macros with variable numbers of arguments and not all the platforms I was building on supported this extension. Hence my syntax of, for example, "
LGI format, arg1, ..., argN) ;", with a trailing parenthesis but no leading parenthesis.
obj_util_debugI personally use, as well as the totally different error and information logging mechanism we used on a large company project.
More to follow when I think of it ...
In writing my software, I try to make it as portable as possible. I make use
of ANSI C libraries and header files as much as I can. Function declarations
are made in both ANSI C and non-ANSI C form, so the code will compile whether
your compiler is ANSI C-compliant or not. I've attempted to isolate compiler
and OS dependencies in a header file,
except for some networking and time definitions that are found in
The major operating systems I've used are:
In previous years, earlier incarnations of my software were built and run on the following OSes: SunOS (on 68K and SPARC platforms), HP/UX, IBM's AIX (we had a single PC RT in the late 1980s), Lynx OS 2.4 (on a PowerPC), PalmOS (68k), and VxWorks (circa 1990 and again in 1994-1996).
I currently have access to:
I've tried to write portable software, but I haven't been able to perform extensive testing of my software in 64-bit environments, especially with regards to the differences resulting from the I32LP64 and IL32P64 data models of Unix and Windows, respectively.
On Windows, I build static libraries and link them to console applications. The libraries are small. so there's no advantage to my figuring out DLLs yet.
The software distributions generally include the following Makefiles. The most
up-to-date Makefile is always
Makefile.linux, so start with it as
a model for new Makefiles:
Makefile.linux- for building under Linux using gcc. This is the only Makefile that generates the regular expression parser using yacc/bison; the other Makefiles use the pre-generated file,
Makefile.cygwin- for building under Cygwin using gcc. These Makefiles are identical to the Linux Makefiles except that libgpl uses the pre-built regular expression parser instead of running yacc/bison.
Makefile.solaris- for building under Solaris using cc or gcc. Support for cc may not work (or be missing from newer Makefiles) since I no longer have access to the earlier Sun machines.
Makefile.tcc- for building under Linux using the blindingly fast Tiny C Compiler (TCC). Way back when, I submitted a bug report regarding the layout of fields within unions or structures that affected my CORBA code. The bug was supposedly fixed, but it appeared to still be present in later versions of the compiler. Regardless, TCC is amazing!
Makefile.freebsd- for building under FreeBSD. I briefly had my home computer dual-booting FreeBSD. It was never able to run my monitor at greater than 800x600 resolution, so I finally ditched FreeBSD for now.
Makefile.palm68k- for building PalmOS libraries and standard I/O applications under Linux using PRC-Tools (GCC for Palm OS).
Makefile.nds- for building Nintendo DS libraries and standard I/O applications using the devkitPro tool chain (GCC for ARM).
vaxc.com- for building under VAX/VMS. A semi-handcrafted batch file to build the code. The VAX I had available for testing didn't have MMS (?) installed. (As an example, here's
vaxc.comfor my General Purpose library.)
*.vcxproj.filters- Microsoft Studio 2010 solution, project, and filters files, respectively.
With respect to PalmOS, I built my libraries with PRC-Tools and I created a number of StdIOPalm applications that use the libraries. Click on the Palm Pilot thumbnail to see the screen output from a port scanner, scanet, running in the POSE emulator. I have not worked with PalmOS for quite some years now; the Palm world moved on to newer operating systems and eventually disappeared.
Update early 2016: I've got three versions of the PalmOS SDK and, on a whim, I installed the PRC-Tools RPMs on a machine running an aging Fedora Core 15. My code used to build under FC1 and FC2, but I got compilation errors and the cause wasn't obvious despite some effort at online research. However, I later installed PRC-Tools under Cygwin32 and, with some slight tweaking, I've been able to compile and build my code, as well as test some of it in two Windows versions of the POSE emulator. I have to use ROM images I found online because my Palm m105 now won't respond to POSE requests to transfer the m105's ROM image. The base CORBA library seems to work, but trying to build the CORBA-based EPOCH applications gives me errors indicating the relative branch limit is being exceeded in one or more code sections. (Looking at this page, I see that the increasing size of the EPOCH IDL caused the limit to be exceeded back in 2006.)
Thanks to the following people for bug and porting reports:
rex_wild(); if I was Donald Knuth, I'd have paid him for it!
I don't have the changes required for the various ports, but at least I know it's possible to port the code to the various platforms with relatively little trouble. My apologies to anyone I've left out, including those who reported bugs (e.g., in the quadword utilities and in the IPC utilities) before I started keeping a list here.
Last Update: Tue Dec 20 14:37:58 2016
Licensing: The CSOFT libraries and applications are covered by the MIT License. Basically, you are free to use the software however you see fit, in commercial or non-commerical applications. I only ask that, if your time and inclination permit, you report any bugs or portability problems you encounter. Suggestions for improvements and enhancements are welcome, but I do not guarantee I will act upon them.
Command Line Processing
opt_util- full-word option scanning package for UNIX-style command lines or strings.
gsc_util- generic depth-first and breadth-first graph search package.
hash_util- hash table creation/search package.
list_util- generic list handling package.
nnl_util- name/number lookup package.
tpl_util- N-tuple creation and element retrieval.
perror(3)-like error reporting function.
drs_util- directory scanning package.
fnm_util- file name parsing package.
The IPC packages provide named message queues, semaphores, and shared memory segments under UNIX and VxWorks. Earlier versions of the semaphore and shared memory packages were ported to VMS by Fred Shaklan and myself; message queues were not needed, but they could have been easily emulated using mailboxes. If I ever work on VMS again, I'll port the new packages; the package APIs are operating system-independent.
msq_util- high-level interface to named message queues (UNIX and VxWorks).
nob_util- named objects database package.
sem_util- high-level interface to named semaphores (UNIX and VxWorks).
shm_util- high-level interface to named shared memory (UNIX and VxWorks).
meo_util- memory operations.
get_util- miscellaneous string scanning functions.
rex_util- full-featured regular expression matching and substitution package.
str_util- miscellaneous string handling functions.
utf_util- Unicode Transformation Format (UTF) functions.
wcs_util- wide-character string handling functions.
bmw_util- benchmarking package.
ts_util- POSIX timespec manipulation package.
tv_util- UNIX timeval manipulation package.
bit_util- bit manipulation functions.
id3_util- ID3 tag access functions.
xqt_util- shell execution package (high-level interface to UNIX shell or VMS CLI).
The following packages provide high-level, but powerful, interfaces to TCP/IP and UDP/IP networking:
tcp_util- high-level interface for TCP/IP network socket I/O.
udp_util- high-level interface for UDP/IP network socket I/O.
And the following packages implement higher-level protocols layered on top of the TCP_UTIL package:
lfn_util- high-level interface for LF-terminated network I/O.
nft_util- FTP server framework (UNIX, VMS, and VxWorks).
xnet_util- high-level interface to
xdr(3)-based network I/O.
The IOX package simplifies the writing of I/O-event-driven applications (e.g., network servers):
iox_util- I/O and timer event dispatcher.
port_util- simple listening ports for IOX dispatcher-based network servers.
The remaining packages are an assortment of networking support functions:
net_util- miscellaneous network functions.
skt_util- socket support functions.
These three packages implement version-independent messages as described in Appendix B of Robert Martin's Designing Object-Oriented C++ Applications Using the Booch Method. (What he calls attributed data trees, I call name/value lists.) VIM network streams are layered on top of the TCP_UTIL package.
nvp_util- name/value pairs.
nvl_util- lists of name/value pairs.
vim_util- version-independent message streams.
The CORBA-Lite packages provide a lightweight implementation of CORBA TCP/IP messaging.
coli_util- CORBA messaging functions.
comx_util- CORBA marshaling functions.
gimx_util- GIOP marshaling utilities.
iiop_util- Internet Inter-ORB Protocol (IIOP) streams.
idl.h) - GNOME Bonobo 2.0 marshaling functions.
idl.h) - Data Acquisition from Industrial Systems (DAIS) marshaling functions.
idl.h) - Data Distribution Service for Real-Time Systems (DDS) marshaling functions.
idl.h) - Laboratory Equipment Control Interface Specification (LECIS) marshaling functions.
Note: Preferring C to C++, I haven't used or updated this library in nearly 10 years. It worked when I did use it!
The ZIP file contains 3 library directories:
rex_utilcode in my C++
RegExpclass, so I used the existing Unix regex(3) library.
The latter two libraries can be dropped if you build a subset of the liberal library. The first six classes listed below have counterparts in the C-language libgpl library and the remaining, EPOCH-specific classes have counterparts in the libepl library.
Dispatcher- I/O events dispatcher.
HashTable- hash table creation and search.
OptionsScan- command-line options scanning.
Endpoint- network endpoint.
TcpEndpoint- TCP/IP endpoint.
BufferedTCP- buffered TCP/IP stream.
EpochStream- EPOCH network stream.
EpochMessage- EPOCH network message.
CortexStream- CORTEX network stream.
NVar- named variables.
NVarSet- sets of named variables.
NVarFile- files of named variable sets.
GSegment- EPOCH global variable segments.
GVar- EPOCH global variables.
Note: As with the liberal library above, I haven't used this library in nearly 10 years. It worked well when I did use it! The archive files above include the project-specific applications below and the latest csoft library.
64-bit Note: All our project code was built in
32-bit mode, so I never tested this code in 64-bit builds. Some of the
code dates back to late 1996 or early 1997 and I generally used
long to guarantee 32-bit integers. This could cause
epc_util communications between heterogeneous
platforms, because the message header has
long fields. The
CORTEX code also uses
longs in the CORTEX message header.
I'm not sure how the CORBA code is affected: it uses
for 32-bit integers and
long long for 64-bit integers; I
don't believe this affects the over-the-network data stream.
eco_util- EPOCH V4 CORBA-Lite utilities.
edb_util- EPOCH events database utilities.
epc_util- EPOCH network communications.
gv_util- EPOCH global variables.
ins_util- IN-SNEC CORTEX utilities.
nvf_util- named variable set files.
nvr_util- named variable utilities.
nvs_util- named variable sets.
- A pocket FTP/WWW server. (When you select the file in the Nintendo DS directory listing, the icon is animated and looks pretty cool, with the red lines pulsating in all directions! Well, at least the 4 diagonal lines radiating out from the center. Yes, anise does work on the NDS. There was or still is a problem in the NDS sockets library when you close a network connection. Your peer on the connection may receive the close-connection message before he/she has received all the data in the pipeline. Consequently, retrieving a file via FTP from the NDS is likely to fail. The WWW server avoids this problem by keeping each connection alive for 30 seconds after sending the last data.)
- Networking extensions to John Sadler's Ficl (Forth Inspired Command Language) interpreter.
- A network server that provides each client with its own Tcl interpreter, extended with networking and hardware debugging commands. (Derived from earlier programs, nicl and picl!)
- Collects function-by-function metrics for C source code. The metrics include lines-of-code, Halstead's Software Science volume, McCabe's cyclomatic complexity, and NPATH.
- Networking extensions to the TinyScheme interpreter.
- chafn - change file names.
- colior - dump CORBA Interoperable Object Reference (IOR).
- dump - formatted dump program.
- duop - dump old-style Opera files.
- ffc - format file in columns.
- gflow - graph flow.
- talknet - network talk utility.
- tag311 - add/change ID3v1.1 tags on MP3 files.
Project-Specific Tools (EPOCH)
The following programs were used in both Versions 3 and 4 of our system. Cornet, dumpaev, milk, and the descendants of epcot and entice were used extensively. I wrote dssi, eniac, and mcci just for the heck of it and they were probably run just once to see if they worked!
- cornet - CORTEX network tool.
- dssi - Dynamic Spacecraft Simulator (DSS) Interface client or server.
- dumpaev - EPOCH archive dumper.
- eniac - Enertec interactive client.
- epcot - EPOCH-CORTEX telemetry server.
- This program was later ported to C++ by me and given the bland name of CortexTlm by the powers-that-be!
- mcci - acts as a Mission Control Center (MCC) client or Spacecraft Control Center (SCC) server.
- milk - EPOCH device handler reader/writer.
- This program was usually used for feeding canned telemetry data into the system for testing purposes. (Regarding the name: milk originally talked to a program, cereal, which emulated our serial-port device handler. We later switched to CORTEX and CORTEX-emulating Enertec interfaces. Consequently, cereal was replaced by a program, entice (Enertec In-Circuit Emulator), which, in turn, was ported to C++ by me and given the bland name of SimHandler by the powers-that-be!)
The following programs were specific to Version 3 of our system. They're all command-line tools and were a lot quicker and easier to use during testing than having to bring up the ponderous, X Windows GUIs to effect or monitor some action. I rarely used the last two, stamp and v3net.
- const - EPOCH V3 node management client.
- direct - EPOCH V3 directive submitter.
- eire - EPOCH V3 events reader.
- glop - EPOCH V3 global variable print.
- stamp - EPOCH V3 stored command client.
- v3net - generic EPOCH V3 client/server network tool.
The following programs were clients for our CORBA-based Version 4 system. As with the Version 3 programs above, these are all command-line tools and were a lot quicker and easier to use during testing than having to bring up the ponderous, Microsoft Windows GUIs to effect or monitor some action. The database clients, cdc and db4u, were very useful because they exhaustively retrieved every bit of information from the database servers, thus exercising them more than our actual system did. The point service client, psic, could request, retrieve, and display running updates of some or all of the available telemetry and non-telemetry points. The test team used to run it in parallel with the test system so that they could determine if a point-service problem was on the GUI client side of the system or the Unix server side.
- cdc - EPOCH CORBA command database client.
- dart - EPOCH CORBA data retriever client.
- db4u - EPOCH CORBA telemetry database client.
- dirt - EPOCH CORBA directive submitter.
- f4rd - EPOCH CORBA telemetry frame reader.
- noman - EPOCH CORBA node management client.
- psic - EPOCH CORBA telemetry point service client.
- (Pronounced "p-sick". I should have called it "Point Service/CORBA" or psico, pronounced "psycho"—an opportunity missed!)
- v4ever - EPOCH CORBA events reader.