C function library for 4gl



About this document

This document originally started as Manifesto, and was modified for purposes of documenting the way the source code is structured and used.

"C function library for x4gl" documentation consists of two documents; this one - "Introduction" and Catalogue of functions by source file.

This software was originally developed by Andrew Hamm and donated to OpenSource environment of Aubit 4gl project, under LGPL GNU license. It has a dedicated mailing list hosted  at Aubit mailing lists home page

support is provided via mailing list. At the moment, this software is available only in Source code form, and only directly from CVS. Please see CVS instructions on Aubit project CVS home page.

Most of the functions are in production but some are "good ideas" and may not be 100% correct or may not be 100% elegant. If anyone wants to use them straight away please e-mail me for an opinion. I'll either say "yup - they're good" or "I'm not happy with that one so give me 10 minutes." You'll probably be able to work out the quality of the straight-forward ones anyway.

Top


C functions for Informix 4GL and friends

Informix 4GL supports the addition of C functions to the RDS runners, which allows you to extend the power of the 4GL language into other areas, not easily, or at all, achievable using only 4GL built-in syntax. My company Sanderson Australia Pty Limited (formerly Wacher Computing Solutions and soon to be something else - sigh) have used Informix 4GL for close to 10 years, and in that time we have developed a large suite of C functions for 4GL.

Noises made recently on the Informix newsgroup have prodded a few people into collating a public collection of C functions. This page is the beginning of my part in the effort.

Top


Responsibility

All care but no responsibility!!!! How could it be any other way?

Top


4GL compilers supported

These functions are all coded to work with Informix 4GL/RDS (P-code), Informix 4GL (C compiled) and Four J's Universal 4GL (A.K.A. Informix Dynamic 4GL) for both P-CODE and C compiled versions*. 

NOTE: Strictly speaking, 4GL for C compiling is called simply "4GL" and 4GL p-code is called 4GL RDS. However, to be completely clear during any discussion, I'll call them 4GL/C and 4GL/RDS.

Aubit 4GL and other 3rd party 4GL compilers may be automatically supported (perhaps with a little effort) depending on their compatibility with the internals of Informix 4GL. Part of this project could be to adapt the functions for these other products (by putting them on a piece of wood and banging a few nails through them?) This will of course have to be performed by interested parties.

* NOTE: Four J's have stated they will remove their support for C compiled 4GL. This was what I heard a year ago anyway... things might have changed since then. Check with Four J's for more accurate information.

Top


Ownership of work

The functions that I've developed will probably remain under copyright to Sanderson, but since they are being published, clearly that's of little relevance to us programmers. Please maintain the copyright messages however; I like to think my work will be treated with due respect.

The new printf set of functions were developed by Art S. Kagel, long-time resident of the Informix newsgroup. Once again, pay due respect to any copyright requirements.

At a guess, Jonathan Leffler might contribute something, even if it's only good advice, and I know Andrej Falout will be getting involved. Everyone is invited to participate, especially if you have any interesting functions of your own, or if you are involved with Yet Another 4GL Compiler (YA4C)

Top


Naming conventions

Since these functions can be linked to 4GL/C as well as 4GL/RDS, the function names cannot conflict with any C function names. That precludes the use of function names like "fopen", "select", "bind", "malloc" and so on.

Informix, and to a greater extent Four J's, have added some functions to 4GL and they usually start with fgl_. Therefore I consider fgl_ to be a reserved name space, however other people do not. They reason that if Informix ever implements their own version of the functions then the private versions become redundant. That's very true assuming the Informix versions cover all the same functionality. More to the point, the rate of change of 4GL is so slow that you could almost say there will never be a conflict.

All the functions start with c_ and internal functions (ie private to the 4GL library but external in scope) have all been prefixed by cfgl_.

Although it's a generally overblown issue, it still needs light debate so do your best...

Top


Coding conventions

Code-sharing
Any half-decent library suite will inevitably require it's own little army of support functions and variables. I don't see the point in having 40 functions each with code to report usage errors or blank-trim strings etc. so some attention has been paid to suitable support functions.

All .c files include cfun4gl.h which contains universal #includes and definitions. You'll find defines for many things including a few macros that help to extract some intelligence from the source using Perl scripts.

A file called cfun4gl.c contains the bulk of the support functions. Some support functions are local static in the individual .c file because they have no other use.

Top

Knowledge of 4GL internals
As much as possible, the code should avoid any knowledge of the internal structure of the Informix 4GL runtime. This of course must also apply to other compilers such as Four J's and Aubit. There is a published interface for attaching C functions to the 4GL runtime and we should strive to stay within those bounds. A significant benefit of this is that you can link old objects to new runners without having to recompile the C. Another way of looking at this is, the same C object files can be linked to a variety of runtime types and versions without the added complication of maintaining many sets of object files.

