blob: b106079bac7058235c6124dfbaa976b6ac92dd86 [file] [log] [blame]
/* --COPYRIGHT--,ESD
* Copyright (c) 2008 Texas Instruments. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License
* v. 1.0 which accompanies this distribution. The Eclipse Public License is
* available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse
* Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Texas Instruments - initial implementation
* --/COPYRIGHT--*/
/*
* ======== System.xdc ========
*/
package xdc.runtime;
/*!
* ======== System ========
* Basic system services
*
* This module provides basic low-level "system" services; e.g.,
* character output, `printf`-like output, and exit handling.
*
* This module is gated and other modules use its gate via the
* `{@link Gate#enterSystem}` and `{@link Gate#leaveSystem}`. The `System`
* gate must be enterable by any thread in a multi-threaded environments. For
* example, in many real-time multi-threaded environments some types of
* threads, such as Interrupt Service Routines (ISRs), are not allowed to call
* operations that block the caller. In such an environment, either the
* `System` gate must disable all interrupts or ISRs must never call a function
* in the `xdc.runtime` package.
*/
@Template("./System.xdt")
@Gated
@ModuleStartup
@DirectCall
@RomConsts
module System {
/*!
* ======== AtexitHandler ========
* `System`'s atexit function prototype.
*
* Fuctions of this type can be added to the list of functions that
* are executed during application termination.
*
* @see #atexit
*/
typedef Void (*AtexitHandler)(Int);
/*!
* ======== STATUS_UNKNOWN ========
* Unknown exit status value
*
* When the program exits by calling {@link #exit System_exit()} the
* `System`'s `atexit` functions are passed the status value passed to
* `System_exit()`. However, if the program exits using
* the ANSI C Standard Library `exit()` function, the `System`'s `atexit`
* functions are passed `System_STATUS_UNKNOWN`; ANSI C `atexit`
* functions are not passed the exit status.
*/
const Int STATUS_UNKNOWN = 0xCAFE;
/*!
* ======== AbortFxn ========
* System abort function prototype.
*
* Fuctions of this type can be plugged in to `System`'s abort function
* that will be executed during abnormal application termination.
*
* @see #abort
*/
typedef Void (*AbortFxn)();
/*!
* ======== ExitFxn ========
* System exit function prototype.
*
* Fuctions of this type can be plugged in to `System`'s exit function that
* will be executed during normal application termination.
*
* @see #exit
*/
typedef Void (*ExitFxn)(Int);
/*! @_nodoc */
@XmlDtd
metaonly struct Module_View {
String atexitHandlers[];
Int numAtexitHandlers;
};
/*! @_nodoc */
metaonly struct PathEntryView {
String entry;
}
/*!
* ======== rovViewInfo ========
* @_nodoc
*/
@Facet
metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
xdc.rov.ViewInfo.create({
viewMap: [
['XDCROOT',
{
type: xdc.rov.ViewInfo.MODULE_DATA,
viewInitFxn: 'viewInitXdcRoot',
structName: 'PathEntryView'
}
],
['XDCPATH',
{
type: xdc.rov.ViewInfo.MODULE_DATA,
viewInitFxn: 'viewInitXdcPath',
structName: 'PathEntryView'
}
],
]
});
/*!
* ======== A_cannotFitIntoArg ========
* Assert that the target's `Float` type fits in an `IArg`
*
* This assertion is triggered when the `%f` format specifier is used,
* the argument treated as an `IArg`, but for the current target
* `sizeof(Float)` > `sizeof(IArg)`.
*/
config Assert.Id A_cannotFitIntoArg = {
msg: "A_cannotFitIntoArg: sizeof(Float) > sizeof(Arg)"
};
/*!
* ======== extendedFormats ========
* Optional conversions supported by `{@link #printf System_printf}`
*
* This string specifies the set of optional argument conversion
* specifiers required by the application. By reducing the number of
* optional conversions understood by the `System {@link #printf}`
* methods, it is possible to significantly reduce the code size
* footprint of the `System` module. This configuration parameter
* enables one to balance `printf` functionality against code size
* footprint.
*
* The format of this string is simply a concatenated list of the desired
* conversion specifiers (with the leading `%` character). For example,
* to support both `%f` and `%$L` set `extendedFormats` to `"%$L%f"`.
*
* To disable all optional converstions, set `extendedFormats` to `null`
* or the empty string ("").
*
* For a complete list of supported extensions, see the
* `{@link #printf System_printf}` "Extended_Format_Specifiers" section.
*
* @a(Note)
* If an optional conversion is used by some part of the application and
* it is not specified in `extendedFormats`, the conversion character(s)
* and leading `%` are treated as ordinary characters to be output. As
* a result, all subsequent arguments will almost certainly be converted
* using the wrong conversion specifier!
*
* @see #printf
*/
metaonly config String extendedFormats = "%$L%$S%$F";
/*!
* ======== SupportProxy ========
* The implementation module of the low-level system functions.
*
* This configuration parameter allows one to "bind" a different
* implementation of the low-level services required to implement
* `System`.
* @p(code)
* var System = xdc.useModule("xdc.runtime.System");
* var SysStd = xdc.useModule("xdc.runtime.SysStd");
* System.SupportProxy = SysStd;
* @p
*
* If this parameter is not set, it defaults to `{@link SysMin}`.
*/
proxy SupportProxy inherits ISystemSupport;
/*!
* ======== maxAtexitHandlers ========
* Maximum number of dynamic atexit handlers allowed in the system.
*
* Maximum number of `System` `atexit` handlers set during runtime via
* the `{@link System#atexit}` function.
*
*/
config Int maxAtexitHandlers = 8;
/*!
* ======== abortFxn ========
* Abort handler function
*
* This configuration parameter allows user to plug in their own abort
* function. By default `{@link #abortStd}` which calls ANSI C Standard
* `abort()` is plugged in. Alternatively `{@link #abortSpin}` can be
* plugged which loops infinitely.
*
*/
config AbortFxn abortFxn = System.abortStd;
/*!
* ======== exitFxn ========
* Exit handler function
*
* This configuration parameter allows user to plug in their own exit
* function. By default `{@link #exitStd}` which calls ANSI C Standard
* `exit()` is plugged in. Alternatively `{@link #exitSpin}` can be
* plugged which loops infinitely.
*
*/
config ExitFxn exitFxn = System.exitStd;
/*!
* ======== abort ========
* Print a message and abort currently running executable.
*
* This is called when an executable abnormally terminates.
* The `System` gate is entered, the
* `{@link #SupportProxy}`'s `abort` function is called
* and then `{@link #abortFxn}` is called.
* No exit functions bound via `System_atexit()` or the ANSI C Standard
* Library `atexit()` functions are executed.
*
* @param(str) abort message (not a format string)
*/
Void abort(CString str);
/*!
* ======== abortStd ========
* ANSI C Standard implementation of abortFxn function
*
* This function calls ANSI C Standard `abort()` to terminate currently
* running executable. This function is used by default in
* `{@link #abortFxn}`.
*
*/
Void abortStd();
/*!
* ======== abortSpin ========
* Lightweight implementation of abortFxn function
*
* This functions loops indefinitely. This can used as an alternative
* `{@link #abortFxn}` when a lightweight implementation is
* required instead of the ANSI C Standard `abort()`.
*/
Void abortSpin();
/*!
* ======== atexit ========
* Add an exit handler
*
* `System_atexit` pushes `handler` onto an internal stack of functions
* to be executed when system is exiting (e.g. `System_exit` is called).
* Up to `{@link #maxAtexitHandlers}` functions can be specified in this
* manner. During the exit processing, the functions are popped off the
* internal stack and called until the stack is empty.
*
* The `System` gate is entered before the `System_atexit` functions
* are called.
*
* The `SupportProxy`'s `{@link ISystemSupport#exit}` function is called
* after all the atexit functions are called.
*
* @param(handler) the `AtexitHandler` to invoke during system
* exit processing.
*
* @a(returns)
* If `FALSE` is returned, the exit handler was not added and it will
* not be called during an exit.
*/
Bool atexit(AtexitHandler handler);
/*!
* ======== atexitMeta ========
* Add an exit handler during configuration
*
* This is the static counterpart to `System_atexit()`. This method can
* be used to add `atexit` handlers at configuration time. These
* handlers do not count against the `maxAtexitHandlers`.
*
* @param(handler) the `AtexitHandler` to invoke during system
* exit processing.
*/
metaonly Void atexitMeta(AtexitHandler handler);
/*!
* ======== exit ========
* Exit currently running executable.
*
* This function is called when an executable needs to terminate
* normally. This function processes all functions bound via
* `System_atexit` and then calls `{@link #exitFxn}`. The
* `{@link #SupportProxy}`'s `exit` function is called during this time.
*
* @param(stat) exit status to return to calling environment.
*/
Void exit(Int stat);
/*!
* ======== exitStd ========
* Implements an `exitFxn` function
*
* This function calls ANSI C Standard `exit()` to terminate currently
* running executable normally. This function is used by default in
* `{@link #exitFxn}`.
*
* @param(stat) exit status to return to calling environment.
*/
Void exitStd(Int stat);
/*!
* ======== exitSpin ========
* Implements an `exitFxn` function
*
* This functions loops indefinitely. This can used as an alternative
* `{@link #exitFxn}` when a light weight implementation is
* required instead of the ANSI C Standard `exit()`.
*
* @param(stat) exit status to return to calling environment.
*/
Void exitSpin(Int stat);
/*!
* ======== processAtExit ========
* Processes all functions bound via `System_atexit`
*
* This function is called by `System_exit` to process all functions
* bound via `System_atexit`. User can add this to ANSI C standard
* `atexit` function so that all functions bound via `System_atexit` are
* processed when ANSI C standard `exit` function is called.
*
* @param(stat) exit status which will passed to all functions
* processed.
*/
Void processAtExit(Int stat);
/*!
* ======== putch ========
* Output a single character
*
* The `{@link #SupportProxy}`'s `putch` function is called
* by this function.
*
* @param(ch) character to be output.
*/
Void putch(Char ch);
/*!
* ======== flush ========
* Flush standard System I/O
*
* This function causes any buffered output characters are "written"
* to the output device.
*
* The `{@link #SupportProxy}`'s `flush` function is called
* by this function.
*/
Void flush();
/*!
* ======== printf ========
* A smaller faster printf
*
* This function behaves much like the ANSI C Standard `printf`
* but does not support the full range of format strings specified by
* the C Standard. In addition, several non-standard format specifiers
* are recognized.
*
* @a(Format Strings)
* The format string is a character string composed of zero or
* more directives: ordinary characters (not %), which are copied
* unchanged to the output stream; and conversion specifications, each of
* which results in fetching zero or more subsequent arguments. Each
* conversion specification is introduced by the character %, and ends
* with a conversion specifier. In between there may be (in this order)
* zero or more flags, an optional minimum field width, an optional
* precision and an optional length modifier.
*
* @a(Flags)
* The following flags are supported:
* @p(dlist)
* - `-`
* The converted value is to be left adjusted on the field
* boundary (the default is right justification.)
* - `0`
* The value should be zero padded. For d, i, o, u, and x
* conversions, the converted value is padded on the left
* with zeros rather than blanks.
* @p
*
* @a(Field Width)
* The optional field width specifier is a decimal digit string (with
* nonzero first digit) specifying a minimum field width. If the
* converted value has fewer characters than the field width, it will
* be padded with spaces on the left (or right, if the left-adjustment
* flag has been given). Instead of a decimal digit string one may
* write `*` to specify that the field width is given in the next
* argument. A negative field width is taken as a '-' flag followed
* by a positive field width.
*
* @a(Precision)
* The optional precision specifier is a period ('.') followed by an
* optional decimal digit string. Instead of a decimal digit string
* one may write `*` to specify that the precision is given in the
* next argument which must be of type int.
*
* If the precision is given as just '.', or the precision is
* negative, the precision is taken to be zero. This gives the
* minimum number of digits to appear for d, i, o, u, and x
* conversions, or the maximum number of characters to be printed from
* a string for s conversions.
*
* @a(Length Modifiers)
* The optional length modifier is a single character from the following
* list.
* @p(dlist)
* - `l`
* A following integer conversion corresponds to a long int
* or unsigned long int argument
*
* @p
*
* @a(Conversion Specifiers)
* The following conversion specifiers are supported.
* @p(dlist)
* - `d`, `i`
* signed integer
* - `u`
* unsigned decimal
* - `x`
* unsigned hex
* - `o`
* unsigned octal
* - `p`
* pointer (@ + hex num)
* - `c`
* character
* - `s`
* string
* @p
* @a(Extended Conversion Specifiers)
* The following conversion specifiers are optionally supported. See
* the `{@link #extendedFormats}` configuration parameter for more
* information about how to enable these conversion specifiers.
*
* @p(dlist)
* - `f`
* decimal floating point.
* - `$`
* non-ANSI conversion prefix. This prefix indicates that the
* next character identifies a non-ANSI standard conversion. See
* the next section for details.
* @p
*
* @a(Non ANSI Conversion Specifiers)
* Among the extended conversion specifiers are unique specifiers which
* are not part of ANSI printf. These are specified using a $, for
* example %$L.
*
* These unique specifiers do not support the minimum field width
* attribute. Certain specifiers have additional restrictions; see below.
*
* @p(dlist)
* - '$L'
* The argument is treated as a pointer to a `{@link Types#Label}`
* and is converted to an appropriate string.
* - '$F'
* Displays a file and line number; used for displaying the call
* site. This specifier consumes two arguments, the file and line
* number, in that order. See an example below.
* - '$S'
* The argument is treated as a format string, and is recursively
* formatted using any following arguments. This specifier does
* not support the use of the "precision" field for specifying
* maximum string length.
* @p
*
* The following are example uses of the %$F and %$S format specifiers.
*
* In this call using %$F, the compiler recognizes these symbols and
* fills in the file and line number.
* @p(code)
* System_printf("%$F", __FILE__, __LINE__);
* @p
* This call outputs, for example,
* @p(code)
* "MyCode.c", line 35:
* @p
* Here is an example using %$S, passing a recursive format string.
* @p(code)
* System_printf("Msg: %$S", "My msg, code: %d", 5);
* @p
* This outputs:
* @p(code)
* Msg: My msg, code: 5
* @p
*
* @param(fmt) a 'printf-style' format string
*
* @a(returns)
* `printf` returns the number of characters printed.
*/
Int printf(CString fmt, ...);
/*!
* ======== aprintf ========
* `{@link #printf}` where all optional arguments are `IArg`s
*
* This function will treat each argument as though it was widened to be
* of type `IArg` prior to being passed to the `{@link #printf}` function
*
* @see #printf
*/
Int aprintf(CString fmt, ...);
/*!
* ======== sprintf ========
* Write formated output to a character buffer
*
* This function is identical to `{@link #printf}` except that the
* output is copied to the specified character buffer `buf` followed
* by a terminating '\0' character.
*
* @param(buf) a character output buffer
* @param(fmt) a 'printf-style' format string
*
* @a(returns)
* `sprintf` returns the number of characters output not including the
* '\0' termination character.
*/
Int sprintf(Char buf[], CString fmt, ...);
/*!
* ======== asprintf ========
* `{@link #sprintf}` where all optional arguments are `IArg`s
*
* This function will treat each argument as though it was widened to be
* of type `IArg` prior to being passed to the `{@link #sprintf}`
* function.
*
* @see #sprintf
*/
Int asprintf(Char buf[], CString fmt, ...);
/*!
* ======== vprintf ========
* A VaList printf
*
* This function is identical to `{@link #printf}` except that its
* arguments are passed via a VaList (a "varargs list").
*
* @param(fmt) a standard 'printf-style' format string.
* @param(va) an args list that points to the arguments referenced
* by the fmt string
*
* @a(returns)
* `vprintf` returns the number of characters output.
*/
Int vprintf(CString fmt, VaList va);
/*!
* ======== avprintf ========
* `{@link #vprintf}` where all optional arguments are `IArg`s
*
* This function will treat each argument as though it was widened to be
* of type `IArg` prior to being passed to the `{@link #vprintf}`
* function.
*
* @see #vprintf
*/
Int avprintf(CString fmt, VaList va);
/*!
* ======== vsprintf ========
* A `VaList` sprintf
*
* This function is identical to `{@link #sprintf}` except that
* its arguments are passed via a `VaList` (a "varargs list").
*
* @param(buf) a character output buffer
* @param(fmt) a standard '`printf`-style' format string.
* @param(va) an arguments list that points to the arguments referenced
* by the `fmt` string
*
* @a(returns)
* `vsprintf` returns the number of characters output.
*/
Int vsprintf(Char buf[], CString fmt, VaList va);
/*!
* ======== avsprintf ========
* `{@link #vsprintf}` where all optional arguments are `IArg`s
*
* This function is identical to `{@link #sprintf}` except that
* its arguments are passed via a `VaList` (a "varargs list").
*
* This function will treat each argument as though it was widened to be
* of type `IArg` prior to being passed to the `vsprintf` function
*
* @see #vsprintf
*/
Int avsprintf(Char buf[], CString fmt, VaList va);
/*!
* ======== snprintf ========
* Write formated output to a character buffer
*
* This function is identical to `{@link #sprintf}` except that at most
* `n` characters are copied to the specified character buffer `buf`.
* If n is zero, nothing is written to character buffer. Otherwise,
* output characters beyond the `n` - 1 are discarded rather than
* being written to the character buf, and a null character is written
* at the end of the characters written into the buffer.
*
* @param(buf) a character output buffer
* @param(n) the maximum number of characters, including '\0', written to
* the output buffer `buf`
* @param(fmt) a 'printf-style' format string
*
* @a(returns)
* `snprintf` returns the number of characters that would have been
* written had `n` been sufficiently large, not counting the terminating
* '\0' character.
*/
Int snprintf(Char buf[], SizeT n, CString fmt, ...);
/*!
* ======== vsnprintf ========
* A `VaList` snprintf
*
* This function is identical to `{@link #snprintf}` except that
* its arguments are passed via a `VaList` (a "varargs list").
*
* @param(buf) a character output buffer
* @param(n) at most number of characters including '\0' written to
* output buffer
* @param(fmt) a standard '`printf`-style' format string.
* @param(va) an arguments list that points to the arguments referenced
* by the `fmt` string
*
* @a(returns)
* `vsnprintf` returns the number of characters that would have been
* written had `n` been sufficiently large, not counting the terminating
* '\0' character.
*/
Int vsnprintf(Char buf[], SizeT n, CString fmt, VaList va);
internal:
/*! struct used to keep track of state during doPrint */
struct ParseData {
Int width; /* width in format specifier */
Bool lFlag; /* length modifier flag */
Bool lJust; /* left justify flag */
Int precis; /* precision in format specifier */
Int len; /* length of formatted number */
Int zpad; /* leading zero pad flag */
Char *end; /* pointer to end of local buf to hold num */
Bool aFlag; /* deal with vars on stack as IArgs */
Char *ptr; /* ptr to local buf after filling in num */
};
/*! typedef for generated functions to process extended formats */
typedef Int (*ExtendFxn)(Char **, CString *, VaList *, ParseData *);
/*! config parameter used to call generated function */
readonly config ExtendFxn extendFxn = '&xdc_runtime_System_printfExtend__I';
/*
* ======== printfExtend ========
* System_printfExtend is generated based on extendedFormats string
*
* This generated function is accessed through an internal config so
* that it is an indirect call in the ROM case, but optimized to a direct
* call in the RAM case.
*
* @_nodoc
*/
Int printfExtend (Char **bufp, CString *fmt, VaList *va, ParseData *parse);
/*!
* ======== exitFxns ========
* @_nodoc
* List of functions statically plugged to be called at exit
*
*/
metaonly config AtexitHandler exitFxns[];
/*!
* ======== mprintf ========
* @_nodoc
*/
function mprintf(fmt, args);
/*!
* ======== doPrint ========
* @_nodoc
*/
Int doPrint(Char buf[], SizeT n, CString fmt, VaList *pva, Bool aFlag);
/*!
* ======== lastFxn ========
* @_nodoc
*
* Calls atexit() after all other modules have been initialized
* This used to be done in System_Module_startup() but this caused
* problems since atexit() uses a heap which isn't necessarily
* initialized.
*/
Void lastFxn();
/*!
* ======== putchar ========
* @_nodoc
*
* Write character ch to the buffer and, if the buffer pointer is
* non-`NULL`, update the buffer pointer.
*
* Keeps track of the number of characters written into the buffer by
* modifying bufsize `n`. Atmost, `n` - 1 characters are written.
*/
Void putchar(Char **bufp, Char ch, SizeT *n);
/*!
* ======== rtsExit ========
* @_nodoc
*/
Void rtsExit();
/*!
* ======== atexitDone ========
* @_nodoc
*/
Bool atexitDone();
/*!
* ======== Module_State ========
* @_nodoc
*/
struct Module_State {
AtexitHandler atexitHandlers[]; /* array of atexit handlers */
Int numAtexitHandlers; /* Current num of atexit handlers */
};
}