RISCOS.com

www.riscos.com Technical Support:
Programmer's Reference Manual

 

The shared C library


Introduction

The shared C library is a RISC OS relocatable module (called SharedCLibrary) which contains the whole of the ANSI C library. It is used by many programs written in C. Consequently, it saves both RAM space and disc space.

The shared C library is used by the RISC OS applications Edit, Paint, Draw and Configure.

Generally you will use the shared C library by linking your programs with the library stubs. However, you may also call it directly from assembly language by means of SWIs provided by the shared C library (you would normally only want to do this if you are implementing your own library stubs for your own language run-time system).

Overview

How to use the C library kernel

C library structure

The C library is organised into three layers:

  • at the centre is the language-independent library kernel providing basic support services;
  • at the next level is a C-specific layer providing compiler support functions;
  • at the outermost level is the actual C library.

A full description of all the C library functions is given in the section entitled C library functions.

The library kernel

The library kernel is designed to allow run-time libraries for different languages to co-reside harmoniously, so that inter-language calling can be smooth. It provides the following facilities:

  • a generic, status-returning, procedural interface to SWIs
  • a procedural interface to commonly used SWIs, arithmetic functions and miscellaneous functions
  • support for manipulating the IRQ state from a relocatable module
  • support for allocating and freeing memory in the RMA area
  • support for stack-limit checking and stack extension
  • trap handling, error handling, event handling and escape handling.

A full description of all the library kernel functions is given in the section entitled Library kernel functions.

Interfacing a language run-time system to the Acorn library kernel

You can also write your own language Run-Time System to use the shared C library. For full details, see the chapter entitled Interfacing a language run-time system to the Acorn library kernel.

How the run-time stack is managed and extended
Management

The run-time stack consists of a doubly-linked list of stack chunks. Each stack chunk is allocated by the storage manager of the master language (in a C program allocating and freeing stack chunks is accomplished using malloc() and free()).

Stack extension

Two types of stack extension are provided:

  • Pascal/Modula-2 style
  • C-style

Calling other programs from C

The C library procedure system() provides the means whereby a program can pass a command to the host system's command line interpreter - in this case the RISC OS command line interpreter. For a full description, see the chapter entitled Calling other programs from C.

Storage management

The storage manager manages the heap in the most 'efficient' manner possible. A rudimentary understanding of it will help you make the best use of it; see the chapter entitled Storage management.

Handling host errors

Calls made to RISC OS via a kernel function return a specific value if an operating system error occurs. A call is provided to then find the associated error number and string. For full details, see the chapter entitled Handling host errors.

Technical details

The shared C library module implements a single SWI which is called by code in the library stubs when your program linked with the stubs starts running. That SWI call tells the stubs where the library is in the machine. This allows the vector of library entry points contained in the stubs to be patched up in order to point at the relevant entry points in the library module.

The stubs also contain your private copy of the library's static data. When code in the library executes on your behalf, it does so using your stack and relocates its accesses to its static data by a value stored in your stack-chunk structure by the stubs initialisation code and addressed via the stack-limit register. (This is why you must preserve the stack-limit register everywhere if you use the shared C library and call your own assembly language sub-routines.) The compiler's register allocation strategy ensures that the real dynamic cost of the relocation is almost always low: for example, by doing it once outside a loop that uses it many times.

Execution time costs

It costs only 4 cycles (0.5[MU]s) per function call and a very small penalty on access to the library's static data by the library (the user program's access to the same data is unpenalised). In general, the difference in performance between using the shared C library and linking a program stand-alone with ANSILib is less than 1%. For the important Dhrystone-2.1 benchmark the performance difference cannot be measured.

How to use the C library kernel

C library structure

The C library is organised into three separate layers. At the centre is the language-independent library kernel. This is implemented in assembly language and provides basic support services, described below, to language run-time systems and, directly, to client applications.

One level out from the library kernel is a thin, C-specific layer, also implemented in assembly language. This provides compiler support functions such as structure copy, interfaces to stack-limit checking and stack extension, setjmp and longjmp support, etc. Everything above this level is written in C.

Finally, there is the C library proper. This is implemented in C and, with the exception of one module which interfaces to the library kernel and the C-specific veneer, is highly portable.

The library kernel

The library kernel provides the following facilities:

  • initialisation functions
  • stack management functions:

    unwinding the stack
    finding the current stack chunk
    four kinds of stack extension -

      small-frame and large-frame extension,
      number of actual arguments known (eg Pascal), or unknown (eg C) by the callee.

  • program environment functions:

    finding the identity of the host system (RISC OS, Arthur, etc)
    determining whether the floating point instruction set is available
    getting the command string with which the program was invoked
    returning the identity of the last OS error
    reading an environment variable
    setting an environment variable
    invoking a sub-application
    claiming memory to be managed by a heap manager
    finding the name of a function containing a given address
    finding the source language associated with code at a given address
    determining if IRQs are enabled
    enabling IRQs
    disabling IRQs.

  • general utility functions:

    generic SWI interface routines
    special SWI interfaces for certain commonly used SWIs.

  • memory allocation functions:

    allocating a block of memory in the RMA
    extending a block of memory in the RMA
    freeing a block of memory in the RMA.

  • language support functions:

    unsigned integer division
    unsigned integer remainder
    unsigned divide by 10 (much faster than general division)
    signed integer division
    signed integer remainder
    signed divide by 10 (much faster than general division).

Interfacing a language run-time system to the Acorn library kernel

In order to use the kernel, a language run-time system must provide an area named RTSK$$DATA, with attributes READONLY. The contents of this area must be a _kernel_languagedescription as follows:

  typedef enum { NotHandled, Handled } _kernel_HandledOrNot
  typedef struct {
     int regs [16];
  } _kernel_registerset;
  typedef struct {
     int regs [10];
  } _kernel_eventregisters;
  typedef void (*PROC) (void);
  typedef _kernel_HandledOrNot
     (*_kernel_trapproc) (int code, _kernel_registerset *regs);
  typedef _kernel_HandledOrNot
     (*_kernel_eventproc) (int code, _kernel_registerset *regs);
  typedef struct {
     int size;
     int codestart, codeend;
     char *name;
     PROC (*InitProc)(void);  /* that is, InitProc returns a PROC */
     PROC FinaliseProc;
     _kernel_trapproc TrapProc;
     _kernel_trapproc UncaughtTrapProc;
     _kernel_eventproc EventProc;
     _kernel_eventproc UnhandledEventProc;
     void (*FastEventProc) (_kernel_eventregisters *);
     int (*UnwindProc) (_kernel_unwindblock *inout, char **language);
     char * (*NameProc) (int pc);
  } _kernel_languagedescription;

Any of the procedure values may be zero, indicating that an appropriate default action is to be taken. Procedures whose addresses lie outside [codestart...codeend] also cause the default action to be taken.

codestart, codeend

These values describe the range of program counter (PC) values which may be taken while executing code compiled from the language. The linker ensures that this can be described with just a single base and limit pair if all code is compiled into areas with the same unique name and same attributes (conventionally, Language$$code, CODE, READONLY. The values required are then accessible through the symbols Language$$code$$Base and Language$$code$$Limit).

InitProc

The kernel contains the entrypoint for images containing it. After initialising itself, the kernel calls (in a random order) the InitProc for each language RTS present in the image. They may perform any required (language-library-specific) initialisation: their return value is a procedure to be called in order to run the main program in the image. If there is no main program in its language, an RTS should return 0. (An InitProc may not itself enter the main program, otherwise other language RTSs might not be initialised. In some cases, the returned procedure may be the main program itself, but mostly it will be a piece of language RTS which sets up arguments first.)

It is an error for all InitProcs in a module to return 0. What this means depends on the host operating system; if RISC OS, SWI OS_GenerateError is called (having first taken care to restore all OS handlers). If the default error handlers are in place, the difference is marginal.

FinaliseProc

On return from the entry call, or on call of the kernel's Exit procedure, the FinaliseProc of each language RTS is called (again in a random order). The kernel then removes its OS handlers and exits setting any return code which has been specified by a call of

_kernel_setreturncode.

TrapProc, UncaughtTrapProc

On occurrence of a trap, or of a fatal error, all registers are saved in an area of store belonging to the kernel. These are the registers at the time of the instruction causing the trap, except that the PC is wound back to address that instruction rather than pointing a variable amount past it.

The PC at the time of the trap together with the call stack are used to find the TrapHandler procedure of an appropriate language. If one is found, it is invoked in user mode. It may return a value (Handled or NotHandled), or may not return at all. If it returns Handled, execution is resumed using the dumped register set (which should have been modified, otherwise resumption is likely just to repeat the trap). If it returns NotHandled, then that handler is marked as failed, and a search for an appropriate handler continues from the current stack frame.

If the search for a trap handler fails, then the same procedure is gone through to find a 'uncaught trap' handler.

If this too fails, it is an error. It is also an error if a further trap occurs while handling a trap. The procedure _kernel_exittraphandler is provided for use in the case the handler takes care of resumption itself (eg via longjmp).

(A language handler is appropriate for a PC value if LanguageCodeBase <= PC and PC < LanguageCodeLimit, and it is not marked as failed. Marking as 'failed' is local to a particular kernel trap handler invocation. The search for an appropriate handler examines the current PC, then R14, then the link field of successive stack frames. If the stack is found to be corrupt at any time, the search fails).

EventProc, UnhandledEventProc

The kernel always installs a handler for OS events and for Escape flag change. On occurrence of one, all registers are saved and an appropriate EventProc, or failing that an appropriate UnhandledEventProc is found and called. Escape pseudo-events are processed exactly like Traps. However, for 'real' events, the search for a handler terminates as soon as a handler is found, rather than when a willing handler is found (this is done to limit the time taken to respond to an event). If no handler is willing to claim the event, it is handed to the event handler which was in force when the program started. (The call happens in CallBack, and if it is the result of an Escape, the Escape has already been acknowledged.)

In the case of escape events, all side effects (such as termination of a keyboard read) have already happened by the time a language escape handler is called.

FastEventProc

The treatment of events by EventProc isn't too good if what the user level handler wants to do is to buffer events (eg conceivably for the key up/down event), because there may be many events to one event handler call. The FastEventProc allows a call at the time of the event, but this is constrained to obey the rules for writing interrupt code (called in IRQ mode; must be quick; may not call SWIs or enable interrupts; must not check for stack overflow). The rules for which handler gets called in this case are rather different from those of (uncaught) trap and (unhandled) event handlers, partly because the user PC is not available, and partly because it is not necessarily quick enough. So the FastEventProc of each language in the image is called in turn (in some random order).

UnwindProc

UnwindProc unwinds one stack frame (see description of _kernel_unwindproc for details). If no procedure is provided, the default unwind procedure assumes that the ARM Procedure Call Standard has been used; languages should provide a procedure if some internal calls do not follow the standard.

NameProc

NameProc returns a pointer to the string naming the procedure in whose body the argument PC lies, if a name can be found; otherwise, 0.

How the run-time stack is managed and extended

The run-time stack consists of a doubly-linked list of stack chunks. The initial stack chunk is created when the run-time kernel is initialised. Currently, the size of the initial chunk is 4Kb. Subsequent requests to extend the stack are rounded up to at least this size, so the granularity of chunking of the stack is fairly coarse. However, clients may not rely on this.

Each chunk implements a portion of a descending stack. Stack frames are singly linked via their frame pointer fields within (and between) chunks. See Appendix C: ARM procedure call standard for more details.

In general, stack chunks are allocated by the storage manager of the master language (the language in which the root procedure - that containing the language entry point - is written). Whatever procedures were last registered with _kernel_register_allocs() will be used (each chunk 'remembers' the identity of the procedure to be called to free it). Thus, in a C program, stack chunks are allocated and freed using malloc() and free().

In effect, the stack is allocated on the heap, which grows monotonically in increasing address order.

The use of stack chunks allows multiple threading and supports languages which have co-routine constructs (such as Modula-2). These constructs can be added to C fairly easily (provided you can manufacture a stack chunk and modify the fp, sp and sl fields of a jmp_buf, you can use setjmp and longjmp to do this).

Stack chunk format

A stack chunk is described by a _kernel_stack_chunk data structure located at its low-address end. It has the following format:

typedef struct stack_chunk {
    unsigned long sc_mark;       /* == 0xf60690ff */
    struct stack_chunk *sc_next, *sc_prev;
    unsigned long sc_size;
    int (*sc_deallocate)();
} _kernel_stack_chunk;

sc_mark is a magic number; sc_next and sc_prev are forward and backward pointers respectively, in the doubly linked list of chunks; sc_size is the size of the chunk in bytes and includes the size of the stack chunk data structure; sc_deallocate is a pointer to the procedure to call to free this stack chunk - often free() from the C library. Note that the chunk lists are terminated by NULL pointers - the lists are not circular.

The seven words above the stack chunk structure are reserved to Acorn. The stack-limit register points 512 bytes above this (ie 560 bytes above the base of the stack chunk).

Stack extension

Support for stack extension is provided in two forms:

  • fp, arguments and sp get moved to the new chunk (Pascal/Modula-2-style)
  • fp is left pointing at arguments in the old chunk, and sp is moved to the new chunk (C-style).

Each form has two variants depending on whether more than 4 arguments are passed (Pascal/Modula-2-style) or on whether the required new frame is bigger than 256 bytes or not (C-style). See the chapter entitled Appendix C: ARM procedure call standard for more details.

_kernel_stkovf_copyargs

Pascal/Modula-2-style stack extension, with some arguments on the stack (ie stack overflow in a procedure with more than four arguments). On entry, ip must contain the number of argument words on the stack.

_kernel_stkovf_copy0args

Pascal/Modula-2-style stack extension, without arguments on the stack (ie stack overflow in a procedure with four arguments or fewer).

_kernel_stkovf_split_frame

C-style stack extension, where the procedure detecting the overflow needs more than 256 bytes of stack frame. On entry, ip must contain the value of sp - the required frame size (ie the desired new sp which would be below the current stack limit).

_kernel_stkovf_split_0frame

C-style stack extension, where the procedure detecting the overflow needs 256 or fewer bytes of stack frame.

Stack chunks are deallocated on returning from procedures which caused stack extension, but with one chunk of latency. That is, one extra stack chunk is kept in hand beyond the current one, to reduce the expense of repeated call and return when the stack is near the end of a chunk; others are freed on return from the procedure which caused the extension.

Calling other programs from C

The C library procedure system() provides the means whereby a program can pass a command to the host system's command line interpreter. The semantics of this are undefined by the draft ANSI standard.

RISC OS distinguishes two kinds of commands, which we term built-in commands and applications. These have different effects. The former always return to their callers, and usually make no use of application workspace; the latter return to the previously set-up 'exit handler', and may use the currently-available application workspace. Because of these differences, system() exhibits three kinds of behaviour. This is explained below.

Applications in RISC OS are loaded at a fixed address specified by the application image. Normally, this is the base of application workspace, &8000. While executing, applications are free to use store between the base and end of application workspace. The end is the value returned by SWI OS_GetEnv. They terminate with a call of SWI OS_Exit, which transfers control to the current exit handler.

When a C program makes the call system("command") several things are done:

  • The calling program and its data are copied to the top end of application workspace and all its handlers are removed.
  • The current end of application workspace is set to just below the copied program and an exit handler is installed in case "command" is another application.
  • "command" is invoked using SWI OS_CLI.

When "command" returns, either directly (if it is a built-in command) or via the exit handler (if it is an application), the caller is copied back to its original location, its handlers are re-installed and it continues, oblivious of the interruption.

The value returned by system() indicates

  • whether the command or application was successfully invoked
  • if the command is an application which obeys certain conventions, whether or not it ran successfully.

The value returned by system (with a non-NULL command string) is as follows:

< 0 - couldn't invoke the command or application (eg command not found);

>=0 - invoked OK and set Sys$ReturnCode to the returned value.

By convention, applications set the environmental variable Sys$ReturnCode to 0 to indicate success and to something non-0 to indicate some degree of failure. Applications written in C do this for you, using the value passed as an argument to the exit() function or returned from the main() function.

If it is necessary to replace the current application by another, use:

system("CHAIN:command");

If the first characters of the string passed to system() are "CHAIN:" or "chain:", the caller is not copied to the top end of application workspace, no exit handler is installed, and there can be no return (return from a built-in command is caught by the C library and turned into a SWI OS_Exit).

Typically, CHAIN: is used to give more memory to the called application when no return from it is required. The C compiler invokes the linker this way if a link step is required. On the other hand, the Acorn Make Utility (AMU) calls each command to be executed. Such commands include the C compiler (as both use the shared C library, the additional use of memory is minimised). Of course, a called application can call other applications using system(). A callee can even CHAIN: to another application and still, eventually, return to the caller. For example, AMU might execute:

system("cc hello.c");

to call the C compiler. In turn, cc executes:

system("CHAIN:link -o hello o.hello $.CLib.o.Stubs");

to transfer control to the linker, giving link all the memory cc had.

However, when Link terminates (calls exit(), returns from main() or aborts) it returns to AMU, which continues (providing Sys$ReturnCode is good).

Storage management (malloc, calloc, free)

The aim of the storage manager is to manage the heap in as 'efficient' a manner as possible. However, 'efficient' does not mean the same to all programs and since most programs differ in their storage requirements, certain compromises have to be made.

You should always try to keep the peak amount of heap used to a minimum so that, for example, a C program may invoke another C program leaving it the maximum amount of memory. This implementation has been tuned to hold the overhead due to fragmentation to less than 50%, with a fast turnover of small blocks.

The heap can be used in many different ways. For example it may be used to hold data with a long life (persistent data structures) or as temporary work space; it may be used to hold many small blocks of data or a few large ones or even a combination of all of these allocated in a disorderly manner. The storage manager attempts to address all of these problems but like any storage manager, it cannot succeed with all storage allocation/deallocation patterns. If your program is unexpectedly running out of storage, see the chapter entitled Guidelines on using memory efficiently. This gives you information on the storage manager's strategy for managing the heap, and may help you to remedy the problem.