The recent printf functions have violated that rule because they have a really difficult job to do. They don't work for Four J's because they are using a different internal stack structure. Looks like we'll be writing a full printf from scratch. Sounds horrible but I did it once when I was a young programmer so can't be that hard to do it again. At least we'll be able to boast a version of printf which is truly portable. I don't think we need to implement 100% of the full C printf.

Top

C/4GL calling convention defined by Informix
One of the minor hassles with building C functions for 4GL is the need to use a very un-C-like calling convention with it's associated dross. No, I'm not complaining about that convention, but it does require some care. I have used a C macro called "function" to build the C function headers. This macro includes parameters for numbers which describe the argument and return parameter counts. Perl scripts (functions.pl and ...) are used to generate includable function headers, and the interface definitions (hooks into 4GL)

The script functions.pl performs this dutyes:

See the .c files mentioned to get a feel for it.

This Perl script looks for the function macro lines, and also looks for the optional RUNNER macros in the .c files. These macros are described in cfun4gl.h and maybe here in more detail one day if someone has a question.

Top

4GL argument and return limitations
All 4GL function arguments are by value only so reference parameters cannot be used. Any value returned from the function must be part of the return list. As a result, some functions are forced to have a usage that is different from the well-known functions they are providing access to. This must be clearly documented (any volunteers?) and the functions must take care to check their usage (see below).

Informix 4GL and Four J's support variable argument lists and variable return lists so generally we can achieve our needs for some C functions which are vararg. One or two functions are pathologically difficult so their ambiguity is corrected using some ugly little booster arguments. The need for this is extremely rare, however.

Top

Error handling
Error handling is important in two ways. If the programmer calls the function incorrectly then they must be notified. Ideally, the compiler will return the error, but that's impossible so I've made the functions check their usage as carefully as possible and they emit a runtime error and terminate the program if there is a usage problem.

The other kind of error handling is more ordinary. If you attempt to open a file but it doesn't exist, then this failure should be returned to the calling code. If you attempt to open a file with 15 parameters on the function call, then that's clearly a usage error so the first response is more appropriate.

Most if not all low-level UNIX system calls return -1 for error and leave an error number in a variable called "errno". Higher level C functions from the standard libraries have "personalized" error conventions.

Currently the affected functions all record errno into a private variable which can be queried by a simple function call. I would like to look into doing something clever which stuffs the errno value (or other errors) into the 4GL status variable. Jonathan Leffler could probably advise on that, but even if it's possible with Informix, it must also be possible with Four J's and to a lesser extent with other YA4C.

Personally I feel that beyond Informix and Four J's, other 4GL systems should not hold our work to ransom, and it's a good opportunity for them to become more compatible anyway. Some might say Four J's does not deserve special status either, but they are the 2nd-biggest player with many customers.

Top

Accessing platform-specific C constants
UNIX error numbers and C constants may vary from platform to platform, so we can't force 4GL programmers to embed things like
    let x = c_errno()
    if x = 27 then
        ....
because 27 may be 28 on a different platform.

Defining symbolic constants through 4GL global variables is not good enough because they will have to be initialized differently depending on the platform the 4GL is delivered to. We supply several different platforms so we could not take advantage of the 4GL portability if we were forced into this. (Ed: this is probably a job for Autoconf)

Using a 4GL preprocessor to define constants (we have a 4GL preprocessor which supports constants and typedefs) is not adequate either because ultimately the constants will be mapped to simple numbers and once again the hard-coded, platform dependent numbers would be embedded in the RDS p-code.

To solve this problem, I've written a support function and defined a simple convention for passing constants back to 4GL. For any package that needs constants (and so far that's errno and the network socket functions) there will be a function available to 4GL called (for example) c__errno("str"). Note the double underscore. The string argument is a representation of the C constant - for example, c__errno("ENODIR").

Within the C library, we define a simple array (sorted by string name) which associates the string with the proper value. By the magic of the C compiler's preprocessor, the string will be mapped to the correct value using a simple (and fast) binary search of the array. Our happy 4GL programmers can now write:

    let x = c_errno()
    if x = c__errno("ENODIR") then
        ....

If anyone thinks they have a performance problem with this in 4GL, they can assign a bunch of 4GL globals with their favorite values somewhere very early in MAIN. Frankly I think that would be excessive and pointless.

Top


Your help needed

The primary purpose of inclusion of this code in OpenSource project, and not just releasing the code as downloadable archive to the public in some software repository, is to get interested parties to participate in it's future development. As with all Aubit 4gl project sub-projects, all forms of participations are invited and equally appreciated. This can range from using the library, and reporting bugs or discussing possible enhancements, to actively developing code and documentation in CVS repository. 

The best way to get involved is to subscribe to the mailing list, as the first step. There, you can discuss issues you have, and ask for CVS read/write permissions if there is something you want to contribute to source code or documentation.

This are some initial items on our TODO list:

Of course, your suggestions are welcome, and your participation appreciated.

See you on the mailing list!

Top


Installing and compiling

4Js/D4GL

 

Informix-4gl

 

Aubit

 

Other 4gl compilers

Top


Aubit 4gl project