Keil™, An ARM® Company

RealView Libraries and Floating Point Support Guide

Technical Support

On-Line Manuals

RealView Libraries and Floating Point Support Guide

Preface
Introduction
The C and C++ Libraries
About the C and C++ libraries
Features of the C and C++ libraries
Namespaces
Writing reentrant and thread‑safe code
Introduction to reentrancy and thread‑safety
Use of static data in the C libraries
The __user_libspace static data area
Managing locks in multithreaded applications
Using the ARM C libraries with a multithreaded app
Thread‑safety in the ARM C libraries
Thread‑safety in the ARM C++ libraries
Building an application with the C library
Using the libraries with an application
Building an application for a semihosted environme
Building an application for a non semihosting envi
Building an application without the C library
Integer and FP helper functions
Bare machine integer C
Bare machine C with floating‑point
Exploiting the C library
The standalone C library functions
Tailoring the C library to a new execution environ
How C and C++ programs use the library functions
__rt_entry
Exiting from the program
__rt_exit()
__rt_lib_init()
__rt_lib_shutdown()
Tailoring static data access
Tailoring locale and CTYPE using assembler macros
Selecting locale at link time
Selecting locale at runtime
Defining a locale block
LC_CTYPE data block
LC_COLLATE data block
LC_MONETARY data block
LC_NUMERIC data block
LC_TIME data block
_get_lconv()
localeconv()
setlocale()
_findlocale()
The lconv structure
Tailoring locale and CTYPE using C macros
Selecting locale at link time
Selecting locale at runtime
Macros and utility functions
_get_lc_ctype()
_get_lc_collate()
_get_lc_monetary()
_get_lc_numeric()
_get_lc_time()
_get_lconv()
localeconv()
setlocale()
_findlocale()
__LC_CTYPE_DEF
__LC_COLLATE_DEF
__LC_TIME_DEF
__LC_NUMERIC_DEF
__LC_MONETARY_DEF
__LC_INDEX_END
The lconv structure
Tailoring error signaling, error handling, and pro
_sys_exit()
errno
__rt_errno_addr()
__raise()
__rt_raise()
__default_signal_handler()
_ttywrch()
__rt_fp_status_addr()
Tailoring storage management
Avoiding the ARM‑supplied heap and heap‑using
Support for malloc
Tailoring the runtime memory model
The memory models
Controlling the runtime memory model
Writing your own memory model
__user_initial_stackheap()
__user_setup_stackheap()
__user_heap_extend()
__user_heap_extent()
__user_stack_cleanup_space()
__rt_heap_extend()
__rt_stack_postlongjmp()
Tailoring the input/output functions
Dependencies on low‑level functions
Target‑dependent input/output support functions
_sys_open()
_sys_close()
_sys_read()
_sys_write()
_sys_ensure()
_sys_flen()
_sys_seek()
_sys_istty()
_sys_tmpnam()
_sys_command_string()
#pragma import(_main_redirection)
Tailoring other C library functions
clock()
_clock_init()
time()
remove()
rename()
system()
getenv()
_getenv_init()
Selecting real‑time division
ISO implementation definition
ISO C library implementation definition
Standard C++ library implementation definition
C library extensions
atoll()
strtoll()
strtoull()
printf()
snprintf()
vsnprintf()
lldiv()
llabs()
wcstombs()
alloca()
strlcpy()
strlcat()
_fisatty()
__heapstats()
__heapvalid()
Library naming conventions
Placing ARM libraries
Helper libraries
Identifying library variants
The C Micro-library
Floating‑point Support

Dependencies on low‑level functions

2.12.1. Dependencies on low‑level functions

Table 2.13 shows the dependencies of the higher‑level functions on lower‑level functions. If you define your own versions of the lower‑level functions, you can use the library versions of the higher‑level functions directly. fgetc() uses __FILE, but fputc() uses __FILE and ferror().

Table 2.13. Input/output dependencies

Low‑level object    High‑level function    
 fprintfprintffwritefputsputsfscanfscanffreadreadfgetsgets
__FILE[1]xxxxxxxxxxx
__stdin[2]xxx
__stdout[3]xx
fputc()[4]xxxxx
ferror()[5]xxx
fgetc()[6]xxxxxx
__backspace()[7]xx

[1] The file structure.

[2] The standard input object of type __FILE.