Note the following:

  • The word heap refers to the section of memory currently under the control of the storage manager.
  • All block sizes are in bytes and are rounded up to a multiple of four bytes.
  • All blocks returned to the user are word-aligned.
  • All blocks have an overhead of eight bytes (two words). One word is used to hold the block's length and status, the other contains a guard constant which is used to detect heap corruptions. The guard word may not be present in future releases of the ANSI C library.

Handling host errors

Calls to RISC OS can be made via one of the kernel functions, (such as _kernel_osfind(64, "...")). If the call causes an operating system error, the function will return the value -2. To find out what the error was, a call to _kernel_last_oserror should be made. This will return a pointer to a _kernel_oserror block containing the error number and any associated error string. If there has been no error since _kernel_last_oserror was last called, the function returns the NULL pointer. Some functions in the C library call _kernel functions, so if an C library function (such as fopen("...", "r")) fails, try calling _kernel_last_oserror to find out what the error was.

SWI Calls


SharedCLibrary_LibInitAPCS_A
(SWI &80680)

This SWI interfaces an application which uses the old 'A' variant (SP=R12) of the Procedure Call Standard to the shared C library. Its use is deprecated and it should not be called in any programs. Use SharedCLibrary_LibInitAPCS_R instead.


SharedCLibrary_LibInitAPCS_R
(SWI &80681)

Interfaces an application with the shared C library

On entry

R0 = pointer to list of stub descriptions each having the following format:

+00: library chunk id (1 or 2)
+04: entry vector base
+08: entry vector limit
+12: static data base
+16: static data limit
The list is terminated by an entry with a library chunk id of -1

R1 = pointer to workspace start
R2 = pointer to workspace limit
R3 = -1
R4 = 0
R5 = -1
R6 =

Bits 0 - 15 = 0
Bits 16 - 31 = Root stack size in Kilobytes

On exit

Entry vectors specified by the stubs descriptions are patched to contain branches to routines in the library.

If R5 > R4 on entry the users statics are copied to the bottom of the workspace specified in R1 and the Client static data offset (at byte offset +24 from the stack base) is initialised.

For each library chunk the library statics are copied either into the workspace specified in R1 if R5 > R4 on entry or to the static data area specified in the chunks stub description if R5 <= R4.

The Library static data offset (at byte offset +20 from the stack base) is initialised.

Space for the root stack chunk is claimed from the workspace specified in R1.

R0 = value of R2 on entry
R1 = stack base
R2 = limit of space claimed from workspace passed in R1. This value should be used as the SP for the root stack chunk
R6 = library version number (currently = 5)

Interrupts

Interrupts are enabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This SWI allows you to interface an application with the shared C library without using the shared C library stubs.

LibInitAPCS_R is used by applications which use APCS_R (see Appendix C: ARM procedure call standard for more details).

Two library chunks are currently defined.

Chunk Id 1 - The Kernel module

The Kernel module defines 48 entries, these are described in the chapter entitled Library kernel functions. You must reserve 48 words in your branch vector table. The words at offsets +04 and +08 of the Kernel stub description must be initialised to the start and limit (end + 1) of your vector table.

The Kernel module requires &31C bytes of static data space. You must reserve this amount of storage. The words at offsets +12 and +16 must be initialised to the start and limit (end + 1) of this storage.

Chunk Id 2 - The C library module

If you wish to use the C library module you must include the Kernel stub description before the C library stub description in the list of stubs descriptions.

The C library module defines 183 entries, these are described in the chapter entitled C library functions. You must reserve 183 words in your branch vector table.

The words at offsets +04 and +08 of the Kernel stub description must be initialised to the start and limit (end + 1) of your vector table.

The C library module requires &B48 bytes of static data space. You must reserve this amount of storage. The words at offsets +12 and +16 must be initialised to the start and limit (end + 1) of this storage. This storage must be contiguous with that for the Kernel module.

Calling library functions

Before calling any library functions you must call the kernel function _kernel_init (entry no. 0). For details on how to call these functions refer to their entries in the chapter entitled Library kernel functions.

SP, SL and FP must be set up before calling any library function. _kernel_init initialises these for the root stack chunk passed to it.

If you wish to call C library functions you must pass a suitable kernel language description block to _kernel_init. For details on the format of a kernel language description block refer to the section entitled Interfacing a language run-time system to the Acorn library kernel.

To call C library functions the fields of the kernel language description block must be as follows:

size The size of this structure in bytes (24 - 52 depending on the number of entries in this block).
codestart These two words should be set to the start and limit of an area
codelimit which is to be treated as C code with respect to trap and event handling. Both these values may be set to 0 in which case no traps or events will be passed to the trap or event handler described in this language description block.
name This must contain a pointer to the 0 terminated string "C".
InitProc Pointer to your initialisation procedure. Your initialisation procedure must call _clib_initialise (entry no. 20). For details on how to call _clib_initialise refer to its entry in the C library functions. It should then load R0 with the address at which execution is to continue at the end of initialisation.
FinaliseProc Pointer to your finalisation procedure. This may contain 0.

The remainder of the entries are optional and may omitted. You must set the size field correctly if omitting entries. If all optional entries are omitted the size field should be set to 24.

Related SWIs

SharedCLibrary_LibInitAPCS_A (SWI &80680)

Related vectors

None


SharedCLibrary_LibInitModule
(SWI &80682)

Interfaces a module with the shared C library

On entry

R0 = pointer to list of stub descriptions each having the following format:

+00: library chunk id (1 or 2)
+04: entry vector base
+08: entry vector limit
+12: static data base
+16: static data limit
The list is terminated by an entry with a library chunk id of -1

R1 = pointer to workspace start
R2 = pointer to workspace limit
R3 = base of area to be zero-initialised
R4 = pointer to start of static data
R5 = pointer to limit of static data
R6 =

Bits 0 - 15 = 0
Bits 16 - 31 = Root stack size in Kilobytes

On exit

Entry vectors specified by the stubs descriptions are patched to contain branches to routines in the library.

If R5 > R4 on entry the users statics are copied to the bottom of the workspace specified in R1 and the Client static data offset (at byte offset +24 from the stack base) is initialised.

For each library chunk the library statics are copied either into the workspace specified in R1 if R5 > R4 on entry or to the static data area specified in the chunks stub description if R5 <= R4.

The Library static data offset (at byte offset +20 from the stack base) is initialised.

Space for the root stack chunk is claimed from the SVC stack.

R0 = value of R2 on entry
R1 = stack base
R2 = limit of space claimed from workspace passed in R1
R6 = library version number (currently = 5)

Note: You must save the words at offsets +20 and +24 from the returned stack base. You must do this before exiting your module initialisation code. These words contain the shared libraries static data offset and the client static data offset (the offset you must use when accessing your static data). These must be restored in the static data offset locations at offsets +00 and +04 from the base of the SVC stack when you are re-entering the module in SVC mode (e.g. in a SWI handler). When restoring the static data offsets you must save the previous static data offsets around the module entry.

Interrupts

Interrupts are enabled
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant

Use

This SWI allows you to interface a module with the shared C library without using the shared C library stubs.

SharedCLibrary_LibInitModule is used by modules, which must use APCS_R, and must be called in the module Initialisation code.

Two library chunks are currently defined.

Chunk Id 1 - The Kernel module

The Kernel module defines 48 entries, these are described in the Library kernel functions. You must reserve 48 words in your branch vector table. The words at offsets +04 and +08 of the Kernel stub description must be initialised to the start and limit (end + 1) of your vector table.

The Kernel module requires &31C bytes of static data space. You must reserve this amount of storage. The words at offsets +12 and +16 must be initialised to the start and limit (end + 1) of this storage.

Chunk Id 2 - The C library module

If you wish to use the C library module you must include the Kernel stub description before the C library stub description in the list of stubs descriptions.

The C library module defines 183 entries, these are described in the C library functions. You must reserve 183 words in your branch vector table.

The words at offsets +04 and +08 of the Kernel stub description must be initialised to the start and limit (end + 1) of your vector table.

The C library module requires &B48 bytes of static data space. You must reserve this amount of storage. The words at offsets +12 and +16 must be initialised to the start and limit (end + 1) of this storage. This storage must be contiguous with that for the Kernel module.

Calling library functions

Before calling any library functions you must call the kernel function _kernel_moduleinit (entry no. 38). For details on how to call these functions refer to their entries in the Library kernel functions.

SP, SL and FP must be set up before calling any library function. _kernel_init initialises these for the root stack chunk passed to it.

If you wish to call C library functions you must pass a suitable kernel language description block to _kernel_init. For details on the format of a kernel language description block refer to the Interfacing a language run-time system to the Acorn library kernel.

To call C library functions the fields of the kernel language description block must be as follows:

size The size of this structure in bytes (24 - 52 depending on the number of entries in this block).
codestart These two words should be set to the start and limit of an area
codelimit which is to be treated as C code with respect to trap and event handling. Both these values may be set to 0 in which case no traps or events will be passed to the trap or event handler described in this language description block.
name This must contain a pointer to the 0 terminated string "C".
InitProc Pointer to your initialisation procedure. Your initialisation procedure must call _clib_initialise (entry no. 20). For details on how to call _clib_initialise refer to its entry in the C library functions. It should then load R0 with the address at which execution is to continue at the end of initialisation.
FinaliseProc Pointer to your finalisation procedure. This may contain 0.

The remainder of the entries are optional and may omitted. You must set the size field correctly if omitting entries. If all optional entries are omitted the size field should be set to 24.

Accessing shared library data

The following items of data are exported from the shared library data and may be used in your programs.

Name Offset Notes
errno &0000 The variable errno is set whenever certain error conditions arise in the C library. These error conditions are described in the section 'errno' on errno.
stdin &0004 These three variables contain the standard C library FILE
stdout &002C structures stdin, stdout and stderr. The address of these variables
stderr &0054 may be passed to any C library function which accept a FILE * argument. For an example of their use see the call to 'fputs' in the module example.
ctype &0290 This is a 256 byte array containing an 8 bit mask for each character in the range 0 to 255. Each bit defines some aspect of the character as follows:
bit 0 character is a whitespace character
bit 1 character is a punctuation character
bit 2 character is a blank (' ')
bit 3 character is a lowercase letter
bit 4 character is an uppercase letter
bit 5 character is a decimal digit
bit 6 character is a control character
bit 7 character is one of the characters A, B, C, D, E, F ora, b, c, d, e, f
This table is initialised for the C locale; it may be changed by calls to the 'setlocale' function.

Note: The offsets given above are offsets into the C library statics. These must be preceded immediately by the kernel statics, which are 800 (&31C) bytes long. To convert offsets in the C library statics to offsets in the library statics add 800 (&31C).

If you are accessing static data within a program (i.e. code which uses SharedCLibrary_LibInitAPCS_R) you can access the static data directly in your own static data area definition. If, however, however you are accessing static data from within a module (using SharedCLibrary_LibInitModule) you must use the add the client static data relocation to the address in your own static data area definition to obtain the true address of the static data. If you wish your module to be multiply instantiable or rommable you must add this relocation when accessing your own static data, not just when accessing the libraries static data.

The client static data relocation is stored at offset -536 (-&218) from the SL register (R10).

For an example of how to use the static data relocation see the call to 'fputs' in the module example.

Related SWIs

None

Related vectors

None

Example programs

Calling the shared C library

; This example demonstates how to call the shared C library.
; It is written for the ObjAsm assembler supplied with the Software
; Developers Toolkit (SDT) and the Desktop Development Environment (DDE).
;
r0             RN      0
r1             RN      1
r2             RN      2
r3             RN      3
r4             RN      4
r5             RN      5
r6             RN      6
sp             RN      13
lr             RN      14
pc             RN      15
|_kernel_init|         EQU     0 * 4          ; Offsets in kernel vector table
|_clib_initialise|     EQU     20 * 4         ; Offsets in C vector table
fopen                  EQU     87 * 4
fprintf                EQU     92 * 4
fclose                 EQU     85 * 4
OS_GenerateError       EQU     &2b
OS_Exit                EQU     &11
SharedCLibrary_LibInitAPCS_R EQU &80681
               IMPORT  |Image$$RO$$Base|      ; Linker defined symbol giving
                                              ; start of image.
               AREA    printf, CODE, READONLY
               ENTRY
               ADR     r0, stubs
               ADRL    r1, workspace
               ADD     r2, r1, #32 * 1024     ; 32K workspace. A real program
               MOV     r3, #-1                ; would use OS_ChangeEnvironment
               MOV     r4, #0                 ; to find the memorylimit.
               MOV     r5, #-1
               MOV     r6, #&00080000
               SWI     SharedCLibrary_LibInitAPCS_R
               MOV     r4, r0
               ADR     r0, kernel_init_block
               MOV     r3, #0
               B kernel_vectors + |_kernel_init|   ; Continues at c_init below
stubs
               DCD     1
               DCD     kernel_vectors
               DCD     kernel_vectors_end
               DCD     kernel_statics
               DCD     kernel_statics_end
               DCD     2
               DCD     clib_vectors
               DCD     clib_vectors_end
               DCD     clib_statics
               DCD     clib_statics_end
               DCD     -1
kernel_init_block
               DCD     |Image$$RO$$Base|
               DCD     rts_block
               DCD     rts_block_end
rts_block
               DCD     rts_block_end - rts_block
               DCD     0
               DCD     0
               DCD     c_str
               DCD     c_init
               DCD     0
rts_block_end
c_str          DCB     "C", 0               ; Must be "C" for CLib to finalise
               ALIGN                        ; properly.
c_init         MOV     r0, sp
               MOV     r1, #0
               MOV     r2, #0
               STMDB   sp!, {lr}
               BL      clib_vectors + |_clib_initialise|
               ADR     r0, c_run            ; Continue at c_run below
               LDMIA   sp!, {pc}^
c_run          ADR     r0, outfile
               ADR     r1, access
               BL      clib_vectors + fopen
               CMP     r0, #0
               ADREQ   r0, Err_Open         ; Will actually say
               SWIEQ   OS_GenerateError     ; Uncaught trap: Error opening ...
               MOV     r4, r0
               ADR     r1, format
               BL      clib_vectors + fprintf
               MOV     r0, r4
               BL      clib_vectors + fclose
               CMP     r0, #0
               ADRNE   r0, Err_Close
               SWINE   OS_GenerateError     ; Uncaught trap: Error writing ...
               SWI     OS_Exit
outfile        DCB     "OutFile", 0
access         DCB     "w", 0
format         DCB     "Sample string printed from asm using fprintf!", 10, 0
               ALIGN
Err_Open       DCD     &1000
               DCB     "Error opening OutFile", 0
               ALIGN
Err_Close      DCD     &1001
               DCB     "Error writing OutFile", 0
               ALIGN
kernel_vectors %       48 * 4
kernel_vectors_end
clib_vectors   %       183 * 4
clib_vectors_end
kernel_statics %       &31c
kernel_statics_end
clib_statics   %       &b48
clib_statics_end
workspace                                 ; Start of workspace at end of app.
               END

Calling the shared C library from a module

; This example demonstates how to call the shared C library from a module. 
; It is written for the ObjAsm assembler supplied with the Software 
; Developers Toolkit (SDT) and the Desktop Development Environment (DDE) 
r0      RN      0 
r1      RN      1 
r2      RN      2 
r3      RN      3 
r4      RN      4 
r5      RN      5 
r6      RN      6 
r7      RN      7 
r8      RN      8 
r9      RN      9 
r10     RN      10 
r11     RN      11 
r12     RN      12
sl      RN      10 
fp      RN      11 
sp      RN      13 
lr      RN      14 
pc      RN      15
swibase         EQU     &88000
V_Bit           EQU     1:SHL:28
Module_Claim    EQU     6
Service_Error   EQU     &06
Service_Help    EQU     &09
XOS_Module      EQU     &2001e
XSharedCLibrary_LibInitModule   EQU     &80682
OS_WriteS       EQU     1
OS_Exit         EQU     &11
                ^       0       ; Offsets in module workspace 
size            #       4       ; Size of this block 
libreloc        #       4       ; Offset for accessing librarys statics 
clientreloc     #       4       ; Offset for accessing our statics 
ws_size         #       0
Lib_Offset       EQU     20     ; Offset of library relocation offset 
                                ; from base of stack. 
SL_Lib_Offset    EQU     540    ; Negative offset of library relocation 
                                ; offset from SL register 
Client_Offset    EQU     24     ; Offset of client relocation offset 
SL_Client_Offset EQU     536    ; Negative offset of client relocation 
                                ; offset from SL register
|_kernel_command_string| EQU    7 * 4 
|_kernel_moduleinit|     EQU    38 * 4 
|_kernel_entermodule|    EQU    42 * 4
|_main|                  EQU    18 * 4 
|_clib_initialise|       EQU    20 * 4 
atexit                   EQU    71 * 4 
printf                   EQU    91 * 4 
fputs                    EQU    104 * 4 
putchar                  EQU    111 * 4 
|_clib_finalisemodule|   EQU    179 * 4
        IMPORT  |__RelocCode|     ; Linker supplied relocation routine 
        IMPORT  |Image$$RO$$Base| ; Linker defined base / limit symbols 
        IMPORT  |Image$$RW$$Base| 
        IMPORT  |Image$$RW$$Limit| 
        IMPORT  |Image$$ZI$$Base|
        AREA    module_code, CODE, READONLY
module_base 
        DCD     start - module_base 
        DCD     init - module_base 
        DCD     terminate - module_base 
        DCD     service - module_base 
        DCD     title - module_base 
        DCD     help - module_base 
        DCD     cmdtbl - module_base 
        DCD     swibase 
        DCD     swicode - module_base 
        DCD     switbl - module_base
title   DCB     "SLClient", 0 
help    DCB     "SLClient", 9, "1.00 (11-Dec-91)", 0
        ALIGN
