Details of target-dependent code


ANSI library functions

The following ANSI standard functions necessarily have an implementation completely dependent on the target operating system. No functions are used internally by the library (so if any are unimplemented, only clients which directly call the functions will fail).

clock_t clock(void)

(The compiler is expected to predefine __CLK_TCK if the units of clock_t differ from the default of centiseconds. If this is not done, time.h must be adjusted to define appropriate values for CLK_TCK and CLOCKS_PER_SEC).

void _clock_init(void) (declared weak)

Clock_init() (if you provide it) is called from the library's initialisation code, (clock() needs initialising if a read-only timer is all it has to work with).

time_t time(time_t *timer)
int remove(const char *pathname)
int rename(const char *old, const char *new)
int system(const char *string)
char *getenv(const char *name)
void getenv_init(void) (declared weak)

Getenv_init() is called from the library's initialisation code if you provide an implementation of it.

I/O support

If any I/O function is to be used hostsys.h must define the type FILEHANDLE, values of which identify an open file to the host system. There must be at least one distinguished value of this type, defined by the macro NONHANDLE, used to distinguish a failed call to _sys_open.

For an unaltered __rt_lib_init, the macro TTYFILENAME must be defined to a string to be used in opening a file to terminal.

The macro HOSTOS_NEEDSENSURE should be defined if the host OS requires an ensure operation to flush OS file buffers to disc if an OS write is followed by an OS read which requires a seek, (the flush happens before the seek). The RISC OS targetting needs this macro to be defined, thanks to an OS file-buffering bug; it is unlikely to be wanted in any retargetting.

FILEHANDLE _sys_open(const char *name, int openmode)

Openmode is a bitmap, whose bits mostly correspond directly to the ANSI mode specification: for details, see hostsys.h in Source organisation (target-dependent extensions are possible in which case freopen() must be extended too). The function _sys_open() is needed by fopen() and freopen(), which in turn are required if any I/O function is to be used.

int _sys_iserror(int status)

A _sys_iserror() function, or a _sys_iserror() macro, is required if any of the following int-returning functions is provided (to determine whether the return value indicates an error).

int _sys_close(FILEHANDLE fh)

The return value is 0 or an error indication. It must be defined if any I/O function is to be used.

int _sys_write(
    FILEHANDLE fh, const unsigned char *buf, 
            unsigned len, int mode)

The mode argument is a bitmap describing the state of the FILE connected to fh. (See the _IOxxx constants in ioguts.h for the its meaning: only a few of these bits are expected to be needed by _sys_write). The return value is the number of characters NOT written (i.e. non-0 denotes a failure of some sort), or an error indicator. This function must be defined if any output function or sprintf variant is to be used.

int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, i
            nt mode)

The mode argument is a bitmap describing the state of the FILE connected to fh, as for _sys_write. The return value is the number of characters NOT read (i.e. len - result were read), or an error indication, or an EOF indicator. The target-independent code is capable of handling either early EOF (the last read from a file returns some characters plus an EOF indicator), or late EOF (the last read returns just EOF). The EOF indication involves the setting of 0x80000000 in the normal result. The function _sys_read() must be defined if any input function or sscanf variant is to be used.

int _sys_seek(FILEHANDLE fh, long pos)

This function positions the file pointer at offset pos from the beginning of the file. The result is >= 0 if OK, negative for an error. The function must be defined if any input or output function is to be used.

int _sys_ensure(FILEHANDLE fh);

A call to _sys_ensure() flushes any buffers associated with fh, and ensures that the file is up to date on the backing store medium. The result is >= 0 if OK, negative for an error. This function is only required if you define HOSTOS_NEEDSENSURE (see above).

long _sys_flen(FILEHANDLE fh);

The above function returns the current length of the file fh (or a negative error indicator). It is needed in order to convert fseek(, SEEK_END) into (, SEEK_SET) as required by _sys_seek. It must be defined if fseek() is to be used. (Note: it is possible to adopt a different model here if the underlying system directly supports seeking relative to the end of a file. In this case, _sys_flen() can be eliminated.)

void _ttywrch(int ch)

This function writes a character, notionally to the console. Used (in the host-independent part of the library) in the last-ditch error reporter, when writing to stderr is believed to have failed or to be unsafe (e.g. in default SIGSTK handler). This function must be defined.

int _sys_istty(FILE *)

This function returns non-0 if the argument file is connected to a terminal. It is used to provide default unbuffered behaviour (in the absence of a call to set(v)buf), and to disallow seeking. It must be defined if any output function (including sprintf variants) or fseek is to be used.

