The <nostub.h> header file
This header file will be automatically included in the program if any other header
file from this library is used, except if you define the global preprocessor symbol
USE_KERNEL
, or if you explicitely include doors.h
header file before including any other header file. This header file provides the basic
support for making a "nostub" (kernel-less) program, i.e. program which does not need any kernels
like DoorsOS or Plusshell (note that this does not imply that they can not
work under DoorsOS or PlusShell). The disadvantage of "nostub" programs is in
fact that they are somewhat longer than "DoorsOS" programs if the program contains
many ROM calls, and they can not call routines from external files (often called
"libraries"). Any other features supported with this library of header files work
in both "DoorsOS" and "nostub" mode, so if the difference in the program size is not
enormous, and if no external libraries are needed, "nostub" mode is highly recommended.
Note that routines defined in these header files contain the most of routines which
are seen in various external libraries, sometimes maybe with different name and
syntax.
Principally, this header file defines one global symbol named NOSTUB
which
is used in other header files to indicate "nostub" mode, and defines one essential
ROM-calling macro named _rom_call
, which is intensively used in all
other header files. This macro implements calling of ROM routines using indirect calls
through the jump table. This macro is smart, and constructs function calls on such way that
the compiler may perform compile-time checking of number and type of arguments (it, in fact,
performs a type-casting of the jump table entry to an adequate function type). More concretely,
_rom_call (return_type, argument_type_list, jump_table_index)
constructs indirect ROM call for function whose index in the jump table is
jump_table_index (this must be a hexadecimal number without 0x prefix),
whose return type is return_type, and which needs arguments described in
argument_type_list. This list is a list of types separated by commas, and
enclosed in small brackets. For example, look the function
memcpy which has the following prototype:
void *memcpy (void *dest, const void *src, unsigned long size);
If you know that the index of function memcpy in the jump table is 26A (these indexes are
documented by TI), you principally can make following (terrible) construction to call
memcpy passing dest, src and
len as arguments to it:
_rom_call (void *, (void *, const void *, unsigned long), 26A) (dest, src, len);
This is awkward, of course. Life may become better if you define
#define memcpy _rom_call (void *, (void *, const void *, unsigned long), 26A)
Then, you can simply use, as in each "normal" C dialect:
memcpy (dest, src, len);
Better, isn't it? This is, in fact, what the most of the header files in this library does.
Definition of this function may be simplified further, because "const" means nothing for built-in
assembly functions, and passing of unsigned and signed arguments are the same:
#define memcpy _rom_call (void *, (void *, void *, long), 26A)
If you need more info about _rom_call macro, inspect various header files to see how some
functions are implemented. Note that _rom_call is redirected in DoorsOS mode to implement
(shorter) DoorsOS calling method (see doors.h for more info).
What else does this header file? It is much more complex than in releases of TIGCCLIB
prior to 2.0, but you need not to call directly anything from it (many tasks will be performed
automatically). First, it contains one assembly instruction which solves completely one
essential bug in TIGCC which appears only in "nostub" mode. Without this patch, any
program which has any static data (including strings) will crash, and even if the
program has not static data, the first function in the program will always be executed
first regardless whether it is _main or not. It also plays some tricks with the machine
stack, necessary for supporting exit and
atexit functions without overloading the size of the
generated code. Next, this header file implements the necessary protocol for returning
values to the TI-Basic (either using the expressions stack or through a variable) if the
preprocessor symbol RETURN_VALUE
is defined before including this header file.
Finally, this header file makes some plays with preprocessor
to redefine the symbol _main
on such way that global symbol _nostub
will be automatically exported to the linker from any source file in which _main function is defined
(such plays are necessary to avoid multiple defining of the same symbol, which would not be allowed
by the linker). So, you don't need to put
int _nostub;
in your program to produce a "nostub" program. This header file will do this automatically
for you.
See also doors.h header file.