base    DCD     |Image$$RW$$Base| 
limit   DCD     |Image$$RW$$Limit| 
zi_base DCD     |Image$$ZI$$Base|
cmdtbl  DCB     "SLClient_Command", 0 
        ALIGN 
        DCD     cmdcode - module_base 
        DCB     0 
        DCB     &ff 
        DCB     255 
        DCB     0 
        DCD     0                 ; No syntax message 
        DCD     0                 ; No help message
switbl  DCB     "SLClient", 0 
        DCB     "SWI", 0          ; SLClient_SWI 
        DCB     0 
        ALIGN
init    STMDB   sp!, {r7-r11, lr} ; Save only regs that need saving 
        MOV     sl, sp, LSR #20   ; Get base of SVC stack in sl. 
        MOV     sl, sl, LSL #20 
        LDMIA   sl, {r4, r5}      ; Save old relocation modifiers 
        STMDB   sp!, {r4, r5}     ; from base of SVC stack 
        BL      |__RelocCode|     ; Relocate module 
        MOV     r0, #Module_Claim 
        LDR     r4, base 
        LDR     r5, limit 
        SUB     r3, r5, r4 
        ADD     r3, r3, #ws_size 
        SWI     XOS_Module 
        MOV     r9, r12 
        STR     r2, [r12]         ; Set private word 
        MOV     r12, r2 
        STR     r3, [r12]         ; First word of block is size of block 
        ADR     r0, stubs 
        ADD     r1, r12, #ws_size 
        ADD     r2, r12, r3 
        LDR     r3, zi_base 
        MOV     r6, #4 :SHL: 16 
        SWI     XSharedCLibrary_LibInitModule 
        ADD     r8, r1, #Lib_Offset 
        LDMIA   r8, {r7, r8}      ; Get Lib and Client reloc. offset 
        STMIB   r12, {r7, r8}     ; Save in work area 
        ADR     r0, kernel_init_block 
        BL      call_moduleinit 
        STMDB   sp!, {r9}         ; Save workspace pointer 
        BL      clib_vectors + |_clib_initialise| 
        LDMIA   sp!, {r2} 
        ADD     r0, sp, #(10-7+2)*4 ; Point to R10 on stack 
        LDMIA   r0, {r0, r1} 
        BL      user_init 
        MOV     sl, sp, LSR #20   ; Get base of SVC stack in sl. 
        MOV     sl, sl, LSL #20 
        LDMIA   sp!, {r4, r5} 
        STMIA   sl, {r4, r5} 
        LDMIA   sp!, {r7-r11, lr} 
        CMPS    r0, #0 
        BICEQS  pc, lr, #V_Bit 
        ORRS    pc, lr, #V_Bit
; _kernel_moduleinit expects the return address to be in the first word on the 
; stack rather than in LR. This function sets up the return address correctly. 
call_moduleinit 
        STMDB   sp!, {lr} 
        B       kernel_vectors + |_kernel_moduleinit|
terminate 
        STMDB   sp!, {r7-r11, lr} ; Save only regs that need saving 
        MOV     sl, sp, LSR #20   ; Get base of SVC stack in sl. 
        MOV     sl, sl, LSL #20 
        LDMIA   sl, {r4, r5}      ; Save old relocation modifiers 
        MOV     r0, r12           ; Set up private word pointer for 
                                  ; _clib_finalisemodule 
        LDR     r12, [r12]        ; Pointer to static data 
        LDMIB   r12, {r11, r12} 
        STMIA   sl, {r11, r12}    ; Set up relocation modifiers 
        ADD     sl, sl, #SL_Lib_Offset 
        MOV     fp, #0            ; FP = 0 => end of linked stack frames 
                                  ; so backtrace stops here 
        BL      clib_vectors + |_clib_finalisemodule| 
        MOV     sl, sp, LSR #20 
        MOV     sl, sl, LSL #20 
        STMIA   sl, {r4, r5}      ; Restore old relocation modifiers 
        LDMIA   sp!, {r7-r11, pc}^
start   ADR     r0, kernel_init_block 
        MOV     r8, r12 
        MOV     r12, #-1 
        MOV     r6, #4 * 1024 
        B       kernel_vectors + |_kernel_entermodule|
c_init  STMDB   sp!, {lr} 
        BL      clib_vectors + |_clib_initialise| 
        ADR     r0, c_run         ; Continue at c_run below 
        LDMIA   sp!, {pc}
c_run   BL      kernel_vectors + |_kernel_command_string| 
        ADR     r1, user_run      ; Continue at user_run below 
        B       clib_vectors + |_main|
cmdcode STMDB   sp!, {r10, r11, lr} 
        MOV     sl, sp, LSR #20   ; Get base of SVC stack 
        MOV     sl, sl, ASL #20 
        LDMIA   sl, {r4, r5}      ; Save old relocation modifiers in R4, R5 
        LDR     r12, [r12] 
        LDMIB   r12, {r11, r12}   ; Set up our relocation modifiers 
        STMIA   sl, {r11, r12} 
        ADD     sl, sl, #SL_Lib_Offset ; Set up stack limit for SVC stack 
        MOV     fp, #0            ; Stop backtrace here 
        BL      user_cmd          ; Call APCS user_cmd routine 
        MOV     sl, sp, LSR #20 
        MOV     sl, sl, ASL #20   ; Get base of SVC stack again 
        STMIA   sl, {r4, r5}      ; Restore old relocation modifiers 
        LDMIA   sp!, {r10, r11, lr} 
        CMP     r0, #0            ; Set V bit on R0 and return 
        BICEQS  pc, lr, #V_Bit 
        ORRS    pc, lr, #V_Bit
swicode STMDB   sp!, {r0-r9, lr}  ; Set up regset on SVC stack 
        MOV     sl, sp, LSR #20   ; Get base of SVC stack 
        MOV     sl, sl, ASL #20 
        LDMIA   sl, {r8, r9}      ; Save old relocation modifiers in R8, R9 
        MOV     r0, r11 
        MOV     r1, sp            ; Pointer to regs on stack 
        MOV     r2, r12 
        LDR     r12, [r12] 
        LDMIB   r12, {r11, r12}   ; Set up relocation modifiers 
        STMIA   sl, {r11, r12} 
        ADD     sl, sl, #SL_Lib_Offset ; Set up stack limit for SVC stack 
        MOV     fp, #0            ; Stop backtrace here 
        BL      user_swi          ; Call APCS user_swi routine 
        MOV     sl, sp, LSR #20   ; Get base of SVC stack again 
        MOV     sl, sl, ASL #20 
        STMIA   sl, {r8, r9}      ; Restore old relocation modifiers 
        CMP     r0, #0            ; Set R0 on stack to error pointer 
        STRNE   r0, [sp]          ; if error on return. 
        LDMIA   sp!, {r0-r9, lr} 
        BICEQS  pc, lr, #V_Bit    ; Set V bit on R0 and return. 
        ORRS    pc, lr, #V_Bit
service TEQ     r1, #Service_Help ; Check service nos. first for speed 
        TEQNE   r1, #Service_Error 
        MOVNES  pc, lr 
        STMDB   sp!, {r0-r9, sl, fp, lr} ; Set up regset on SVC/IRQ stack 
        MOV     r0, r1 
        MOV     r1, sp            ; Pointer to regs on stack 
        MOV     r6, pc            ; Save old mode 
        BIC     lr, r6, #3        ; To SVC mode from SVC/IRQ mode 
        TEQP    lr, #3 
        MOV     r0, r0            ; NOP after mode change 
        MOV     fp, #0            ; Stop backtrace 
        MOV     r7, lr            ; Save SVC lr if entered in IRQ mode 
        MOV     sl, sp, LSR #20   ; Get base of SVC stack 
        MOV     sl, sl, ASL #20 
        LDMIA   sl, {r8, r9}      ; Save old relocation modifiers in R8, R9 
        MOV     r2, r12 
        LDR     r12, [r12] 
        LDMIB   r12, {r11, r12}   ; Set up relocation modifiers 
        STMIA   sl, {r11, r12} 
        ADD     sl, sl, #SL_Lib_Offset ; Set up stack limit for SVC stack 
        BL      user_service      ; Call APCS user_service routine 
        MOV     lr, r7            ; Restore SVC lr 
        TEQP    r6, #0            ; Back to entry mode 
        MOV     r0, r0            ; NOP after mode change 
        MOV     sl, sp, LSR #20   ; Get base of SVC stack 
        MOV     sl, sl, ASL #20 
        STMIA   sl, {r8, r9}      ; Restore old relocation modifiers 
        LDMIA   sp!, {r0-r9, sl, fp, pc}^
