blob: 1734fa6cede2bbcfe7e5262c28c567cd848d5671 [file] [log] [blame]
%%{
/* --COPYRIGHT--,ESD
* Copyright (c) 2008-2020 Texas Instruments Incorporated
* 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--*/
/* define convenience aliases for long System names */
var INum = "xdc_runtime_System_INum";
var UNum = "xdc_runtime_System_UNum";
var formatNum = "xdc_runtime_System_formatNum__I";
/* determine if the target's va_list is an array type */
var arrayTypeVaList = false;
if ("arrayTypeVaList" in Program.build.target) {
arrayTypeVaList = Program.build.target.arrayTypeVaList;
}
/* vav is used in an optimization of printfExtend to reduce pointer math
*
* Unfortunately, this optimization is not portable: targets in which
* a va_list is an array type require more careful use of va_start,
* va_copy, and va_end which defeats the optimization.
*/
var vav = arrayTypeVaList ? "*pva" : "va";
%%}
%var System = xdc.module("xdc.runtime.System");
#include <xdc/std.h>
#include <limits.h>
#include <xdc/runtime/Types.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/System__internal.h>
/*
* ======== System_printfExtend__I ========
* This function processes optional extended formats of printf.
*
* It returns the number of characters added to the result.
*
* Precision (maximum string length) is not supported for %$S.
*
* Right-justified (which is default) minimum width is not supported
* for %$L, %$S, or %$F.
*/
xdc_Int xdc_runtime_System_printfExtend__I(xdc_Char **pbuf, xdc_CString *pfmt,
xdc_VaList *pva, xdc_runtime_System_ParseData *parse)
{
xdc_Int res;
xdc_Char c;
xdc_Bool found = FALSE;
%if (!arrayTypeVaList) {
/*
* Create a local variable 'va' to ensure that the dereference of
* pva only occurs once.
*/
va_list va = *pva;
%}
res = 0;
c = **pfmt;
*pfmt = *pfmt + 1;
%/* Only include the code to check for '$' if the extendedFormats */
%/* includes one of the $ format types. */
%var regexp = /\$/;
%if (System.extendedFormats && (System.extendedFormats.search(regexp) != -1)) {
if (c == '$') {
c = **pfmt;
*pfmt = *pfmt + 1;
% /* %$L - formats a Types.Label */
% var regexp = /%\$L/;
% if (System.extendedFormats &&
% (System.extendedFormats.search(regexp) != -1)) {
%
if (c == 'L') {
xdc_runtime_Types_Label *lab = (parse->aFlag == TRUE) ?
(xdc_runtime_Types_Label *)xdc_iargToPtr(va_arg(`vav`, xdc_IArg)) :
(xdc_runtime_Types_Label *)va_arg(`vav`, void *);
/*
* Call Text_putLab to write out the label, taking the precision
* into account.
*/
res = xdc_runtime_Text_putLab(lab, pbuf, parse->precis);
/*
* Set the length to 0 to indicate to 'doPrint' that nothing should
* be copied from parse.ptr.
*/
parse->len = 0;
/* Update the minimum width field. */
parse->width -= res;
found = TRUE;
}
% } /* end %$L */
%
% /* %$F - formats a file name and optional line number */
% var regexp = /%\$F/;
% if (System.extendedFormats &&
% (System.extendedFormats.search(regexp) != -1)) {
%
if (c == 'F') {
xdc_runtime_Types_Site site;
/* Retrieve the file name string from the argument list */
site.file = (parse->aFlag == TRUE) ?
(xdc_Char *) xdc_iargToPtr(va_arg(`vav`, xdc_IArg)) :
(xdc_Char *) va_arg(`vav`, xdc_Char *);
/* Retrieve the line number from the argument list. */
site.line = (parse->aFlag == TRUE) ?
(xdc_Int) va_arg(`vav`, xdc_IArg) :
(xdc_Int) va_arg(`vav`, xdc_Int);
/*
* Omit the 'mod' field, set it to 0.
* '0' is a safe sentinel value - the IDs for named modules are
* 0x8000 and higher, and the IDs for unnamed modules go from 0x1
* to 0x7fff.
*/
site.mod = 0;
/*
* Call putSite to format the file and line number.
* If a precision was specified, it will be used as the maximum
* string length.
*/
res = xdc_runtime_Text_putSite(&site, pbuf, parse->precis);
/*
* Set the length to 0 to indicate to 'doPrint' that nothing should
* be copied from parse.ptr.
*/
parse->len = 0;
/* Update the minimum width field */
parse->width -= res;
found = TRUE;
}
% } /* end %$F */
%
% /* %$S - Recursively formats a string */
% var regexp = /%\$S/;
% if (System.extendedFormats &&
% (System.extendedFormats.search(regexp) != -1)) {
%
if (c == 'S') {
/* Retrieve the format string from the argument list */
parse->ptr = (parse->aFlag == TRUE) ?
(xdc_Char *) xdc_iargToPtr(va_arg(`vav`, xdc_IArg)) :
(xdc_Char *) va_arg(`vav`, xdc_Char *);
% if (!arrayTypeVaList) {
/* Update pva before passing it to doPrint. */
*pva = va;
% }
/* Perform the recursive format. System_doPrint does not advance
* the buffer pointer, so it has to be done explicitly.
* System_doPrint guarantees that parse->precis is positive.
*/
res = xdc_runtime_System_doPrint__I(*pbuf, (xdc_SizeT)parse->precis,
parse->ptr, pva, parse->aFlag);
if (*pbuf != NULL) {
if (res >= parse->precis) {
/* Not enough space for all characters, only
* (parse->precis - 1) and '\0' were printed.
*/
res = parse->precis - 1;
}
*pbuf += res;
}
% if (!arrayTypeVaList) {
/* Update the temporary variable with any changes to *pva */
va = *pva;
% }
/*
* Set the length to 0 to indicate to 'doPrint' that nothing should
* be copied from parse.ptr
*/
parse->len = 0;
/* Update the minimum width field */
parse->width -= res;
/* Indicate that we were able to interpret the specifier */
found = TRUE;
}
% } /* end %$S */
}
%} /* end $ */
%
%var regexp = /%f/;
%if (System.extendedFormats && (System.extendedFormats.search(regexp) != -1)) {
%
if (c == 'f') {
xdc_Double d, tmp;
`UNum` fract;
xdc_Int negative;
if (parse->aFlag == TRUE) {
xdc_runtime_Assert_isTrue((sizeof(xdc_Float) <= sizeof(xdc_IArg)),
xdc_runtime_System_A_cannotFitIntoArg);
d = argToFloat(va_arg(`vav`, xdc_IArg));
}
else {
d = va_arg(`vav`, double);
}
if (d < 0.0) {
d = -d;
negative = TRUE;
parse->zpad--;
}
else {
negative = FALSE;
}
/*
* output (error) if we can't print correct value
*/
if (d > (double) LONG_MAX) {
parse->ptr = "(error)";
parse->len = 7; /* strlen("(error)"); */
goto end;
}
/* Assumes four digits after decimal point. We are using a temporary
* double variable to force double-precision computations without
* using --fp_mode=strict flag. See the description of that flag in
* the compiler's doc for a further explanation.
*/
tmp = (d - (`UNum`)d) * 1e4;
fract = (`UNum`)tmp;
parse->ptr = `formatNum`(parse->end, fract, 4, 10);
*(--parse->ptr) = '.';
#if 0
/* eliminate trailing zeros */
do {
} while (*(--parse->end) == '0');
++parse->end;
#endif
parse->len = (UInt)(parse->end - parse->ptr);
/* format integer part (right to left!) */
parse->ptr = `formatNum`(parse->ptr,
(`INum`)d, parse->zpad - parse->len, 10);
if (negative) {
*(--parse->ptr) = '-';
}
parse->len = (UInt)(parse->end - parse->ptr);
found = TRUE;
}
%} else {
if (c == 'f') {
/* support arguments _after_ optional float support */
if (parse->aFlag == TRUE) {
(void)va_arg(`vav`, xdc_IArg);
}
else {
(void)va_arg(`vav`, double);
}
}
%} /* %f */
if (found == FALSE) {
/* other character (like %) copy to output */
*(parse->ptr) = c;
parse->len = 1;
}
/*
* Before returning, we must update the value of pva. We use a label here
* so that all return points will go through this update.
* The 'goto end' is here to ensure that there is always a reference to the
* label (to avoid the compiler complaining).
*/
goto end;
end:
%if (!arrayTypeVaList) {
*pva = va;
%}
return (res);
}
%
%if (!(Program.build.target.os === undefined)) {
#include <stdlib.h>
/*
*
* ======== xdc_runtime_System_lastFxn__I ========
*/
xdc_Void xdc_runtime_System_lastFxn__I(xdc_Void)
{
xdc_runtime_System_atexit__E(\
(xdc_runtime_System_AtexitHandler)xdc_runtime_System_atexitDone__I);
atexit(xdc_runtime_System_rtsExit__I);
}
/*
* rtsExit__I is an internal entry point called by target/platform boot code.
* Boot code is not brought into a partial-link assembly. So without this pragma,
* whole program optimizers would otherwise optimize-out these functions.
*/
xdc_Void xdc_runtime_System_rtsExit__I(void) __attribute__ ((used));
/*
* ======== xdc_runtime_System_rtsExit__I ========
*/
xdc_Void xdc_runtime_System_rtsExit__I(xdc_Void)
{
if (!xdc_runtime_System_atexitDone__I()) {
xdc_runtime_System_processAtExit__E(xdc_runtime_System_STATUS_UNKNOWN);
}
}
/*
* ======== xdc_runtime_System_atexitDone__I ========
*/
xdc_Bool xdc_runtime_System_atexitDone__I(xdc_Void)
{
static xdc_Bool done = FALSE;
/* If this function is called the first time */
if (!done) {
done = TRUE;
return (FALSE);
}
return (TRUE);
}
%}