A linked Unicon program consists of the "Icode" bytes that are interpreted
by the Icon virtual machine, generally preceded by bootstrap code. This
bootstrap code is responsible for finding the Icon code executer, then
running the Icon executer so that it will interpret the "Icode" bytes that
follows the bootstrap code.  The bootstrap code takes one of several forms:

- Some Icon / Unicon configurations use no bootstrap code; in this case, the
Icon / Unicon linker produces a file that consists of "Icode" only, and this
file must be run by passing it to the Icon executer.
- On some platforms, this bootstrap code is executable image code, i.e. the
sort of code produced by the C linker.
- On most platforms, the bootstrap code can take the form of a shell script.
Depending on the OS, the script format is either Bourne shell, MS CMD file,
or Rexx.

The source code for writing or skipping over the bootstrap code to a linked
Icon / Unicon program has been developed by multiple authors over many
years. By its very nature, this facility is highly platform specific and
somewhat messy. The current implementation of bootstrap code is also messier
than it needs to be, as we shall soon see.

The configuration of this facility depends on two macros:

- The Header macro is defined when some sort of bootstrap code is to be
included; and
- The ShellHeader macro is defined when the bootstrap code takes the form of
a shell script.
- if Header is defined and ShellHeader is not defined, an executable image
header is to be used.

If Header and ShellHeader are defined, the kind of shell script used is
determined by the OS. As a result, the current code precludes the
possibility of supporting more than one script language for the bootstrap
code on a given platform. This is a limitation I have already encountered: I
make heavy use of the Cygwin environment, a Posix implementation for Win32
platforms. Either Bourne shell or MS CMD scripting is a viable option for
Cygwin, but you cannot switch between these options by merely changing the
"src/define.h" and "Makedefs" files.

The details of the various forms of bootstrap codes are divided among at
least 4 source files, with lots of details copied between these files. One
must be careful that any changes made in this facility (including additional
scripting languages) is done in tandem.

There are two separate mechanisms for generating the executable image
bootstrap code. The first step of generating the executable image bootstrap
code is to compile, link, and strip the C program "src/icont/ixhdr.c". Then,
one of two approaches are used to generate the header:

- either the ixhdr executable file is run through the "src/icont/newhdr"
program to turn in into a C header file "src/icont/hdr.h" that defines an
array of the bytes in ixhdr; or
- the ixhdr executable is copied to the ./bin directory, and icont will
assume that the ixhdr can always be found in the same directory as itself.

In the process of doing a new Cygwin port, I revised the bootstrap code
facility to make it both cleaner and more modular. The Header / ShellHeader
macros were dropped and replaced with the more appropriately named macro
Bootcode. The revised version of "src/h/config.h" defines the following
values for Bootcode:

#define Bootcode_None        0       /* No bootstrap code */
#define Bootcode_ExecImage   1       /* Executable image code */
#define Bootcode_BourneShell 2       /* Bourne Shell code */
#define Bootcode_MsCmd       3       /* MS CMD code */
#define Bootcode_Rexx        4       /* Rexx code */

The user can specify which kind of bootstrap code to use by declaring the
value of Bootcode in "src/h/define.h". For example, if I wanted to link
Unicon programs as Bourne Shell files, I could include the following line in
"define.h":

#define Bootcode Bootcode_BourneShell

If "src/h/define.h" does not define Bootcode, the revised "src/h/config.h"
file will provide a default value for Bootcode, based on the platform. This
scheme may sound messy, but it actually allows us to cut a lot of "#if" /
"#endif" directives from the rest of the code.

The new approach provides the following three functions that are used for
processing the bootstrap code in a Unicon / Icon program:

/*
 * put_bootcode - Writes boot code to outfile, sets *hdrsize to size of boot
code.
 */
void put_bootcode( FILE* outfile, const char* iconxloc, long* hdrsize );

/*
 * skip_bootcode - Skips boot code in infile;
 * If outfile != NULL, boot code from infile is copied to outfile.
 * Returns 1 if successful;
 * if it fails, returns 0 and writes an error message to errmsg.
 */
int skip_bootcode( FILE* infile, FILE* outfile, char* errmsg );

/*
 * put_bootend - Given an outfile that starts with boot code,
 * writes anything required at the end of the file to complete the code.
 * Returns 1 if successful;
 * if it fails, returns 0 and writes an error message to errmsg.
 */
int put_bootend( FILE* outfile, char* errmsg );

I created a new source file "common/src/bootcode.c" that implements these 3
functions. The implementations of these functions depends heavily on the
value of the Bootcode macro. The callers of these functions, however, does
not need to use ANY macros or preprocessor directives in order to process
bootstrap code. All of the gory details are encapilated in
"common/src/bootcode.c", and the rest of the code can treat this facility as
a black box.

I am pleased to report that I can now switch between linking Unicon programs
as *.exe files, *.bat files, or Bourne scripts with changing just a few
lines in "define.h" and "Makedefs" (related to file extensions). The source
is now cleaner. Moreover, if we ever needed to support another script
language for the bootstrap code, all we need to do is defined a new
"Bootcode_*" macro in "src/h/config.h" and update "src/common/bootcode.c" to
handle it. Everything else would be unchanged.

I have attached "src/common/bootcode.c" to this message. I would be happy to
send the rest of my changes to those who request it. Is this worth including
in a future version of Unicon / Icon?

Attachment: bootcode.c
Description: Binary data

Reply via email to