; _kernel_oserror *user_init(char *cmd_tail, int base, void *pw); 
user_init 
        STMDB   sp!, {r4, r9, lr} 
        LDR     r9, [sl, #-SL_Client_Offset] ; Get Client relocation 
        MOV     r4, r0 
        ADR     r0, format 
        ADR     r1, init_str 
        BL      clib_vectors + printf 
        ADR     r0, cmd_format 
        LDR     r1, stdout        ; Address stdout in library statics 
        ADD     r1, r1, r9        ; Add client relocation 
        BL      clib_vectors + fputs 
10      LDRB    r0, [r4], #1 
        CMP     r0, #32 
        MOVCC   r0, #10 
        BL      clib_vectors + putchar 
        BCS     %B10 
        ADR     r0, user_exit     ; Set up atexit handler 
        BL      clib_vectors + atexit 
        MOV     r0, #0 
        LDMIA   sp!, {r4, r9, pc}^
stdout  DCD     clib_statics + &2c
; void user_exit(void); 
user_exit 
        STMDB   sp!, {lr} 
        ADR     r0, format 
        ADR     r1, exit_str 
        BL      clib_vectors + printf 
        LDMIA   sp!, {pc}^
; int user_run(int argc, char **argv); 
user_run 
        STMDB   sp!, {r4, r5, r6, lr} 
        MOV     r4, r0 
        MOV     r5, r1 
        ADR     r0, format 
        ADR     r1, run_str 
        BL      clib_vectors + printf 
        ADR     r0, argc_format 
        MOV     r1, r4 
        BL      clib_vectors + printf 
        MOV     r6, #0 
10      CMP     r6, r4 
        ADRCC   r0, argv_format 
        MOVCC   r1, r6 
        LDRCC   r2, [r5, r6, LSL #2] 
        BLCC    clib_vectors + printf 
        ADDCC   r6, r6, #1 
        BCC     %B10 
        MOV     r0, #0 
        LDMIA   sp!, {r4, r5, r6, pc}^
; _kernel_oserror *user_cmd(char *args, int argc); 
user_cmd 
        STMDB   sp!, {r4, r5, lr} 
        MOV     r4, r0 
        MOV     r5, r1 
        ADR     r0, format 
        ADR     r1, cmd_str 
        BL      clib_vectors + printf 
        ADR     r0, args_format 
        MOV     r1, r5 
        BL      clib_vectors + printf 
10      LDRB    r0, [r4], #1 
        CMP     r0, #32 
        MOVCC   r0, #10 
        BL      clib_vectors + putchar 
        BCS     %B10 
        MOV     r0, #0 
        LDMIA   sp!, {r4, r5, pc}^
; _kernel_oserror *user_swi(int swi_no, _kernel_swi_regs *r, void *pw); 
user_swi 
        STMDB   sp!, {lr} 
        ADR     r0, format 
        ADR     r1, swi_str 
        BL      clib_vectors + printf 
        MOV     r0, #0 
        LDMIA   sp!, {pc}^
; void user_service(int service_no, _kernel_swi_regs *r, void *pw); 
user_service 
        STMDB   sp!, {lr} 
        CMP     r0, #Service_Help 
        ADR     r0, format 
        ADREQ   r1, help_str 
        ADRNE   r1, error_str 
        BL      clib_vectors + printf 
        LDMIA   sp!, {pc}^
format          DCB     "In %s code", 10, 0 
                ALIGN 
argc_format     DCB     "argc = %d", 10, 0 
                ALIGN 
argv_format     DCB     "argv[%d] = %s", 10, 0 
                ALIGN 
args_format     DCB     "argc = %d, args = ", 0 
                ALIGN 
cmd_format      DCB     "Command tail = ", 0 
                ALIGN 
init_str        DCB     "initialisation", 0 
                ALIGN 
exit_str        DCB     "exit", 0 
                ALIGN 
run_str         DCB     "run", 0 
                ALIGN 
cmd_str         DCB     "command", 0 
                ALIGN 
swi_str         DCB     "swi", 0 
                ALIGN 
help_str        DCB     "help", 0 
                ALIGN 
error_str       DCB     "error", 0 
                ALIGN
stubs 
        DCD     1 
        DCD     kernel_vectors 
        DCD     kernel_vectors_end 
        DCD     kernel_statics 
        DCD     kernel_statics_end
        DCD     2 
        DCD     clib_vectors 
        DCD     clib_vectors_end 
        DCD     clib_statics 
        DCD     clib_statics_end
        DCD     -1
kernel_init_block 
        DCD     |Image$$RO$$Base| 
        DCD     rts_block 
        DCD     rts_block_end
rts_block 
        DCD     rts_block_end - rts_block 
        DCD     0 
        DCD     0 
        DCD     c_str 
        DCD     c_init 
        DCD     0 
rts_block_end
c_str   DCB     "C", 0 
        ALIGN
kernel_vectors  %       48 * 4 
kernel_vectors_end
clib_vectors    %       183 * 4 
clib_vectors_end
; Unlike the application example the kernel statics and clib statics must be in 
; a data area otherwise the data size calculation above (using Image$$RW$$Base 
; & Image$$RW$$Limit does not work. 
; 
; Ideally this would be a zero init area of appropriate size but the assembler 
; doesn't support zero init areas. 
        AREA    module_data 
 
kernel_statics  %       &31c 
kernel_statics_end 
 
clib_statics    %       &b48 
clib_statics_end 
 
        END

Library kernel functions

The library kernel functions are grouped under the following headings:

  • initialisation functions
  • stack management functions
  • program environment functions
  • general utility functions
  • memory allocation functions
  • language support functions.
Index of library kernel functions by entry number
entry no. Name
0 _kernel_init
1 _kernel_exit
2 _kernel_setreturncode
3 _kernel_exittraphandler
4 _kernel_unwind
5 _kernel_procname
6 _kernel_language
7 _kernel_command_string
8 _kernel_hostos
9 _kernel_swi
10 _kernel_osbyte
11 _kernel_osrdch
12 _kernel_oswrch
13 _kernel_osbget
14 _kernel_osbput
15 _kernel_osgbpb
16 _kernel_osword
17 _kernel_osfind
18 _kernel_osfile
19 _kernel_osargs
20 _kernel_oscli
21 _kernel_last_oserror
22 _kernel_system
23 _kernel_getenv
24 _kernel_setenv
25 _kernel_register_allocs
26 _kernel_alloc
27 _kernel_stkovf_split_0frame
28 _kernel_stkovf_split
29 _kernel_stkovf_copyargs
30 _kernel_stkovf_copy0args
31 _kernel_udiv
32 _kernel_urem
33 _kernel_udiv10
34 _kernel_sdiv
35 _kernel_srem
36 _kernel_sdiv10
37 _kernel_fpavailable
38 _kernel_moduleinit
39 _kernel_irqs_on
40 _kernel_irqs_off
41 _kernel_irqs_disabled
42 _kernel_entermodule
43 _kernel_escape_seen
44 _kernel_current_stack_chunk
45 _kernel_swi_c
46 _kernel_register_slotextend
47 _kernel_raise_error
Index of library kernel functions by function name
Name entry no.
_kernel_alloc 26
_kernel_command_string 7
_kernel_current_stack_chunk 44
_kernel_entermodule 42
_kernel_escape_seen 43
_kernel_exit 1
_kernel_exittraphandler 3
_kernel_fpavailable 37
_kernel_getenv 23
_kernel_hostos 8
_kernel_init 0
_kernel_irqs_disabled 41
_kernel_irqs_off 40
_kernel_irqs_on 39
_kernel_language 6
_kernel_last_oserror 21
_kernel_moduleinit 38
_kernel_osargs 19
_kernel_osbget 13
_kernel_osbput 14
_kernel_osbyte 10
_kernel_oscli 20
_kernel_osfile 18
_kernel_osfind 17
_kernel_osgbpb 15
_kernel_osrdch 11
_kernel_osword 16
_kernel_oswrch 12
_kernel_procname 5
_kernel_raise_error 47
_kernel_register_allocs 25
_kernel_register_slotextend 46
_kernel_sdiv 34
_kernel_sdiv10 36
_kernel_setenv 24
_kernel_setreturncode 2
_kernel_srem 35
_kernel_stkovf_copy0args 30
_kernel_stkovf_copyargs 29
_kernel_stkovf_split 28
_kernel_stkovf_split_0frame 27
_kernel_swi 9
_kernel_swi_c 45
_kernel_system 22
_kernel_udiv 31
_kernel_udiv10 33
_kernel_unwind 4
_kernel_urem 32

The following structure is common to all library kernel functions:

typedef struct
{
  int  errnum;        /* error number */
  char errmess[252];  /* error message (zero terminated) */
}
_kernel_oserror;

Initialisation functions

Entry no. 0: _kernel_init
On entry

R0 = Pointer to kernel init block having the following format

+00: Image base (e.g. the value of the linker symbol Image$$RO$$Base)
+04: pointer to start of language description blocks
+08: pointer to end of language description blocks
R1 = base of root stack chunk (value returned in R1 from LibInitAPCS_A or LibInitAPCS_R)
R2 = top of root stack chunk (value returned in R2 from LibInitAPCS_A or LibInitAPCS_R)
R3 =
0 for application
1 for module
R4 = end of workspace

On exit

Does not return. Control is regained through the procedure pointer returned in R0 by one of the language initialisation procedures (i.e. control is passed to the run code of the language).

This call does not obey the APCS. All registers are altered. The APCS_R SL, FP and SP (R10, R11 and R13) are set up. LR does not contain a valid return address when control is passed to the run entry.

This function must be called by any client which calls LibInitAPCS_A or LibInitAPCS_R. Modules should call this entry in their run entry.

The words at offsets +04 and +08 from R0 describe an area containing at least one language description block. Any number of language description blocks may be present. The size field of each block must be the offset to the next language description block.

The command line is copied to an internal buffer at the top of the root stack chunk. To set a command line call SWI OS_WriteEnv. RISC OS sets up a command line before running your application or entering your module.

Exit, Error, CallBack, Escape, Event, UpCall, Illegal Instruction, Prefetch Abort, Data Abort and Address Exception handlers are set up.

Initial default alloc and free procs for use during stack extension are set up. These should be replaced with your own alloc and free procs as soon as possible.

The kernel's workspace pointers are initialised to the values contained in R1 and R4. Note that it is assumed the root stack chunk resides at the base of the workspace area.

A small stack (159 words) for use during stack extension is claimed from the workspace following R2 (i.e. 159 words are claimed from R2 upwards).

Note: _kernel_init does not check that there is sufficient space in the workspace to claim this area. You must ensure there is sufficient space before calling _kernel_init.

The availability of floating point is determined (by calling SWI FPE_Version).

If executing under the desktop the initial wimpslot size is determined by reading the Application Space handler.

The initialisation for each language is called, then the run code if any is called. If no run code is present the error No main program is generated.

Entry no. 38: _kernel_moduleinit
On entry

R0 = pointer to kernel init block as described in _kernel_init on Entry no. 0: _kernel_init
R1 = pointer to base of SVC stack (as returned by SWI LibInitModule)

On exit

This call does not obey the APCS.
It assumes that LR has already been pushed on the stack, and so returns to the address on top of the stack (ie the address pointed to by SP), rather than to the address contained in LR on entry. The stack pointer is incremented by 4. See the chapter entitled Calling the shared C library from a module for an example.
On exit SL points to R1 on entry + 560.
R0, R1, R2 and R12 are indeterminate.

The kernel init block is copied for later use. The Image base is ignored.

The functions _kernel_RMAalloc and _kernel_RMAfree are established as the default alloc and free procs for use during stack extension.

You should call this function after calling SWI LibInitModule.

Entry no. 42: _kernel_entermodule
On entry

R0 = pointer to kernel init block as described in _kernel_init on Entry no. 0: _kernel_init
R6 = requested root stack size
R8 = modules private word pointer
R12 = -1

On exit

Does not return.
Control is regained through the procedure pointer returned in R0 by one of the language initialisation procedures.

The private word must point to the module workspace word which must contain the application base, the shared library static offset, and the client static offset in words 0, 1 and 2 (the application base is ignored for modules).

After claiming workspace from the application space and claiming a root stack from this _kernel_entermodule calls _kernel_init.

Stack management functions

Entry no. 27: _kernel_stkovf_split_0frame

This function is described in the section entitled How the run-time stack is managed and extended.

Entry no. 28: _kernel_stkovf_split

This function is described in the section entitled How the run-time stack is managed and extended.

Entry no. 29: _kernel_stkovf_copyargs

This function is described in the section entitled How the run-time stack is managed and extended.

Entry no. 30: _kernel_stkovf_copy0args

This function is described in the section entitled How the run-time stack is managed and extended.

typedef struct stack_chunk {
   unsigned long sc_mark;    /* == 0xf60690ff */
   struct stack_chunk *sc_next, *sc_prev;
   unsigned long sc_size;
   int (*sc_deallocate)()
} _kernel_stack_chunk;

Entry no. 44: _kernel_stack_chunk *_kernel_current_stack_chunk(void)

Returns a pointer to the current stack chunk.

typedef struct {
   int r4, r5, r6, r7, r8, r9;
   int fp, sp, pc, sl;
   int f4[3], f5[3], f6[3], f7[3];
} _kernel_unwindblock;

Entry no. 4: int _kernel_unwind(_kernel_unwindblock *inout, char **language)

Unwinds the call stack one level. Returns:
>0 if it succeeds
0 if it fails because it has reached the stack end or
<0 if it fails for any other reason (e.g. stack corrupt)

Input values for fp, sl and pc must be correct. r4-r9 and f4-f7 are updated if the frame addressed by the input value of fp contains saved values for the corresponding registers.

fp, sp, sl and pc are always updated, the word pointed to by language is updated to point to a string naming the language corresponding to the returned value of pc.

Program environment functions

Entry no. 5: char *_kernel_procname(int pc)

Returns a string naming the procedure containing the address pc (or 0 if no name for it can be found).

Entry no. 6: char *_kernel_language(int pc)

Returns a string naming the language in whose code the address pc lies (or 0 if it is in no known language).

Entry no. 7: char *_kernel_command_string(void)

Returns a pointer to a copy of the command string used to run the program.

Entry no. 2: void _kernel_setreturncode(unsigned code)

Sets the return code to be used by _kernel_exit.

Entry no. 1: void _kernel_exit(void)

Calls OS_Exit with the return code specified by a previous call to _kernel_setreturncode.

Entry no. 47: void _kernel_raise_error(_kernel_oserror *)

Generates an external error.

Entry no. 3: void _kernel_exittraphandler(void)

Resets the InTrapHandler flag which prevents recursive traps. Used in trap handlers which do not return directly but continue execution. For example, the longjmp function in the C library calls _kernel_exittraphandler if called from within a signal handler.

Entry no. 8: int _kernel_hostos(void)

Returns 6 for RISC OS.
(Returns the result of calling OS_Byte with R0 = 0 and R1 = 1.)

Entry no. 37: int _kernel_fpavailable(void)

Returns non-zero if floating point is available.

Entry no. 21: _kernel_oserror *_kernel_last_oserror(void)

Returns a pointer to an error block describing the last OS error since _kernel_last_oserror was last called (or since the program started if there has been no such call). If there has been no OS error it returns 0. Note that occurrence of a further error may overwrite the contents of the block. This can be used, for example, to determine the error which caused fopen to fail. If _kernel_swi caused the last OS error, the error already returned by that call gets returned by this too.

Entry no. 23: _kernel_oserror *_kernel_getenv(const char *name, char *buffer, unsigned size)

Reads the value of a system variable, placing the value string in the buffer (of size size).

Entry no. 24: _kernel_oserror *_kernel_setenv(const char *name, const char *value)

Updates the value of a system variable to be string valued, with the given value (value = 0 deletes the variable).

Entry no. 43: int _kernel_escape_seen(void)

Returns 1 if there has been an escape since the previous call of _kernel_escape_seen (or since the program start if there has been no previous call). Escapes are never ignored with this mechanism, whereas they may be with the language EventProc mechanism since there may be no stack to call the EventProc on.

Entry no. 39: void _kernel_irqs_on(void)

Enable interrupts. You should not disable interrupts unless absolutely necessary. If you disable interrupts you should re-enable them as soon as possible (preferably within 10[MU]S).

This function can only be used from code running in SVC mode.

Entry no. 40: void _kernel_irqs_off(void)

Disable IRQ interrupts. You should not disable interrupts unless absolutely necessary. If you disable interrupts you should re-enable them as soon as possible (preferably within 10[MU]S).

This function can only be used from code running in SVC mode.

Entry no. 41: int _kernel_irqs_disabled(void)

Returns non-zero if IRQ interrupts are disabled.

General utility functions

typedef struct {
   int r[10]; /* only r0 - r9 matter for swi's */
} _kernel_swi_regs;

Entry no. 9: _kernel_oserror *_kernel_swi (int no, _kernel_swi_regs *in, _kernel_swi_regs *out)

Call the SWI specified by no. The X bit is set by _kernel_swi unless bit 31 of the SWI no (in no) is set. in and out are pointers to blocks for R0 - R9 on entry to and exit from the SWI.

Returns a pointer to an error block if an error occurred, otherwise 0.

Warning: If you use this function to call a SWI that returns an error longer than 148 bytes, the register dump area is corrupted; even longer errors may corrupt other vital system data. You should ensure that no error will be returned - or work round this problem by instead using the internal function _swix, which is documented in the C library header files.

Entry no. 45: _kernel_oserror *_kernel_swi_c(int no, _kernel_swi_regs *in, _kernel_swi_regs *out, int *carry)

Similar to _kernel_swi but returns the status of the carry flag on exit from the SWI in the word pointed to by carry.

Entry no. 10: int _kernel_osbyte(int op, int x, int y)

Performs an OS_Byte operation. If there is no error, the result contains:
the return value of R1 (x) in its bottom byte
the return value of R2 (y) in its second byte
1 in the third byte if carry is set on return, otherwise 0
0 in its top byte

Note that some OS_Byte calls return values too great too fit in a single byte.

Entry no. 11: int _kernel_osrdch(void)

Returns a character read from the currently selected OS input stream.

Entry no. 12: int _kernel_oswrch(int ch)

Writes a byte to all currently selected OS output streams. The return value just indicates success or failure.

Entry no. 13: int _kernel_osbget(unsigned handle);

Returns the next byte from the file identified by handle. (-1 =>EOF)

Entry no. 14: int _kernel_osbput(int ch, unsigned handle)

Writes a byte to the file identified by handle. The return value just indicates success or failure.

typedef struct {
   void * dataptr; /* memory address of data */
   int nbytes, fileptr;
   int buf_len; /* these fields for RISC OS gpbp extensions */
   char * wild_fld; /* points to wildcarded filename to match */
} _kernel_osgbpb_block;

Entry no. 15: int _kernel_osgbpb(int op, unsigned handle, _kernel_osgbpb_block *inout);

Reads or writes a number of bytes from a filing system. The return value just indicates success or failure. Note that for some operations, the return value of C is significant, and for others it isn't. In all cases, therefore, a return value of -1 is possible, but for some operations it should be ignored.

Entry no. 16: int _kernel_osword(int op, int *data)

Performs an OS_Word operation. The size and format of the block pointed to by data depends on the particular OS_Word being used; it may be updated.

Entry no. 17: int _kernel_osfind(int op, char *name)

Opens or closes a file. Open returns a file handle (0 => open failed without error). For close the return value just indicates success or failure.

typedef struct {
  int load, exec; /* load, exec addresses */
  int start, end; /* start address/length, end address/attributes */
} _kernel_osfile_block;

Entry no. 18: int _kernel_osfile(int op, const char *name, _kernel_osfile_block *inout)

Performs an OS_File operation, with values of R2 - R5 taken from the osfile block. The block is updated with the return values of these registers, and the result is the return value of R0 (or an error indication).

Entry no. 19: int _kernel_osargs(int op, unsigned handle, int arg)

Performs an OS_Args operation. The result is the current filing system number (if op = 0) otherwise the value returned in R2 by the OS_Args operation.

Entry no. 20: int _kernel_oscli(char *s)

Calls OS_CLI with the specified string. If used to run another application the current application will be closed down. If you wish to return to the current application use _kernel_system. Any return value indicates an error in _kernel_oscli itself.

Entry no. 22: int _kernel_system(char *string, int chain)

Calls OS_CLI with the specified string. If chain is 0, the current application is copied to the top of memory first, then handlers are installed so that if the command string causes an application to be invoked, control returns to _kernel_system, which then copies the calling application back into its proper place. Hence the command is executed as a sub-program. If chain is 1, all handlers are removed before calling the CLI, and if it returns (the command is built-in) _kernel_system exits. Any return value indicates an error in _kernel_system itself.

Memory allocation functions

Entry no. 26: unsigned _kernel_alloc(unsigned words, void **block)

Tries to allocate a block of size = words words. Failing that, it allocates the largest possible block (may be size zero). If words is < 2048 it is rounded up to 2048. Returns a pointer to the allocated block in the word pointed to by block. The return value gives the size of the allocated block.

typedef void freeproc(void *);
typedef void * allocproc(unsigned);

Entry no. 25: void _kernel_register_allocs(allocproc *malloc, freeproc *free)

Registers procedures to be used by the kernel when it requires to free or allocate storage. Currently this is only used to allocate and free stack chunks. Since allocproc and freeproc are called during stack extension, they must not check for stack overflow themselves or call any procedure which does stack checking and must guarantee to require no more than 41 words of stack.

The kernel provides default alloc and free procedures, however you should replace these with your own procedures since the default procedures are rather naive.

typedef int _kernel_ExtendProc(int /*n*/, void** /*p*/);

Entry no. 46: _kernel_ExtendProc *_kernel_register_slotextend(_kernel_ExtendProc *proc)

When the initial heap (supplied to _kernel_init) is full, the kernel is normally capable of extending it by extending the wimpslot. However, if the heap limit is not the same as the application limit, it is assumed that someone else has acquired the space between, and the procedure registered here is called to request n bytes from it.

Its return value is expected to be >= n, or 0 to indicate failure. If successful the word pointed to by p should be set to point to the space allocated.

Language support functions

Entry no. 31: unsigned _kernel_udiv(unsigned divisor, unsigned dividend);

Divide and remainder function, returns the remainder in R1.

Entry no. 32: unsigned _kernel_urem(unsigned divisor, unsigned dividend);

Remainder function.

Entry no. 33: unsigned _kernel_udiv10(unsigned dividend);

Divide and remainder function, returns the remainder in R1.

Entry no. 34: int _kernel_sdiv(int divisor, int dividend);

Signed divide and remainder function, returns the remainder in R1.

Entry no. 35: int _kernel_srem(int divisor, int dividend);

Signed remainder function.

Entry no. 36: int _kernel_sdiv10(int dividend);

Signed divide and remainder function, returns the remainder in R1.

C library functions

The C library functions are grouped under the following headings:

  • Language support functions
    Provides functions for trap and event handling, initialisation and finalisation, and mathematical routines such as number conversion and mulitplication.
  • assert
    The assert modiule provides one function which is useful during program testing.
  • ctype
    The ctype module provides several functions useful for testing and mapping characters.
  • errno
    The word variable __errno at offset 800 in the library statics is set whenever certain error conditions arises.
  • locale
    This module handles national characteristics, such as the different orderings of month-day-year (USA) and day-month-year (UK).
  • math
    This module contains the prototypes for 22 mathematical functions. All return the type double.
  • setjmp
    This module provides two functions for bypassing the normal function call and return discipline.
  • signal
    Signal provides two functions.
  • stdio stdio provides many functions for performing input and output.
  • stdlib stdlib provides several general purpose functions.
  • string string provides several functions useful for manipulating character arrays and other objects treated as character arrays.
  • time time provides several functions for manipulating time.
Index of C library functions by entry number
entry no. name
0 trapHandler
1 uncaughtTrapHandler
2 eventHandler
3 unhandledEventHandler
4 x$stack_overflow
5 x$stack_overflow_1
6 x$udivide
7 x$uremainder
8 x$divide
9 x$divtest
10 x$remainder
11 x$multiply
12 _rd1chk
13 _rd2chk
14 _rd4chk
15 _wr1chk
16 _wr2chk
17 _wr4chk
18 _main
19 _exit
20 _clib_initialise
21 _backtrace
22 _count
23 _count1
24 _stfp
25 _ldfp
26 _printf
27 _fprintf
28 _sprintf
29 clock
30 difftime
31 mktime
32 time
33 asctime
34 ctime
35 gmtime
36 localtime
37 strftime
38 memcpy
39 memmove
40 strcpy
41 strncpy
42 strcat
43 strncat
44 memcmp
45 strcmp
46 strncmp
47 memchr
48 strchr
49 strcspn
50 strpbrk
51 strrchr
52 strspn
53 strstr
54 strtok
55 memset
56 strerror
57 strlen
58 atof
59 atoi
60 atol
61 strtod
62 strtol
63 strtoul
64 rand
65 srand
66 calloc
67 free
68 malloc
69 realloc
70 abort
71 atexit
72 exit
73 getenv
74 system
75 bsearch
76 qsort
77 abs
78 div
79 labs
80 ldiv
81 remove
82 rename
83 tmpfile
84 _old_tmpnam
85 fclose
86 fflush
87 fopen
88 freopen
89 setbuf
90 setvbuf
91 printf
92 fprintf
93 sprintf
94 scanf
95 fscanf
96 sscanf
97 vprintf
98 vfprintf
99 vsprintf
100 _vprintf
101 fgetc
102 fgets
103 fputc
104 fputs
105 __filbuf
106 getc
107 getchar
108 gets
109 __flsbuf
110 putc
111 putchar
112 puts
113 ungetc
114 fread
115 fwrite
116 fgetpos
117 fseek
118 fsetpos
119 ftell
120 rewind
121 clearerr
122 feof
123 ferror
124 perror
125 __ignore_signal_handler
126 __error_signal_marker
127 __default_signal_handler
128 signal
129 raise
130 setjmp
131 longjmp
132 acos
133 asin
134 atan
135 atan2
136 cos
137 sin
138 tan
139 cosh
140 sinh
141 tanh
142 exp
143 frexp
144 ldexp
145 log
146 log10
147 modf
148 pow
149 sqrt
150 ceil
151 fabs
152 floor
153 fmod
154 setlocale
155 isalnum
156 isalpha
157 iscntrl
158 isdigit
159 isgraph
160 islower
161 isprint
162 ispunct
163 isspace
164 isupper
165 isxdigit
166 tolower
167 toupper
168 __assert
169 _memcpy
170 _memset
171 localeconv
172 mblen
173 mbtowc
174 wctomb
175 mbstowcs
176 wcstombs
177 strxfrm
178 strcoll
179 _clib_finalisemodule
180 _clib_version
181 finalise
182 tmpnam
error condition ERANGE
error condition ESIGNUM
Index of C library functions by function name
name entry no.
abort 70
abs 77
acos 132
asctime 33
asin 133
__assert 168
atan 134
atan2 135
atexit 71
atof 58
atoi 59
atol 60
_backtrace 21
bsearch 75
calloc 66
ceil 150
clearerr 121
_clib_finalisemodule 179
_clib_initialise 20
_clib_version 180
clock 29
cos 136
cosh 139
_count 22
_count1 23
ctime 34
__default_signal_handler 127
difftime 30
div 78
__error_signal_marker 126
eventHandler 2
exit 72
_exit 19
exp 142
fabs 151
fclose 85
feof 122
ferror 123
fflush 86
fgetc 101
fgetpos 116
fgets 102
__filbuf 105
finalise 181
floor 152
__flsbuf 109
fmod 153
fopen 87
fprintf 92
_fprintf 27
fputc 103
fputs 104
fread 114
free 67
freopen 88
frexp 143
fscanf 95
fseek 117
fsetpos 118
ftell 119
fwrite 115
getc 106
getchar 107
getenv 73
gets 108
gmtime 35
__ignore_signal_handler 125
isalnum 155
isalpha 156
iscntrl 157
isdigit 158
isgraph 159
islower 160
isprint 161
ispunct 162
isspace 163
isupper 164
isxdigit 165
labs 79
localeconv 171
ldexp 144
_ldfp 25
ldiv 80
localtime 36
log 145
log10 146
longjmp 131
_main 18
malloc 68
mblen 172
mbstowcs 175
mbtowc 173
memchr 47
memcmp 44
memcpy 38
_memcpy 169
memmove 39
memset 55
_memset 170
mktime 31
modf 147
_old_tmpnam 84
perror 124
pow 148
printf 91
_printf 26
putc 110
putchar 111
puts 112
qsort 76
raise 129
rand 64
_rd1chk 12
_rd2chk 13
_rd4chk 14
realloc 69
remove 81
rename 82
rewind 120
scanf 94
setbuf 89
setjmp 130
setlocale 154
setvbuf 90
signal 128
sin 137
sinh 140
sprintf 93
_sprintf 28
sqrt 149
srand 65
sscanf 96
_stfp 24
strcat 42
strchr 48
strcmp 45
strcoll 178
strcpy 40
strcspn 4
strerror 56
strftime 37
strlen 57
strncat 43
strncmp 46
strncpy 41
strpbrk 50
strrchr 51
strspn 52
strstr 53
strtod 61
strtok 54
strtol 62
strtoul 63
strxfrm 177
system 74
tan 138
tanh 141
time 32
tmpfile 83
tmpnam 182
tolower 166
toupper 167
trapHandler 0
uncaughtTrapHandler 1
ungetc 113
unhandledEventHandler 3
vfprintf 98
vprintf 97
_vprintf 100
vsprintf 99
wcstombs 176
wctomb 174
_wr1chk 15
_wr2chk 16
_wr4chk 17
x$divide 8
x$divtest 9
x$multiply 11
x$remainder 10
x$stack_overflow 4
x$stack_overflow_1 5
x$udivide 6
x$uremainder 7

Language support functions

Entry no. 0: TrapHandler

Entry no. 1: UncaughtTrapHandler
On entry:

R0 = error code
R1 = pointer to register dump

On exit:

Only exits if the trap was not handled

R0 = 0 (indicating that the trap was not handled).

These are the default TrapProc and UncaughtTrapProc handlers used by the C library in its kernel language description (see the chapter entitled Interfacing a language run-time system to the Acorn library kernel).

You may use these entries in your own kernel language description if you wish to have trap handling similar to that provided by the C library, or you may call these entries directly from your own trap handler if you wish to perform some pre-processing before passing the trap on.

The error code on entry is converted to a signal number as follows:

Signal no. Error codes
2 (SIGFPE) &80000020 (Error_DivideByZero),
&80000200 (Error_FPBase) - &800002FF (Error_FPLimit - 1)
3 (SIGILL) &80000000 (Error_IllegalInstruction),
&80000001 (Error_PrefetchAbort),
&80000005 (Error_BranchThroughZero)
5 (SIGSEGV) &80000002 (Error_DataAbort),
&80000003 (Error_AddressException),
&80800EA0 (Error_ReadFail),
&80800EA1 (Error_WriteFail)
7 (SIGSTAK) &80000021 (Error_StackOverflow)
10 (SIGOSERROR) All other errors

It then determines whether a signal handler has been set up for the converted signal handler; if no such handler has been set up (ie the signal handler is set to __SIG_DFL) it returns with R0 = 0.

Otherwise it calls the C library function raise with the derived signal number. If the raise function returns (ie the signal handler returns) a postmortem stack backtrace is generated.

Entry no. 2: EventHandler

Entry no. 3: UnhandledEventHandler
On entry:

R0 = event code
R1 = pointer to register dump

On exit:

R0 = 1 if the event was handled, else 0

These are the default EventProc and UnhandledEventProc handlers used by the C library in its kernel language description (see the chapter entitled Interfacing a language run-time system to the Acorn library kernel).

You may use these entries in your own kernel language description if you wish to have event handling similar to that provided by the C library or you may call these entries directly from your own event handler if you wish to perform some pre-processing before passing the event on.

The event code on entry is either a RISC OS event number as described in the chapter entitled Events, or -1 to indicate an escape event.

All events codes except -1 are currently ignored. The handler simply returns with R0 = 0 if R0 [NOT EQUAL] -1 on entry.

EventHandler then determines whether a SIGINT signal handler has been set up. If no handler is set up (ie the signal handler is set to __SIG_DFL) EventHandler returns with R0 = 0.

The C library function raise is then called with the signal number SIGINT. Note: raise is always called by UnhandledEventHandler even if the signal handler is set to __SIG_DFL.

If the signal handler returns the event handler returns with R0 = 1.

Certain sections of the C library are non-reentrant. When these sections are entered they set the variable _interrupts_off at offset 964 in the library statics to 1.

EventHandler and UnhandledEventHandler check this variable and, if it is set, they set the variable _saved_interrupt at offset 968 in the library statics to SIGINT and return immediately with R0 = 1 and without calling raise.

When the non-reentrant sections of code finish they reset the variable _interrupts_off and check the variable _saved_interrupts. If _saved_interrupts is non-zero it is reset to zero and the signal number stored in _saved_interrupts (before it was reset to 0) is raised.

Entry no. 4: x$stack_overflow

This entry branches directly to _kernel_stkovf_split_0frame which is described in the chapter entitled How the run-time stack is managed and extended.

Entry no. 5: x$stack_overflow_1

This entry branches directly to _kernel_stkovf_split which is described in the chapter entitled How the run-time stack is managed and extended.

Entry no. 6: x$udivide

This entry branches directly to _kernel_udiv described on Entry no. 31: unsigned _kernel_udiv(unsigned divisor, unsigned dividend);.

Entry no. 7: x$uremainder

This entry branches directly to _kernel_urem described on Entry no. 32: unsigned _kernel_urem(unsigned divisor, unsigned dividend);.

Entry no. 8: x$divide

This entry branches directly to _kernel_sdiv described on Entry no. 34: int _kernel_sdiv(int divisor, int dividend);.

Entry no. 9: x$divtest

This function is used by the C compiler to test for division by zero when the result of the division is discarded.

If R0 is non-zero the function simply returns. Otherwise it generates a Divide by zero error.

Entry no. 10: x$remainder

This entry branches directly to _kernel_srem described on Entry no. 35: int _kernel_srem(int divisor, int dividend);.

Entry no. 11: x$multiply
On entry:

R0 = multiplicand
R1 = multiplier

On exit:

R0 = R0 × R1
R1, R2 scrambled.

Entry no. 12: _rd1chk

Entry no. 13: _rd2chk

Entry no. 14: _rd4chk

The functions _rd1chk, _rd2chk and _rd4chk check that the value of R0 passed to them is a valid address in the application space (&8000 <= R0 < &1000000). _rd2chk and _rd4chk also check that the value is properly aligned for a half-word / word access respectively.

If the value of R0 is a valid address the function just returns, otherwise it generates an Illegal read error.

These calls are used by the C compiler when compiling with memory checking enabled.

Entry no. 15: _wr1chk

Entry no. 16: _wr2chk

Entry no. 17: _wr4chk

The functions _wr1chk, _wr2chk and _wr4chk check that the value of R0 passed to them is a valid address in the application space (&8000 <= R0 < &1000000). _rd2chk and _rd4chk also check that the value is properly aligned for a half-word / word access respectively.

If the value of R0 is a valid address the function just returns, otherwise it generates an Illegal write error.

These calls are used by the C compiler when compiling with memory checking enabled.

Entry no. 18: _main
On entry:

R0 = pointer to copy of command line (the command line pointed to by R0 on return from OS_GetEnv should be copied to another buffer before calling _main; this can be done using _kernel_command_string, detailed on Entry no. 7: char *_kernel_command_string(void)).

R1 = address of routine at which execution will continue when _main has finished.

The following entry and exit conditions apply for this routine:

On entry:

R0 = count of argument words.
R1 = pointer to block containing R0 + n words, each word of which points to a zero terminated string which is the nth word in the command line passed to _main. The last word in the block contains 0.

On exit:

R0 = exit condition (0 = success, else failure)

For C programs this argument will generally point at main.

On exit:

Does not return. Control is regained through the R1 argument on entry.

This function parses the command line pointed to by R0 and then calls the function pointed to by R1.

For C programs this function is called by the C library as a precursor to calling main to provide the C entry / exit requirements.

Entry no. 19: void _exit(void)

This function is identical in behaviour to the C library function exit described on Entry no. 72: void exit(int status).

Entry no. 20: void _clib_initialise(void)

Performs initialisation required by the C library before other C library functions can be called. You may call kernel library functions without first making this call. You should call this function in your initialisation entry for a module and in your InitProc procedure for applications or modules that have a run entry. For a description of InitProc procedures, see InitProc. The two programming examples on Calling the shared C library and Calling the shared C library from a module show how _clib_initialise should be called for an application and a module respectively.

Entry no. 21: void _backtrace(int why, int *address, _kernel_unwindblock *uwb)

Displays a stack backtrace and exits with the exit code 1.

The _kernel_unwindblock structure is described with the _kernel_unwind function on Entry no. 4: int _kernel_unwind(_kernel_unwindblock *inout, char **language). The argument why is an error code, if why is Error_ReadFail (&80800ea0) or Error_WriteFail (&80800ea1) the address given by the address argument is displayed at the top of the backtrace, otherwise the message postmortem requested is displayed.

Entry no. 22: _count

Entry no. 23: _count1

These entries are used by the C compiler when generating profile code.

Both _count and _count1 increment the word pointed to by R14 (after stripping the status bits); this will generally be the word immediately following a BL instruction to the relevant routine. _count then returns to the word immediately following the incremented word, _count1 returns to the word after that (the second word is used by the C compiler to record the position in a source file that this count-point refers to).

 BL     _count
 DCD    0       ; This word incremented each time _count is called
 ...            ; Control returns here
 BL     _count1
 DCD    0       ; This word incremented each time _count1 is called
 DCD    filepos ; Offset into source file
 ...            ; Control returns here

Entry no. 24: void _stfp(double d, void *x)

This function converts the double FP no. d to packed decimal and stores it at address x. Note that the double d is passed in R0, R1 (R0 containing the first word when a double is stored in memory, R1 containing the second word), the argument x is passed in R2. Three words should be reserved at x for the packed decimal number.

Entry no. 25: double _ldfp(void *x)

This function converts the packed decimal number stored at x to a double FP no. and returns this in F0.

Entry no. 169: void _memcpy(int *dest, int *source, int n)

This function performs a similar function to memcpy except that dest and source must be word aligned and the byte count n must be a multiple of 4.

It is used by the C compiler when copying structures.

Entry no. 170: void _memset(int *dest, int w, int n)

This function performs a similar function to memset except that dest must be word aligned, the byte value to be set must be copied into each of the four bytes of w (i.e. to initialise memory to &01 you must use &01010101 in w) and the byte count n must be a multiple of 4.

It is used by the C compiler when initialising structures.

Entry no. 179: _clib_finalisemodule
On entry:

R0 = private word pointer

On exit:

Block pointed to by private word is freed

This entry must be called in the finalisation code of a module which uses the shared C library. Before calling it you must set up the static data relocation pointers on the base of the SVC stack and initialise the SL register to point to the base of the SVC stack + 512. The old static data relocation pointers on the base of the SVC stack must be saved around this call.

Entry no. 180: char *_clib_version(void)

This function returns a string giving version information on the shared C library.

Entry no. 181: Finalise

This function calls all the registered atexit functions and then performs some internal finalisation of the alloc and io subsystems.

This entry is called automatically by the C library on finalisation; you should not call it in your code.

assert

The assert module provides one function which is useful during program testing.

Entry no. 168: void __assert(char *reason, char *file, int line)

Displays the message:

*** assertion failed: 'reason', file 'file', line 'line'

and raises SIGABRT.

This function is generally used within a macro which calls __assert if a specified condition is false.

ctype

The ctype module provides several functions useful for testing and mapping characters. In all cases the argument is an int, the value of which is representable as an unsigned char or equal to the value -1. If the argument has any other value, the behaviour is undefined.

Entry no. 155: int isalnum(int c)

Returns true if c is alphabetic or numeric

Entry no. 156: int isalpha(int c)

Returns true if c is alphabetic

Entry no. 157: int iscntrl(int c)

Returns true if c is a control character (in the ASCII locale)

Entry no. 158: int isdigit(int c)

Returns true if c is a decimal digit

Entry no. 159: int isgraph(int c)

Returns true if c is any printable character other than space

Entry no. 160: int islower(int c)

Returns true if c is a lower-case letter

Entry no. 161: int isprint(int c)

Returns true if c is a printable character (in the ASCII locale this means &20 (space) -> &7E (tilde) inclusive).

Entry no. 162: int ispunct(int c)

Returns true if c is a printable character other than a space or alphanumeric character

Entry no. 163: int isspace(int c)

Returns true if c is a white space character viz: space, newline, return, linefeed, tab or vertical tab

Entry no. 164: int isupper(int c)

Returns true if c is an upper-case letter

Entry no. 165: int isxdigit(int c)

Returns true if c is a hexadecimal digit, ie in 0...9, a...f, or A...F

Entry no. 166: int tolower(int c)

Forces c to lower case if it is an upper-case letter, otherwise returns the original value

Entry no. 167: int toupper(int c)

Forces c to upper case if it is a lower-case letter, otherwise returns the original value

errno

The word variable errno at offset 800 in the library statics is set whenever one of the error conditions listed below arises.

EDOM (errno=1)

If a domain error occurs (an input argument is outside the domain over which the mathematical function is defined) the integer expression errno acquires the value of the macro EDOM, and HUGE_VAL is returned. EDOM may be used by non-mathematical functions.

ERANGE (errno=2)

A range error occurs if the result of a function cannot be represented as a double value. If the result overflows (the magnitude of the result is so large that it cannot be represented in an object of the specified type), the function returns the value of the macro HUGE_VAL, with the same sign as the correct value of the function; the integer expression errno acquires the value of the macro ERANGE. If the result underflows (the magnitude of the result is so small that it cannot be represented in an object of the specified type), the function returns zero; the integer expression errno acquires the value of the macro ERANGE. ERANGE may be used by non-mathematical functions.

ESIGNUM (errno=3)

If an unrecognised signal is caught by the default signal handler, errno is set to ESIGNUM.

locale

This module handles national characteristics, such as the different orderings month-day-year (USA) and day-month-year (UK).

Entry no. 154: char *setlocale(int category, const char *locale)

Selects the appropriate part of the program's locale as specified by the category and locale arguments. The setlocale function may be used to change or query the program's entire current locale or portions thereof. Locale information is divided into the following types:

Type Value Description
LC_COLLATE (1) string collation
LC_CTYPE (2) character type
LC_MONETARY (4) monetary formatting
LC_NUMERIC (8) numeric string formatting
LC_TIME (16) time formatting
LC_ALL (31) entire locale

The locale string specifies which locale set of information is to be used. For example,

setlocale(LC_MONETARY,"uk")

would insert monetary information into the lconv structure. To query the current locale information, set the locale string to null and read the string returned.

Entry no. 171: struct lconv *localeconv(void)

Sets the components of an object with type struct lconv with values appropriate for the formatting of numeric quantities (monetary and otherwise) according to the rules of the current locale. The members of the structure with type char * are strings, any of which (except decimal_point) can point to "", to indicate that the value is not available in the current locale or is of zero length. The members with type char are non-negative numbers, any of which can be CHAR_MAX to indicate that the value is not available in the current locale. The members included are described above.

localeconv returns a pointer to the filled in object. The structure pointed to by the return value will not be modified by the program, but may be overwritten by a subsequent call to the localeconv function. In addition, calls to the setlocale function with categories LC_ALL, LC_MONETARY, or LC_NUMERIC may overwrite the contents of the structure.

math

This module contains 22 mathematical functions. All return the type double.

Entry no. 132: double acos(double x)

Returns arc cosine of x. A domain error occurs for arguments not in the range -1 to 1

Entry no. 133: double asin(double x)

Returns arc sine of x. A domain error occurs for arguments not in the range -1 to 1

Entry no. 134: double atan(double x)

Returns arc tangent of x

Entry no. 135: double atan2(double x, double y)

Returns arc tangent of x/y

Entry no. 136: double cos(double x)

Returns cosine of x (measured in radians)

Entry no. 137: double sin(double x)

Returns sine of x (measured in radians)

Entry no. 138: double tan(double x)

Returns tangent of x (measured in radians)

Entry no. 139: double cosh(double x)

Returns hyperbolic cosine of x

Entry no. 140: double sinh(double x)

Returns hyperbolic sine of x

Entry no. 141: double tanh(double x)

Returns hyperbolic tangent of x

Entry no. 142: double exp(double x)

Returns exponential function of x

Entry no. 143: double frexp(double x, int *exp)

Returns the value x, such that x is a double with magnitude in the interval 0.5 to 1.0 or zero, and value equals x times 2 raised to the power *exp

Entry no. 144: double ldexp(double x, int exp)

Returns x times 2 raised to the power of exp

Entry no. 145: double log(double x)

Returns natural logarithm of x

Entry no. 146: double log10(double x)

Returns log to the base 10 of x

Entry no. 147: double modf(double x, double *iptr)

Returns signed fractional part of x. Stores integer part of x in object pointed to by iptr.

Entry no. 148: double pow(double x, double y)

Returns x raised to the power of y

Entry no. 149: double sqrt(double x)

Returns positive square root of x

Entry no. 150: double ceil(double x)

Returns smallest integer not less than x (ie rounding up)

Entry no. 151: double fabs(double x)

Returns absolute value of x

Entry no. 152: double floor(double x)

Returns largest integer not greater than x (ie rounding down)

Entry no. 153: double fmod(double x, double y)

Returns floating-point remainder of x/y

setjmp

This module provides two functions for bypassing the normal function call and return discipline (useful for dealing with unusual conditions encountered in a low-level function of a program).

Entry no. 130: int setjmp(jmp_buf env)

The calling environment is saved in env, for later use by the longjmp function. If the return is from a direct invocation, the setjmp function returns the value zero. If the return is from a call to the longjmp function, the setjmp function returns a non-zero value.

Entry no. 131: void longjmp(jmp_buf env, int val)

The environment saved in env by the most recent call to setjmp is restored. If there has been no such call, or if the function containing the call to setjmp has terminated execution (eg with a return statement) in the interim, the behaviour is undefined. All accessible objects have values as at the time longjmp was called, except that the values of objects of automatic storage duration that do not have volatile type and that have been changed between the setjmp and longjmp calls are indeterminate.

As it bypasses the usual function call and return mechanism, the longjmp function executes correctly in contexts of interrupts, signals and any of their associated functions. However, if the longjmp function is invoked from a nested signal handler (that is, from a function invoked as a result of a signal raised during the handling of another signal), the behaviour is undefined.

After longjmp is completed, program execution continues as if the corresponding call to setjmp had just returned the value specified by val. The longjmp function cannot cause setjmp to return the value 0; if val is 0, setjmp returns the value 1.

signal

Signal provides two functions.

typedef void Handler(int);

Entry no. 128: Handler *signal(int, Handler *);

The following signal handlers are defined:
Type Value Description
SIG_DFL (Handler*)-1 default routine
SIG_IGN (Handler*)-2 ignore signal routine
SIG_ERR (Handler*)-3 dummy routine to flag error return from signal

The following signals are defined:

Signal Value Description
SIGABRT 1 abort (ie call to abort())
SIGFPE 2 arithmetic exception
SIGILL 3 illegal instruction
SIGINT 4 attention request from user
SIGSEGV 5 bad memory access
SIGTERM 6 termination request
SIGSTAK 7 stack overflow
SIGUSR1 8 user definable
SIGUSR2 9 user definable
SIGOSERROR 1 operating system error

The 'signal' function chooses one of three ways in which receipt of the signal number sig is to be subsequently handled. If the value of func is SIG_DFL, default handling for that signal will occur. If the value of func is SIG_IGN, the signal will be ignored. Otherwise func points to a function to be called when that signal occurs.

When a signal occurs, if func points to a function, first the equivalent of signal(sig, SIG_DFL) is executed. (If the value of sig is SIGILL, whether the reset to SIG_DFL occurs is implementation-defined (under RISC OS the reset does occur)). Next, the equivalent of (*func)(sig); is executed. The function may terminate by calling the abort, exit or longjmp function. If func executes a return statement and the value of sig was SIGFPE or any other implementation-defined value corresponding to a computational exception, the behaviour is undefined. Otherwise, the program will resume execution at the point it was interrupted.

If the signal occurs other than as a result of calling the abort or raise function, the behaviour is undefined if the signal handler calls any function in the standard library other than the signal function itself or refers to any object with static storage duration other than by assigning a value to a volatile static variable of type sig_atomic_t. At program start-up, the equivalent of signal(sig, SIG_IGN) may be executed for some signals selected in an implementation defined manner (under RISC OS this does not occur); the equivalent of signal(sig, SIG_DFL) is executed for all other signals defined by the implementation.

If the request can be honoured, the signal function returns the value of func for most recent call to signal for the specified signal sig. Otherwise, a value of SIG_ERR is returned and the integer expression errno is set to indicate the error.

Entry no. 129: int raise(int sig)

Sends the signal sig to the executing program. Returns zero if successful, non-zero if unsuccessful.

Entry no. 125: void __ignore_signal_handler(int sig)

This function is for compatibility with older versions of the shared C library stubs and should not be called in your code.

Entry no. 126: void __error_signal_marker(int sig)

This function is for compatibility with older versions of the shared C library stubs and should not be called in your code.

Entry no. 127: void __default_signal_handler(int sig)

This function is for compatibility with older versions of the shared C library stubs and should not be called in your code.

stdio

stdio provides many functions for performing input and output. For a discussion on Streams and Files refer to sections 4.9.2 and 4.9.3 in the ANSI standard.

The following two types are used by the stdio module:

typedef int fpos_t;

fpos_t is an object capable of recording all information needed to specify uniquely every position within a file.

typedef struct FILE {
   unsigned char *_ptr;   /* pointer to IO buffer */
   int _icnt;             /* character count for input */
   int _ocnt;             /* character count for output */
   int _flag;             /* flags, see below */
   int internal[6];
} FILE;

The following flags are defined in the flags field above:

Flag Bit mask Description
_IOEOF &040 end-of-file reached
_IOERR &080 error occurred on stream
_IOFBF &100 fully buffered IO
_IOLBF &200 line buffered IO<
_IONBF &400 unbuffered IO

FILE is an object capable of recording all information needed to control a stream, such as its file position indicator, a pointer to its associated buffer, an error indicator that records whether a read/write error has occurred and an end-of-file indicator that records whether the end-of-file has been reached.

Entry no. 81: int remove(const char *filename)

Causes the file whose name is the string pointed to by filename to be removed. Subsequent attempts to open the file will fail, unless it is created anew. If the file is open, the behaviour of the remove function is implementation-defined (under RISC OS the operation fails).

Returns: zero if the operation succeeds, non-zero if it fails.

Entry no. 82: int rename(const char *old, const char *new)

Causes the file whose name is the string pointed to by old to be henceforth known by the name given by the string pointed to by new. The file named old is effectively removed. If a file named by the string pointed to by new exists prior to the call of the rename function, the behaviour is implementation-defined (under RISC OS, the operation fails).

Returns: zero if the operation succeeds, non-zero if it fails, in which case if the file existed previously it is still known by its original name.

Entry no. 83: FILE *tmpfile(void)

Creates a temporary binary file that will be automatically removed when it is closed or at program termination. The file is opened for update.

Returns: a pointer to the stream of the file that it created. If the file cannot be created, a null pointer is returned.

Entry no. 182: char *tmpnam(char *s)

Generates a string that is not the same as the name of an existing file. The tmpnam function generates a different string each time it is called, up to TMP_MAX times. If it is called more than TMP_MAX times, the behaviour is implementation-defined (under RISC OS the algorithm for the name generation works just as well after tmpnam has been called more than TMP_MAX times as before; a name clash is impossible in any single half year period).

Returns: If the argument is a null pointer, the tmpnam function leaves its result in an internal static object and returns a pointer to that object. Subsequent calls to the tmpnam function may modify the same object. If the argument is not a null pointer, it is assumed to point to an array of at least L_tmpnam characters; the tmpnam function writes its result in that array and returns the argument as its value.

Entry no. 84: char *__old_tmpnam(char *s)

This function is included for backwards compatibility for binaries linked with older library stubs. You should not call this function in your code, call tmpnam (Entry no. 182) instead.

Entry no. 85: int fclose(FILE *stream)

Causes the stream pointed to by stream to be flushed and the associated file to be closed. Any unwritten buffered data for the stream are delivered to the host environment to be written to the file; any unread buffered data are discarded. The stream is disassociated from the file. If the associated buffer was automatically allocated, it is deallocated.

Returns: zero if the stream was successfully closed, or EOF if any errors were detected or if the stream was already closed.

Entry no. 86: int fflush(FILE *stream)

If the stream points to an output or update stream in which the most recent operation was output, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file. If the stream points to an input or update stream, the fflush function undoes the effect of any preceding ungetc operation on the stream.

Returns: EOF if a write error occurs.

Entry no. 87: FILE *fopen(const char *filename, const char *mode)

Opens the file whose name is the string pointed to by filename, and associates a stream with it. The argument mode points to a string beginning with one of the following sequences:

r open text file for reading
w create text file for writing, or truncate to zero length
a append; open text file or create for writing at eof
rb open binary file for reading
wb create binary file for writing, or truncate to zero length
ab append; open binary file or create for writing at eof
r+ open text file for update (reading and writing)
w+ create text file for update, or truncate to zero length
a+ append; open text file or create for update, writing at eof
r+b or rb+ open binary file for update (reading and writing)
w+b or wb+ create binary file for update, or truncate to zero length
a+b or ab+ append; open binary file or create for update, writing at eof
  • Opening a file with read mode (r as the first character in the mode argument) fails if the file does not exist or cannot be read.
  • Opening a file with append mode (a as the first character in the mode argument) causes all subsequent writes to be forced to the current end of file, regardless of intervening calls to the fseek function.
  • In some implementations, opening a binary file with append mode (b as the second or third character in the mode argument) may initially position the file position indicator beyond the last data written, because of null padding (but not under RISC OS).
  • When a file is opened with update mode (+ as the second or third character in the mode argument), both input and output may be performed on the associated stream. However, output may not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), nor may input be directly followed by output without an intervening call to the fflush function or to a file positioning function, unless the input operation encounters end-of-file.
  • Opening a file with update mode may open or create a binary stream in some implementations (but not under RISC OS). When opened, a stream is fully buffered if and only if it does not refer to an interactive device. The error and end-of-file indicators for the stream are cleared.

Returns: a pointer to the object controlling the stream. If the open operation fails, fopen returns a null pointer.

Entry no. 88: FILE *freopen(const char *filename, const char *mode, FILE *stream)

Opens the file whose name is the string pointed to by filename and associates the stream pointed to by stream with it. The mode argument is used just as in the fopen function. The freopen function first attempts to close any file that is associated with the specified stream. Failure to close the file successfully is ignored. The error and end-of-file indicators for the stream are cleared.

Returns: a null pointer if the operation fails. Otherwise, freopen returns the value of the stream.

Entry no. 89: void setbuf(FILE *stream, char *buf)

Except that it returns no value, the setbuf function is equivalent to the setvbuf function invoked with the values _IOFBF for mode and BUFSIZ for size, or if buf is a null pointer, with the value _IONBF for mode.

Returns: no value.

Entry no. 90: int setvbuf(FILE *stream, char *buf, int mode, size_t size)

This may be used after the stream pointed to by stream has been associated with an open file but before it is read or written. The argument mode determines how stream will be buffered, as follows:

  • _IOFBF causes input/output to be fully buffered.
  • _IOLBF causes output to be line buffered (the buffer will be flushed when a newline character is written, when the buffer is full, or when interactive input is requested).
  • _IONBF causes input/output to be completely unbuffered.

If buf is not the null pointer, the array it points to may be used instead of an automatically allocated buffer (the buffer must have a lifetime at least as great as the open stream, so the stream should be closed before a buffer that has automatic storage duration is deallocated upon block exit). The argument size specifies the size of the array. The contents of the array at any time are indeterminate.

Returns: zero on success, or non-zero if an invalid value is given for mode or size, or if the request cannot be honoured.

Entry no. 92: int fprintf(FILE *stream, const char *format, ...)

Writes output to the stream pointed to by stream, under control of the string pointed to by format that specifies how subsequent arguments are converted for output. If there are insufficient arguments for the format, the behaviour is undefined. If the format is exhausted while arguments remain, the excess arguments are evaluated but otherwise ignored. The fprintf function returns when the end of the format string is reached. The format must be a multibyte character sequence, beginning and ending in its initial shift state. The format is composed of zero or more directives: ordinary multibyte characters (not %), which are copied unchanged to the output stream; and conversion specifiers, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the character %. For a complete description of the available conversion specifiers refer to section 4.9.6.1 in the ANSI standard. The minimum value for the maximum number of characters that can be produced by any single conversion is at least 509.

A brief and incomplete description of conversion specifications is:

[flags][field width][.precision]specifier-char

flags is most commonly -, indicating left justification of the output item within the field. If omitted, the item will be right justified.
field width is the minimum width of field to use. If the formatted item is longer, a bigger field will be used; otherwise, the item will be right (left) justified in the field.
precision is the minimum number of digits to print for a d, i, o, u, x or X conversion, the number of digits to appear after the decimal digit for e, E and f conversions, the maximum number of significant digits for g and G conversions, or the maximum number of characters to be written from strings in an s conversion.

Either of both of field width and precision may be *, indicating that the value is an argument to printf.

The specifier chars are:

d, i int printed as signed decimal
o, u, x, X unsigned int value printed as unsigned octal, decimal or hexadecimal
f double value printed in the style [-]ddd.ddd
e, E double value printed in the style [-]d.ddd...e±dd
g, G double printed in f or e format, whichever is more appropriate
c int value printed as unsigned char
s char *value printed as a string of characters
p void *argument printed as a hexadecimal address
% write a literal %

Returns: the number of characters transmitted, or a negative value if an output error occurred.

Entry no. 91: int printf(const char *format, ...)

Equivalent to fprintf with the argument stdout interposed before the arguments to printf.

Returns: the number of characters transmitted, or a negative value if an output error occurred.

Entry no. 93: int sprintf(char *s, const char *format, ...)

Equivalent to fprintf, except that the argument s specifies an array into which the generated output is to be written, rather than to a stream. A null character is written at the end of the characters written; it is not counted as part of the returned sum.

Returns: the number of characters written to the array, not counting the terminating null character.

Entry no. 26: int _printf(const char *format, ...)

This function is identical in function to printf except that it does not handle floating point arguments.

It is used for space optimisation by the C compiler when using the non shared library and when a literal format string does not contain any floating point conversions.

It is included in the shared library for compatibility with the non shared library.

Entry no. 27: int _fprintf(FILE *stream, const char *format, ...)

This function is identical in function to fprintf except that it does not handle floating point arguments.

It is used for space optimisation by the C compiler when using the non shared library and when a literal format string does not contain any floating point conversions.

It is included in the shared library for compatibility with the non shared library.

Entry no. 28: int _sprintf(char *s, const char *format, ...)

This function is identical in function to sprintf except that it does not handle floating point arguments.

It is used for space optimisation by the C compiler when using the non shared library and when a literal format string does not contain any floating point conversions.

It is included in the shared library for compatibility with the non shared library.

Entry no. 100: int _vfprintf(FILE *stream, const char *format, va_list arg)

This function is identical in function to vfprintf except that it does not handle floating point arguments.

It is used for space optimisation by the C compiler when using the non shared library and when a literal format string does not contain any floating point conversions.

It is included in the shared library for compatibility with the non shared library.

Entry no. 95: int fscanf(FILE *stream, const char *format, ...)

Reads input from the stream pointed to by stream, under control of the string pointed to by format that specifies the admissible input sequences and how they are to be converted for assignment, using subsequent arguments as pointers to the objects to receive the converted input. If there are insufficient arguments for the format, the behaviour is undefined. If the format is exhausted while arguments remain, the excess arguments are evaluated but otherwise ignored. The format is composed of zero or more directives, one or more white-space characters, an ordinary character (not %), or a conversion specification. Each conversion specification is introduced by the character %. For a description of the available conversion specifiers refer to section 4.9.6.2 in the ANSI standard, or to any of the references listed in the chapter entitled Introduction on page 1 of the Acorn Desktop C Manual. A brief list is given above, under the entry for fprintf.

If end-of-file is encountered during input, conversion is terminated. If end-of-file occurs before any characters matching the current directive have been read (other than leading white space, where permitted), execution of the current directive terminates with an input failure; otherwise, unless execution of the current directive is terminated with a matching failure, execution of the following directive (if any) is terminated with an input failure.

If conversions terminate on a conflicting input character, the offending input character is left unread in the input stream. Trailing white space (including newline characters) is left unread unless matched by a directive. The success of literal matches and suppressed assignments is not directly determinable other than via the %n directive.

Returns: the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the fscanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early conflict between an input character and the format.

Entry no. 94: int scanf(const char *format, ...)

Equivalent to fscanf with the argument stdin interposed before the arguments to scanf.

Returns: the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.

Entry no. 96: int sscanf(const char *s, const char *format, ...)

Equivalent to fscanf except that the argument s specifies a string from which the input is to be obtained, rather than from a stream. Reaching the end of the string is equivalent to encountering end-of-file for the fscanf function.

Returns: the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.

Entry no. 97: int vprintf(const char *format, va_list arg)

Equivalent to printf, with the variable argument list replaced by arg, which has been initialised by the va_start macro (and possibly subsequent va_arg calls). The vprintf function does not invoke the va_end function.

Returns: the number of characters transmitted, or a negative value if an output error occurred.

Entry no. 98: int vfprintf(FILE *stream, const char *format, va_list arg)

Equivalent to fprintf, with the variable argument list replaced by arg, which has been initialised by the va_start macro (and possibly subsequent va_arg calls). The vfprintf function does not invoke the va_end function.

Returns: the number of characters transmitted, or a negative value if an output error occurred.

Entry no. 99: int vsprintf(char *s, const char *format, va_list arg)

Equivalent to sprintf, with the variable argument list replaced by arg, which has been initialised by the va_start macro (and possibly subsequent va_arg calls). The vsprintf function does not invoke the va_end function.

Returns: the number of characters written in the array, not counting the terminating null character.

Entry no. 101: int fgetc(FILE *stream)

Obtains the next character (if present) as an unsigned char converted to an int, from the input stream pointed to by stream, and advances the associated file position indicator (if defined).

Returns: the next character from the input stream pointed to by stream. If the stream is at end-of-file, the end-of-file indicator is set and fgetc returns EOF. If a read error occurs, the error indicator is set and fgetc returns EOF.

Entry no. 102: char *fgets(char *s, int n, FILE *stream)

Reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a newline character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array.

Returns: s if successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned. If a read error occurs during the operation, the array contents are indeterminate and a null pointer is returned.

Entry no. 103: int fputc(int c, FILE *stream)

Writes the character specified by c (converted to an unsigned char) to the output stream pointed to by stream, at the position indicated by the associated file position indicator (if defined), and advances the indicator appropriately. If the file cannot support positioning requests, or if the stream was opened with append mode, the character is appended to the output stream.

Returns: the character written. If a write error occurs, the error indicator is set and fputc returns EOF.

Entry no. 104: int fputs(const char *s, FILE *stream)

Writes the string pointed to by s to the stream pointed to by stream. The terminating null character is not written.

Returns: EOF if a write error occurs; otherwise it returns a non-negative value.

Entry no. 106: int getc(FILE *stream)

Equivalent to fgetc except that it may be (and is under RISC OS) implemented as a macro. stream may be evaluated more than once, so the argument should never be an expression with side effects.

Returns: the next character from the input stream pointed to by stream. If the stream is at end-of-file, the end-of-file indicator is set and getc returns EOF. If a read error occurs, the error indicator is set and getc returns EOF.

Entry no. 107: int getchar(void)

Equivalent to getc with the argument stdin.

Returns: the next character from the input stream pointed to by stdin. If the stream is at end-of-file, the end-of-file indicator is set and getchar returns EOF. If a read error occurs, the error indicator is set and getchar returns EOF.

Entry no. 108: char *gets(char *s)

Reads characters from the input stream pointed to by stdin into the array pointed to by s, until end-of-file is encountered or a newline character is read. Any newline character is discarded, and a null character is written immediately after the last character read into the array.

Returns: s if successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned. If a read error occurs during the operation, the array contents are indeterminate and a null pointer is returned.

Entry no. 110: int putc(int c, FILE *stream)

Equivalent to fputc except that it may be (and is under RISC OS) implemented as a macro. stream may be evaluated more than once, so the argument should never be an expression with side effects.

Returns: the character written. If a write error occurs, the error indicator is set and putc returns EOF.

Entry no. 111: int putchar(int c)

Equivalent to putc with the second argument stdout.

Returns: the character written. If a write error occurs, the error indicator is set and putc returns EOF.

Entry no. 112: int puts(const char *s)

Writes the string pointed to by s to the stream pointed to by stdout, and appends a newline character to the output. The terminating null character is not written.

Returns: EOF if a write error occurs; otherwise it returns a non-negative value.

Entry no. 113: int ungetc(int c, FILE *stream)

Pushes the character specified by c (converted to an unsigned char) back onto the input stream pointed to by stream. The character will be returned by the next read on that stream. An intervening call to the fflush function or to a file positioning function (fseek, fsetpos, rewind) discards any pushed-back characters. The external storage corresponding to the stream is unchanged. One character pushback is guaranteed. If the unget function is called too many times on the same stream without an intervening read or file positioning operation on that stream, the operation may fail. If the value of c equals that of the macro EOF, the operation fails and the input stream is unchanged.

A successful call to the ungetc function clears the end-of-file indicator. The value of the file position indicator after reading or discarding all pushed-back characters will be the same as it was before the characters were pushed back. For a text stream, the value of the file position indicator after a successful call to the ungetc function is unspecified until all pushed-back characters are read or discarded. For a binary stream, the file position indicator is decremented by each successful call to the ungetc function; if its value was zero before a call, it is indeterminate after the call.

Returns: the character pushed back after conversion, or EOF if the operation fails.

Entry no. 114: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

Reads into the array pointed to by ptr, up to nmemb members whose size is specified by size, from the stream pointed to by stream. The file position indicator (if defined) is advanced by the number of characters successfully read. If an error occurs, the resulting value of the file position indicator is indeterminate. If a partial member is read, its value is indeterminate. The ferror or feof function shall be used to distinguish between a read error and end-of-file.

Returns: the number of members successfully read, which may be less than nmemb if a read error or end-of-file is encountered. If size or nmemb is zero, fread returns zero and the contents of the array and the state of the stream remain unchanged.

Entry no. 115: size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

Writes, from the array pointed to by ptr up to nmemb members whose size is specified by size, to the stream pointed to by stream. The file position indicator (if defined) is advanced by the number of characters successfully written. If an error occurs, the resulting value of the file position indicator is indeterminate.

Returns: the number of members successfully written, which will be less than nmemb only if a write error is encountered.

Entry no. 116: int fgetpos(FILE *stream, fpos_t *pos)

Stores the current value of the file position indicator for the stream pointed to by stream in the object pointed to by pos. The value stored contains unspecified information usable by the fsetpos function for repositioning the stream to its position at the time of the call to the fgetpos function.

Returns: zero, if successful. Otherwise non-zero is returned and the integer expression errno is set to an implementation-defined non-zero value (under RISC OS fgetpos cannot fail).

Entry no. 117: int fseek(FILE *stream, long int offset, int whence)

Sets the file position indicator for the stream pointed to by stream. For a binary stream, the new position is at the signed number of characters specified by offset away from the point specified by whence. The specified point is the beginning of the file for SEEK_SET, the current position in the file for SEEK_CUR, or end-of-file for SEEK_END. A binary stream need not meaningfully support fseek calls with a whence value of SEEK_END, though the Acorn implementation does. For a text stream, offset is either zero or a value returned by an earlier call to the ftell function on the same stream; whence is then SEEK_SET. The Acorn implementation also allows a text stream to be positioned in exactly the same manner as a binary stream, but this is not portable. The fseek function clears the end-of-file indicator and undoes any effects of the ungetc function on the same stream. After an fseek call, the next operation on an update stream may be either input or output.

Returns: non-zero only for a request that cannot be satisfied.

Entry no. 118: int fsetpos(FILE *stream, const fpos_t *pos)

Sets the file position indicator for the stream pointed to by stream according to the value of the object pointed to by pos, which is a value returned by an earlier call to the fgetpos function on the same stream. The fsetpos function clears the end-of-file indicator and undoes any effects of the ungetc function on the same stream. After an fsetpos call, the next operation on an update stream may be either input or output.

Returns: zero, if successful. Otherwise non-zero is returned and the integer expression errno is set to an implementation-defined non-zero value (under RISC OS the value is that of EDOM in math.h).

Entry no. 119: long int ftell(FILE *stream)

Obtains the current value of the file position indicator for the stream pointed to by stream. For a binary stream, the value is the number of characters from the beginning of the file. For a text stream, the file position indicator contains unspecified information, usable by the fseek function for returning the file position indicator to its position at the time of the ftell call; the difference between two such return values is not necessarily a meaningful measure of the number of characters written or read. However, for the Acorn implementation, the value returned is merely the byte offset into the file, whether the stream is text or binary.

Returns: if successful, the current value of the file position indicator. On failure, the ftell function returns -1L and sets the integer expression errno to an implementation-defined non-zero value (under RISC OS ftell cannot fail).

Entry no. 120: void rewind(FILE *stream)

Sets the file position indicator for the stream pointed to by stream to the beginning of the file. It is equivalent to (void)fseek(stream, 0L, SEEK_SET) except that the error indicator for the stream is also cleared.

Returns: no value.

Entry no. 121: void clearerr(FILE *stream)

Clears the end-of-file and error indicators for the stream pointed to by stream. These indicators are cleared only when the file is opened or by an explicit call to the clearerr function or to the rewind function.

Returns: no value.

Entry no. 122: int feof(FILE *stream)

Tests the end-of-file indicator for the stream pointed to by stream.

Returns: non-zero if the end-of-file indicator is set for stream.

Entry no. 123: int ferror(FILE *stream)

Tests the error indicator for the stream pointed to by stream.

Returns: non-zero if the error indicator is set for stream.

Entry no. 124: void perror(const char *s)

Maps the error number in the integer expression errno to an error message. It writes a sequence of characters to the standard error stream thus: first (if s is not a null pointer and the character pointed to by s is not the null character), the string pointed to by s followed by a colon and a space; then an appropriate error message string followed by a newline character. The contents of the error message strings are the same as those returned by the strerror function with argument errno, which are implementation-defined.

Returns: no value.

Entry no. 105: int __filbuf(FILE *stream)

This function is used by the C library to implement the 'getc' macro. The definition of the 'getc' macro is as follows:

#define getc(p) \
    (--((p)->__icnt) >= 0 ? *((p)->__ptr)++ : __filbuf(p))

where p is a pointer to a FILE structure.

__filbuf fills the buffer associated with p from a file stream and returns the first character of the buffer incrementing the buffer pointer and decrementing the input character count.

Entry no. 109: int __flsbuf(int ch, FILE *stream)

This function is used by the C library to implement the putc macro. The definition of the putc macro is as follows:

#define putc(ch, p) \
    (--((p)->__ocnt) >= 0 ? (*((p)->__ptr)++ = (ch)) : __flsbuf(ch,p))

where p is a pointer to a FILE structure.

__flsbuf flushes the buffer associated with p to a file stream and writes the character ch to the file stream. The buffer pointer and output character count are reset.

stdlib

stdlib provides several general purpose functions

Entry no. 58: double atof(const char *nptr)

Converts the initial part of the string pointed to by nptr to double * representation.

Returns: the converted value.

Entry no. 59: int atoi(const char *nptr)

Converts the initial part of the string pointed to by nptr to int representation.

Returns: the converted value.

Entry no. 60: long int atol(const char *nptr)

Converts the initial part of the string pointed to by nptr to long int representation.

Returns: the converted value.

Entry no. 61: double strtod(const char *nptr, char **endptr)

Converts the initial part of the string pointed to by nptr to double representation. First it decomposes the input string into three parts: an initial, possibly empty, sequence of white-space characters (as specified by the isspace function), a subject sequence resembling a floating point constant, and a final string of one or more unrecognised characters, including the terminating null character of the input string. It then attempts to convert the subject sequence to a floating point number, and returns the result. A pointer to the final string is stored in the object pointed to by endptr, provided that endptr is not a null pointer.

Returns: the converted value if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, plus or minus HUGE_VAL is returned (according to the sign of the value), and the value of the macro ERANGE is stored in errno. If the correct value would cause underflow, zero is returned and the value of the macro ERANGE is stored in errno.

Entry no. 62: long int strtol(const char *nptr, char **endptr, int base)

Converts the initial part of the string pointed to by nptr to long int representation. First it decomposes the input string into three parts: an initial, possibly empty, sequence of white-space characters (as specified by the isspace function), a subject sequence resembling an integer represented in some radix determined by the value of base, and a final string of one or more unrecognised characters, including the terminating null character of the input string.

It then attempts to convert the subject sequence to an integer, and returns the result. If the value of base is 0, the expected form of the subject sequence is that of an integer constant (described precisely in the ANSI standard, section 3.1.3.2), optionally preceded by a + or - sign, but not including an integer suffix. If the value of base is between 2 and 36, the expected form of the subject sequence is a sequence of letters and digits representing an integer with the radix specified by base, optionally preceded by a plus or minus sign, but not including an integer suffix. The letters from a (or A) through z (or Z) are ascribed the values 10 to 35; only letters whose ascribed values are less than that of the base are permitted. If the value of base is 16, the characters 0x or 0X may optionally precede the sequence of letters and digits following the sign if present. A pointer to the final string is stored in the object pointed to by endptr, provided that endptr is not a null pointer.

Returns: the converted value if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, LONG_MAX or LONG_MIN is returned (according to the sign of the value), and the value of the macro ERANGE is stored in errno.

Entry no. 63: unsigned long int strtoul(const char *nptr, char **endptr, int base)

Converts the initial part of the string pointed to by nptr to unsigned long int representation. First it decomposes the input string into three parts: an initial, possibly empty, sequence of white space characters (as determined by the isspace function), a subject sequence resembling an unsigned integer represented in some radix determined by the value of base, and a final string of one or more unrecognised characters, including the terminating null character of the input string.

It then attempts to convert the subject sequence to an unsigned integer, and returns the result. If the value of base is zero, the expected form of the subject sequence is that of an integer constant (described precisely in the ANSI Standard, section 3.1.3.2), optionally preceded by a + or - sign, but not including an integer suffix. If the value of base is between 2 and 36, the expected form of the subject sequence is a sequence of letters and digits representing an integer with the radix specified by base, optionally preceded by a + or - sign, but not including an integer suffix. The letters from a (or A) through z (or Z) stand for the values 10 to 35; only letters whose ascribed values are less than that of the base are permitted. If the value of base is 16, the characters 0x or 0X may optionally precede the sequence of letters and digits following the sign, if present. A pointer to the final string is stored in the object pointed to by endptr, provided that endptr is not a null pointer.

Returns: the converted value if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, ULONG_MAX is returned, and the value of the * macro ERANGE is stored in errno.

Entry no. 64: int rand(void)

Computes a sequence of pseudo-random integers in the range 0 to RAND_MAX, where RAND_MAX = 0x7fffffff.

Returns: a pseudo-random integer.

Entry no. 65: void srand(unsigned int seed)

Uses its argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand. If srand is then called with the same seed value, the sequence of pseudo-random numbers will be repeated. If rand is called before any calls to srand have been made, the same sequence is generated as when srand is first called with a seed value of 1.

Entry no. 66: void *calloc(size_t nmemb, size_t size)

Allocates space for an array of nmemb objects, each of whose size is size. The space is initialised to all bits zero.

Returns: either a null pointer or a pointer to the allocated space.

Entry no. 67: void free(void *ptr)

Causes the space pointed to by ptr to be deallocated (made available for further allocation). If ptr is a null pointer, no action occurs. Otherwise, if ptr does not match a pointer earlier returned by calloc, malloc or realloc or if the space has been deallocated by a call to free or realloc, the behaviour is undefined.

Entry no. 68: void *malloc(size_t size)

Allocates space for an object whose size is specified by size and whose value is indeterminate.

Returns: either a null pointer or a pointer to the allocated space.

Entry no. 69: void *realloc(void *ptr, size_t size)

Changes the size of the object pointed to by ptr to the size specified by size. The contents of the object is unchanged up to the lesser of the new and old sizes. If the new size is larger, the value of the newly allocated portion of the object is indeterminate. If ptr is a null pointer, the realloc function behaves like a call to malloc for the specified size. Otherwise, if ptr does not match a pointer earlier returned by calloc, malloc or realloc, or if the space has been deallocated by a call to free or realloc, the behaviour is undefined. If the space cannot be allocated, the object pointed to by ptr is unchanged. If size is zero and ptr is not a null pointer, the object it points to is freed.

Returns: either a null pointer or a pointer to the possibly moved allocated space.

Entry no. 70: void abort(void)

Causes abnormal program termination to occur, unless the signal SIGABRT is being caught and the signal handler does not return. Whether open output streams are flushed or open streams are closed or temporary files removed is implementation-defined (under RISC OS all these occur). An implementation-defined form of the status 'unsuccessful termination' (1 under RISC OS) is returned to the host environment by means of a call to raise(SIGABRT).

Entry no. 71: int atexit(void (*func)(void))

Registers the function pointed to by func, to be called without its arguments at normal program termination. It is possible to register at least 32 functions.

Returns: zero if the registration succeeds, non-zero if it fails.

Entry no. 72: void exit(int status)

Causes normal program termination to occur. If more than one call to the exit function is executed by a program (for example, by a function registered with atexit), the behaviour is undefined. First, all functions registered by the atexit function are called, in the reverse order of their registration. Next, all open output streams are flushed, all open streams are closed, and all files created by the tmpfile function are removed. Finally, control is returned to the host environment. If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status 'successful termination' (0 under RISC OS) is returned. If the value of status is EXIT_FAILURE, an implementation-defined form of the status 'unsuccessful termination' (1 under RISC OS) is returned. Otherwise the status returned is implementation-defined (the value of status is returned under RISC OS).

Entry no. 73: char *getenv(const char *name)

Searches the environment list, provided by the host environment, for a string that matches the string pointed to by name. The set of environment names and the method for altering the environment list are implementation-defined.

Returns: a pointer to a string associated with the matched list member. The array pointed to is not modified by the program, but may be overwritten by a subsequent call to the getenv function. If the specified name cannot be found, a null pointer is returned.

Entry no. 74: int system(const char *string)

Passes the string pointed to by string to the host environment to be executed by a command processor in an implementation-defined manner. A null pointer may be used for string, to inquire whether a command processor exists. Under RISC OS, care must be taken, when executing a command, that the command does not overwrite the calling program. To control this, the string chain: or call: may immediately precede the actual command. The effect of call: is the same as if call: were not present. When a command is called, the caller is first moved to a safe place in application workspace. When the callee terminates, the caller is restored. This requires enough memory to hold caller and callee simultaneously. When a command is chained, the caller may be overwritten. If the caller is not overwritten, the caller exits when the callee terminates. Thus a transfer of control is effected and memory requirements are minimised.

Returns: If the argument is a null pointer, the system function returns non-zero only if a command processor is available. If the argument is not a null pointer, it returns an implementation-defined value (under RISC OS 0 is returned for success and -2 for failure to invoke the command; any other value is the return code from the executed command).

Entry no. 75: void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *))

