| %%{ |
| /* --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); |
| } |
| %} |