void _sys_tmpnam(char *name, int fileno);

This function returns the name for temporary file number fileno in the buffer name. It must be defined if tmpnam() or tmpfil() are to be used.

Floating-point support

int __fp_initialise(void)
void __fp_finalise(void)

If the variant fp_type == module is selected, and the target-dependent library kernel follows the pattern of the RISC OS example, these two functions must be supplied (though they need not do anything). The function __fp_initialise() returns 1 if floating-point instructions are available, otherwise 0.

bool __fp_address_in_module(void *)

If the variant fp_type == module is selected and the supplied abort handlers are used, then the above function must be provided. It is intended to return 1 if the argument address falls within the code of the fp emulator, (to allow the abort handler to describe what is really an abort on a floating-point load or store as such, rather than somewhere within the emulator's code).

Kernel

The Kernel handles the entry to, and exit from, an application linked with the library. It also exports some variables for use by other parts of the library. Details of what the kernel must do are strongly dependent on details of the target environment. It is suggested that the ARMulator version of this file (kernel.s in the semi directory) be used as a prototype. The following are the main interfaces to the kernel:

__main()

The entry point to the application. Must perform low-level library initialisation, then call _main. (What initialisation needs to be done is target environment dependent: it may include heap, stack, fp support, calling various osdep_xxx_init() functions if they exist). __rt_lib_init must be called to initialise the body of the library.

void __rt_exit(int);

This function finalises the library (including calling atexit() handlers), then returns to the OS with its argument as a completion code. It must be provided.

char *__rt_command_string(void);

This function returns the address of (maybe a copy of) the string used to invoke the program. It must be provided.

void __rt_trap(__rt_error *, __rt_registers *);

__rt_trap() handles a fault (processor detected trap, enabled fp exception, or the like). The argument register set describes the processor state at the time of the fault, with the pc value addressing the faulting instruction (except perhaps in the case of imprecise floating-point exceptions). This function must be provided. The implementation in the ARMulator kernel will usually be adequate.

unsigned __rt_alloc(unsigned minwords, void **block);

__rt_alloc() is the low-level memory allocator underlying malloc(). (malloc() allocates only memory between HeapBase and HeapTop; a call to __rt_alloc() attempts to move HeapTop: cf Unix sbrk()). __rt_alloc should try to allocate a block of sensible size >= minwords. If this is not available, and if __osdep_heapsupport_extend is defined, it should call that to attempt to move HeapLimit. Otherwise (or if the call fails) it should allocate the largest possible block of sensible size. The return value is the size of block allocated, and *block is set to point to the start of the allocated block (the return may be 0 if no sensibly sized block can be allocated). Allocations are rounded up to a suitable size to avoid an excessive number of calls to __rt_alloc.

void *(*__rt_malloc)(size_t)

This is a function pointer, which the kernel should initialise to some primitive memory allocation function. The library itself contains no calls to malloc(), (other than those from functions of the malloc family, such as calloc()), instead the function pointed to by __rt_malloc is called. __rt_malloc is set to malloc during initialisation (if malloc is linked into the image). The use of __rt_malloc ensures that allocations made before malloc is initialised succeed, and prevents malloc from being necessarily linked into an image, even when unused.

extern void (*__rt_free)(void *);

This is a function pointer, which the kernel should initialise to some primitive memory-freeing function. (see __rt_malloc above).

Miscellaneous

void __osdep_traphandlers_init(void)

This arranges to catch processor aborts (and pass them to __rt_trap).

void __osdep_traphandlers_finalise(void)

This removes the processor abort handlers installed by ..._init().

void __osdep_heapsupport_init(HeapDescriptor *)

This function must be provided, but may be null.

void __osdep_heapsupport_finalise(void)

This function must be provided, but may be null.

{ int, void *} __osdep_heapsupport_extend(int size, HeapDescriptor *)

This function requests extension of the heap by at least size bytes. The return values are number of bytes acquired, and base address of the new acquisition. This function must be provided, (but a null version just returning 0 will suffice if heap extension is not needed).

char *_hostos_error_string(int no, char *buf);

This function is called to return a string describing an error outside the set ERRxxx defined in errno.h. (It may generate the message into the supplied buf if it needs to do so). It must be defined if perror() or strerror() is to be used.

char *_hostos_signal_string(int no)

This function is called to return a string describing a signal whose number is outside the set SIGxxx defined in signal.h.