Searches an array of nmemb objects, the initial member of which is pointed to by base, for a member that matches the object pointed to by key. The size of each member of the array is specified by size. The contents of the array must be in ascending sorted order according to a comparison function pointed to by compar, which is called with two arguments that point to the key object and to an array member, in that order. The function returns an integer less than, equal to, or greater than zero if the key object is considered, respectively, to be less than, to match, or to be greater than the array member.

Returns: a pointer to a matching member of the array, or a null pointer if no match is found. If two members compare as equal, which member is matched is unspecified.

Entry no. 76: void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))

Sorts an array of nmemb objects, the initial member of which is pointed to by base. The size of each object is specified by size. The contents of the array are sorted in ascending order according to a comparison function pointed to by compar, which is called with two arguments that point to the objects being compared. The function returns an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second. If two members compare as equal, their order in the sorted array is unspecified.

Entry no. 77: int abs(int j)

Computes the absolute value of an integer j. If the result cannot be represented, the behaviour is undefined.

Returns: the absolute value.

Entry no. 78: div_t div(int numer, int denom)

Computes the quotient and remainder of the division of the numerator numer by the denominator denom. If the division is inexact, the resulting quotient is the integer of lesser magnitude that is the nearest to the algebraic quotient. If the result cannot be represented, the behaviour is undefined; otherwise, quot * denom + rem equals numer.