[3] The standard output object of type __FILE.

[4] Outputs a character to a file.

[5] Returns the error status accumulated during file I/O.

[6] Gets a character from a file.

[7] Moves file pointer to previous character. See Re‑implementing __backspace().

See the ISO C Reference for the syntax of the low‑level functions.

Note

If you choose to re‑implement fgetc(), fputc(), and __backspace(), be aware that fopen() and related functions use the ARM layout for the __FILE structure. You might also need to re-implement fopen() and related functions if you define your own version of __FILE.

printf family

The printf family consists of _printf(), printf(), _fprintf(), fprintf(), vprintf(), and vfprintf(). All these functions use __FILE opaquely and depend only on the functions fputc() and ferror(). The functions _printf() and _fprintf() are identical to printf() and fprintf() except that they cannot format floating‑point values.

The standard output functions of the form _printf(...) are equivalent to:

fprintf(& __stdout, ...)

where __stdout has type __FILE.

scanf family

The scanf() family consists of scanf() and fscanf(). These functions depend only on the functions fgetc(), __FILE, and __backspace(). See Re‑implementing __backspace().

The standard input function of the form scanf(...) is equivalent to:

fscanf(& __stdin, ...)

where __stdin has type __FILE.

fwrite(), fputs, and puts

If you define your own version of __FILE, and your own fputc() and ferror() functions and the __stdout object, you can use all of the printf() family, fwrite(), fputs(), puts() and the C++ object std::cout unchanged from the library. Example 2.24 shows how to do this. Consider modifying the system routines if you require real file handling.

Example 2.24. printf() and __FILE

#include <stdio.h>
struct __FILE
{
    int handle;
    /* Whatever you need here (if the only file you are using
       is the stdoutput using printf for debugging, no file
       handling is required) */
};

FILE __stdout;
int fputc(int ch, FILE *f)
{
    /* Your implementation of fputc */
    return ch;
}
int ferror(FILE *f)
{
    /* Your implementation of ferror */
    return EOF;
}
void test(void)
{
    printf("Hello world\n");  /* This works ... */
}

By default, fread() and fwrite() call fast block input/output functions that are part of the ARM stream implementation. If you define your own __FILE structure instead of using the ARM stream implementation, fread() and fwrite() call fgetc() instead of calling the block input/output functions.

fread(), fgets(), and gets()

The functions fread(), fgets(), and gets() are implemented as a loop over fgetc() and ferror(). Each uses the FILE argument opaquely.

If you provide your own implementation of __FILE, __stdin (for gets()), fgetc(), and ferror(), you can use these functions, and the C++ object std::cin directly from the library.

Re‑implementing __backspace()

The function __backspace() is used by the scanf family of functions. It must never be called directly, but re‑implemented if you are retargeting the stdio arrangements at the fgetc() level.

The semantics are:

int __backspace(FILE *stream);

__backspace(stream) must be called after reading a character from the stream. It returns to the stream the last character that was read from the stream, so that the same character is read from the stream again. This means that a character that was read from the stream by scanf but which is not required (that is, it terminates the scanf operation) is read correctly by the next function that reads from the stream.

__backspace is separate from ungetc(). This is to guarantee that a single character can be pushed back after the scanf family of functions has finished.

The value returned by __backspace() is either 0 (success) or EOF (failure). It returns EOF only if used incorrectly, for example, if no characters have been read from the stream. When used correctly, __backspace() must always return 0, because the scanf family of functions do not check the error return.

The interaction between __backspace() and ungetc() is:

  • If you apply __backspace() to a stream and then ungetc() a character into the same stream, subsequent calls to fgetc() must return first the character returned by ungetc(), and then the one returned by __backspace().

  • If you ungetc() a character back to a stream, then read it with fgetc(), and then backspace it, the next character read by fgetc() must be the same character that was returned to the stream. That is the __backspace() operation must cancel the effect of the fgetc() operation. However, another call to ungetc() after the call to __backspace() is not required to succeed.

  • The situation where you ungetc() a character into a stream and then __backspace() another one immediately, with no intervening read, never arises. __backspace() must only be called after fgetc(), so this sequence of calls is illegal. You can write __backspace() implementations and assume that this does not happen.

Copyright © 2007 ARM Limited. All rights reserved.ARM DUI 0378A