Returns: a structure of type div_t, comprising both the quotient and the remainder. The structure contains the following members: int quot; int rem. You may not rely on their order.

Entry no. 79: long int labs(long int j)

Computes the absolute value of an long integer j. If the result cannot be represented, the behaviour is undefined.

Returns: the absolute value.

Entry no. 80: ldiv_t ldiv(long int numer, long int denom)

Computes the quotient and remainder of the division of the numerator numer by the denominator denom. If the division is inexact, the sign of the resulting quotient is that of the algebraic quotient, and the magnitude of the resulting quotient is the largest integer less than the magnitude of the algebraic quotient. If the result cannot be represented, the behaviour is undefined; otherwise, quot * denom + rem equals numer.

Returns: a structure of type ldiv_t, comprising both the quotient and the remainder. The structure contains the following members: long int quot; long int rem. You may not rely on their order.

Multibyte character functions

The behaviour of the multibyte character functions is affected by the LC_CTYPE category of the current locale. For a state-dependent encoding, each function is placed into its initial state by a call for which its character pointer argument, s, is a null pointer. Subsequent calls with s as other than a null pointer cause the internal state of the function to be altered as necessary. A call with s as a null pointer causes these functions to return a non-zero value if encoding have state dependency, and a zero otherwise. After the LC_CTYPE category is changed, the shift state of these functions is indeterminate.

Entry no. 172: int mblen(const char *s, size_t n)

If s is not a null pointer, the mblen function determines the number of bytes comprising the multibyte character pointed to by s. Except that the shift state of the mbtowc function is not affected, it is equivalent to mbtowc((wchar_t *)0, s, n).

Returns: If s is a null pointer, the mblen function returns a non-zero or zero value, if multibyte character encodings, respectively do or do not have state-dependent encodings. If s is not a null pointer, the mblen function either returns a 0 (if s points to a null character), or returns the number of bytes that comprise the multibyte character (if the next n or fewer bytes form a valid multibyte character), or returns -1 (if they do not form a valid multibyte character).

Entry no. 173: int mbtowc(wchar_t *pwc, const char *s, size_t n)

If s is not a null pointer, the mbtowc function determines the number of bytes that comprise the multibyte character pointed to by s. It then determines the code for value of type wchar_t that corresponds to that multibyte character. (The value of the code corresponding to the null character is zero). If the multibyte character is valid and pwc is not a null pointer, the mbtowc function stores the code in the object pointed to by pwc. At most n bytes of the array pointed to by s will be examined.

Returns: If s is a null pointer, the mbtowc function returns a non-zero or zero value, if multibyte character encodings, respectively do or do not have state-dependent encodings. If s is not a null pointer, the mbtowc function either returns a 0 (if s points to a null character), or returns the number of bytes that comprise the converted multibyte character (if the next n of fewer bytes form a valid multibyte character), or returns -1 (if they do not form a valid multibyte character).

Entry no. 174: int wctomb(char *s, wchar_t wchar)

Determines the number of bytes need to represent the multibyte character corresponding to the code whose value is wchar (including any change in shift state). It stores the multibyte character representation in the array object pointed to by s (if s is not a null pointer). At most MB_CUR_MAX characters are stored. If the value of wchar is zero, the wctomb function is left in the initial shift state).

Returns: If s is a null pointer, the wctomb function returns a non-zero or zero value, if multibyte character encodings, respectively do or do not have state-dependent encodings. If s is not a null pointer, the wctomb function returns a -1 if the value of wchar does not correspond to a valid multibyte character, or returns the number of bytes that comprise the multibyte character corresponding to the value of wchar.

Multibyte string functions

The behaviour of the multibyte string functions is affected by the LC_CTYPE category of the current locale.

Entry no. 175: size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n)

Converts a sequence of multibyte characters that begins in the initial shift state from the array pointed to by s into a sequence of corresponding codes and stores not more than n codes into the array pointed to by pwcs. No multibyte character that follows a null character (which is converted into a code with value zero) will be examined or converted. Each multibyte character is converted as if by a call to the mbtowc function. If an invalid multibyte character is found, mbstowcs returns (size_t)-1. Otherwise, the mbstowcs function returns the number of array elements modified, not including a terminating zero code, if any.

Entry no. 176: size_t wcstombs(char *s, const wchar_t *pwcs, size_t n)

Converts a sequence of codes that correspond to multibyte characters from the array pointed to by pwcs into a sequence of multibyte characters that begins in the initial shift state and stores these multibyte characters into the array pointed to by s, stopping if a multibyte character would exceed the limit of n total bytes or if a null character is stored. Each code is converted as if by a call to the wctomb function, except that the shift state of the wctomb function is not affected. If a code is encountered which does not correspond to any valid multibyte character, the wcstombs function returns (size_t)-1. Otherwise, the wcstombs function returns the number of bytes modified, not including a terminating null character, if any.

string

string provides several functions useful for manipulating character arrays and other objects treated as character arrays. Various methods are used for determining the lengths of the arrays, but in all cases a char * or void * argument points to the initial (lowest addresses) character of the array. If an array is written beyond the end of an object, the behaviour is undefined.

Entry no. 38: void *memcpy(void *s1, const void *s2, size_t n)

Copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behaviour is undefined.

Returns: the value of s1.

Entry no. 39: void *memmove(void *s1, const void *s2, size_t n)

Copies n characters from the object pointed to by s2 into the object pointed to by s1. Copying takes place as if the n characters from the object pointed to by s2 are first copied into a temporary array of n characters that does not overlap the objects pointed to by s1 and s2, and then the n characters from the temporary array are copied into the object pointed to by s1.

Returns: the value of s1.

Entry no. 40: char *strcpy(char *s1, const char *s2)

Copies the string pointed to by s2 (including the terminating null character) into the array pointed to by s1. If copying takes place between objects that overlap, the behaviour is undefined.

Returns: the value of s1.

Entry no. 41: char *strncpy(char *s1, const char *s2, size_t n)

Copies not more than n characters (characters that follow a null character are not copied) from the array pointed to by s2 into the array pointed to by s1. If copying takes place between objects that overlap, the behaviour is undefined. If terminating nul has not been copied in chars, no term nul is placed in s2.

Returns: the value of s1.

Entry no. 42: char *strcat(char *s1, const char *s2)

Appends a copy of the string pointed to by s2 (including the terminating null character) to the end of the string pointed to by s1. The initial character of s2 overwrites the null character at the end of s1.

Returns: the value of s1.

Entry no. 43: char *strncat(char *s1, const char *s2, size_t n)

Appends not more than n characters (a null character and characters that follow it are not appended) from the array pointed to by s2 to the end of the string pointed to by s1. The initial character of s2 overwrites the null character at the end of s1. A terminating null character is always appended to the result.

Returns: the value of s1.

The sign of a non-zero value returned by the comparison functions is determined by the sign of the difference between the values of the first pair of characters (both interpreted as unsigned char) that differ in the objects being compared.

Entry no. 44: int memcmp(const void *s1, const void *s2, size_t n)

Compares the first n characters of the object pointed to by s1 to the first n characters of the object pointed to by s2.

Returns: an integer greater than, equal to, or less than zero, depending on whether the object pointed to by s1 is greater than, equal to, or less than the object pointed to by s2.

Entry no. 45: int strcmp(const char *s1, const char *s2)

Compares the string pointed to by s1 to the string pointed to by s2.

Returns: an integer greater than, equal to, or less than zero, depending on whether the string pointed to by s1 is greater than, equal to, or less than the string pointed to by s2.

Entry no. 46: int strncmp(const char *s1, const char *s2, size_t n)

Compares not more than n characters (characters that follow a null character are not compared) from the array pointed to by s1 to the array pointed to by s2.

Returns: an integer greater than, equal to, or less than zero, depending on whether the string pointed to by s1 is greater than, equal to, or less than the string pointed to by s2.

Entry no. 178: int strcoll(const char *s1, const char *s2)

Compares the string pointed to by s1 to the string pointed to by s2, both interpreted as appropriate to the LC_COLLATE category of the current locale.

Returns: an integer greater than, equal to, or less than zero, depending on whether the string pointed to by s1 is greater than, equal to, or less than the string pointed to by s2 when both are interpreted as appropriate to the current locale.

Entry no. 177: size_t strxfrm(char *s1, const char *s2, size_t n)

Transforms the string pointed to by s2 and places the resulting string into the array pointed to by s1. The transformation function is such that if the strcmp function is applied to two transformed strings, it returns a value greater than, equal to or less than zero, corresponding to the result of the strcoll function applied to the same two original strings. No more than n characters are placed into the resulting array pointed to by s1, including the terminating null character. If n is zero, s1 is permitted to be a null pointer. If copying takes place between objects that overlap, the behaviour is undefined.

Under RISC OS 3 (version 3.10) this function only works for the default ANSI locale, but not for other locales (ie not after a setlocale call).

Returns: The length of the transformed string is returned (not including the terminating null character). If the value returned is n or more, the contents of the array pointed to by s1 are indeterminate.

Entry no. 47: void *memchr(const void *s, int c, size_t n)

Locates the first occurrence of c (converted to an unsigned char) in the initial n characters (each interpreted as unsigned char) of the object pointed to by s.

Returns: a pointer to the located character, or a null pointer if the character does not occur in the object.

Entry no. 48: char *strchr(const char *s, int c)

Locates the first occurrence of c (converted to a char) in the string pointed to by s (including the terminating null character). The BSD UNIX name for this function is index().

Returns: a pointer to the located character, or a null pointer if the character does not occur in the string.

Entry no. 49: size_t strcspn(const char *s1, const char *s2)

Computes the length of the initial segment of the string pointed to by s1 which consists entirely of characters not from the string pointed to by s2. The terminating null character is not considered part of s2.

Returns: the length of the segment.

Entry no. 50: char *strpbrk(const char *s1, const char *s2)

Locates the first occurrence in the string pointed to by s1 of any character from the string pointed to by s2.

Returns: returns a pointer to the character, or a null pointer if no character form s2 occurs in s1.

Entry no. 51: char *strrchr(const char *s, int c)

Locates the last occurrence of c (converted to a char) in the string pointed to by s. The terminating null character is considered part of the string. The BSD UNIX name for this function is rindex().

Returns: a pointer to the character, or a null pointer if c does not occur in the string.

Entry no. 52: size_t strspn(const char *s1, const char *s2)

Computes the length of the initial segment of the string pointed to by s1 which consists entirely of characters from the string pointed to by s2.

Returns: the length of the segment.

Entry no. 53: char *strstr(const char *s1, const char *s2)

Locates the first occurrence in the string pointed to by s1 of the sequence of characters (excluding the terminating null character) in the string pointed to by s2.

Returns: a pointer to the located string, or a null pointer if the string is not found.

Entry no. 54: char *strtok(char *s1, const char *s2)

A sequence of calls to the strtok function breaks the string pointed to by s1 into a sequence of tokens, each of which is delimited by a character from the string pointed to by s2. The first call in the sequence has s1 as its first argument, and is followed by calls with a null pointer as their first argument. The separator string pointed to by s2 may be different from call to call. The first call in the sequence searches for the first character that is not contained in the current separator string s2. If no such character is found, then there are no tokens in s1 and the strtok function returns a null pointer. If such a character is found, it is the start of the first token. The strtok function then searches from there for a character that is contained in the current separator string. If no such character is found, the current token extends to the end of the string pointed to by s1, and subsequent searches for a token will fail. If such a character is found, it is overwritten by a null character, which terminates the current token. The strtok function saves a pointer to the following character, from which the next search for a token will start. Each subsequent call, with a null pointer as the value for the first argument, starts searching from the saved pointer and behaves as described above.

Returns: pointer to the first character of a token, or a null pointer if there is no token.

Entry no. 55: void *memset(void *s, int c, size_t n)

Copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s.

Returns: the value of s.

Entry no. 56: char *strerror(int errnum)

Maps the error number in errnum to an error message string.

Returns: a pointer to the string, the contents of which are implementation-defined. Under RISC OS and Arthur the strings for the given errnums are as follows:

0 No error (errno = 0)
EDOM function argument out of range
ERANGE function result not representable
ESIGNUM illegal signal number to signal() or raise()
others Error code (errno) has no associated message.

The array pointed to may not be modified by the program, but may be overwritten by a subsequent call to the strerror function.

Entry no. 57: size_t strlen(const char *s)

Computes the length of the string pointed to by s.

Returns: the number of characters that precede the terminating null character.

time

time provides several functions for manipulating time. Many functions deal with a calendar time that represents the current date (according to the Gregorian calendar) and time. Some functions deal with local time, which is the calendar time expressed for some specific time zone, and with Daylight Saving Time, which is a temporary change in the algorithm for determining local time.

struct tm holds the components of a calendar time called the broken-down time. The value of tm_isdst is positive if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and negative if the information is not available.

struct tm {
  int tm_sec;    /* seconds after the minute, 0 to 60
                    (0-60 allows for the occasional leap
                    second) */
  int tm_min     /* minutes after the hour, 0 to 59 */
  int tm_hour    /* hours since midnight, 0 to 23 */
  int tm_mday    /* day of the month, 0 to 31 */
  int tm_mon     /* months since January, 0 to 11 */
  int tm_year    /* years since 1900 */
  int tm_wday    /* days since Sunday, 0 to 6 */
  int tm_yday    /* days since January 1, 0 to 365 */
  int tm_isdst   /* Daylight Saving Time flag */
};

Entry no. 29: clock_t clock(void)

Determines the processor time used.

Returns: the implementation's best approximation to the processor time used by the program since program invocation. The time in seconds is the value returned, divided by the value of the macro CLOCKS_PER_SEC. The value (clock_t)-1 is returned if the processor time used is not available. In the desktop, clock() returns all processor time, not just that of the program.

Entry no. 30: double difftime(time_t time1, time_t time0)

Computes the difference between two calendar times: time1 - time0. Returns: the difference expressed in seconds as a double.

Entry no. 31: time_t mktime(struct tm *timeptr)

Converts the broken-down time, expressed as local time, in the structure pointed to by timeptr into a calendar time value with the same encoding as that of the values returned by the time function. The original values of the tm_wday and tm_yday components of the structure are ignored, and the original values of the other components are not restricted to the ranges indicated above. On successful completion, the values of the tm_wday and tm_yday structure components are set appropriately, and the other components are set to represent the specified calendar time, but with their values forced to the ranges indicated above; the final value of tm_mday is not set until tm_mon and tm_year are determined.

Returns: the specified calendar time encoded as a value of type time_t. If the calendar time cannot be represented, the function returns the value (time_t)-1.

Entry no. 32: time_t time(time_t *timer)

Determines the current calendar time. The encoding of the value is unspecified.

Returns: the implementation's best approximation to the current calendar time. The value (time_t)-1 is returned if the calendar time is not available. If timer is not a null pointer, the return value is also assigned to the object it points to.

Entry no. 33: char *asctime(const struct tm *timeptr)

Converts the broken-down time in the structure pointed to by timeptr into a string in the style Sun Sep 16 01:03:52 1973\n\0.

Returns: a pointer to the string containing the date and time.

Entry no. 34: char *ctime(const time_t *timer)

Converts the calendar time pointed to by timer to local time in the form of a string. It is equivalent to asctime(localtime(timer)).

Returns: the pointer returned by the asctime function with that broken-down time as argument.

Entry no. 35: struct tm *gmtime(const time_t *timer)

Converts the calendar time pointed to by timer into a broken-down time, expressed as Greenwich Mean Time (GMT).

Returns: a pointer to that object or a null pointer if GMT is not available.

Entry no. 36: struct tm *localtime(const time_t *timer)

Converts the calendar time pointed to by timer into a broken-down time, expressed a local time.

Returns: a pointer to that object.

Entry no. 37: size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)

Places characters into the array pointed to by s as controlled by the string pointed to by format. The format string consists of zero or more directives and ordinary characters. A directive consists of a % character followed by a character that determines the directive's behaviour. All ordinary characters (including the terminating null character) are copied unchanged into the array. No more than maxsize characters are placed into the array. Each directive is replaced by appropriate characters as described in the following list. The appropriate characters are determined by the LC_TIME category of the current locale and by the values contained in the structure pointed to by timeptr.

Directive Replaced by
%a the locale's abbreviated weekday name
%A the locale's full weekday name
%b the locale's abbreviated month name
%B the locale's full month name
%c the locale's appropriate date and time representation
%d the day of the month as a decimal number (01 - 31)
%H the hour (24-hour clock) as a decimal number (00 - 23)
%I the hour (12-hour clock) as a decimal number (01 - 12)
%j the day of the year as a decimal number (001 - 366)
%m the month as a decimal number (01 - 12)
%M the minute as a decimal number (00 - 61)
%p the locale's equivalent of either AM or PM designation associated with a 12-hour clock
%S the second as a decimal number (00 - 61)
%U the week number of the year (Sunday as the first day of week 1) as a decimal number (00 - 53)
%w the weekday as a decimal number (0 (Sunday) - 6)
%W the week number of the year (Monday as the first day of week 1) as a decimal number (00 - 53)
%x the locale's appropriate date representation
%X he locale's appropriate time representation
%y the year without century as a decimal number (00 - 99)
%Y the year with century as a decimal number
%Z the time zone name or abbreviation, or by no character if no time zone is determinable
%% %

If a directive is not one of the above, the behaviour is undefined.

Returns: If the total number of resulting characters including the terminating null character is not more than maxsize, the strftime function returns the number of characters placed into the array pointed to by s not including the terminating null character. Otherwise, zero is returned and the contents of the array are indeterminate.

This edition Copyright © 3QD Developments Ltd 2015
Last Edit: Tue,03 Nov 2015