1 2 3 4 5 6 7 8
9
10 11 12 13
14
15 package xdc.runtime;
16
17 /*!
18 * ======== System ========
19 * Basic system services
20 *
21 * This module provides basic low-level "system" services; e.g.,
22 * character output, `printf`-like output, and exit handling.
23 *
24 * This module is gated and other modules use its gate via the
25 * `{@link Gate#enterSystem}` and `{@link Gate#leaveSystem}`. The
26 * `System` gate must be enterable by any thread in a multi-threadded
27 * environments. For example, in many real-time multi-threaded environments
28 * some types of threads, such as Interrupt Service Routines (ISRs), are not
29 * allowed to call operations that block the caller. In such an environment,
30 * either the `System` gate must disable all interrupts or ISRs must never
31 * call a function in the `xdc.runtime` package.
32 */
33
34 @Template("./System.xdt")
35 @Gated
36 @ModuleStartup
37 module System {
38
39 /*!
40 * ======== AtexitHandler ========
41 * `System`'s atexit function prototype.
42 *
43 * Fuctions of this type can be added to the list of functions that
44 * are executed during applciation terminiation.
45 *
46 * @see #atexit
47 */
48 typedef Void (*AtexitHandler)(Int);
49
50 /*!
51 * ======== STATUS_UNKNOWN ========
52 * Unknown exit status value
53 *
54 * When the program exits by calling {@link #exit} the `System`'s
55 * atexit functions are passed the status. When the program exits using
56 * the ANSI C Standard Library `exit()` function, the `System`'s atexit
57 * functions are passed `System_STATUS_UNKNOWN`.
58 */
59 const Int STATUS_UNKNOWN = 0xCAFE;
60
61 /*! @_nodoc */
62 @XmlDtd
63 metaonly struct Module_View {
64 String atexitHandlers[];
65 Int numAtexitHandlers;
66 };
67
68 /*!
69 * ======== A_cannotFitIntoArg ========
70 * Assert that the target's `Float` type fits in an `IArg`
71 *
72 * This assertion is triggered when the `%f` format specifier is used,
73 * the argument treated as an `IArg`, but for the current target
74 * `sizeof(Float)` > `sizeof(IArg)`.
75 */
76 config Assert.Id A_cannotFitIntoArg = {
77 msg: "A_cannotFitIntoArg: sizeof(Float) > sizeof(Arg)"
78 };
79
80 /*!
81 * ======== extendedFormats ========
82 * Optional conversions supported by `{@link #printf System_printf}`
83 *
84 * This string specifies the set of optional argument conversion
85 * specifiers required by the application. By reducing the number of
86 * optional conversions understood by the `System {@link #printf}`
87 * methods, it is possible to significantly reduce the code size
88 * footprint of the `System` module. This configuration parameter
89 * enables one to balence `printf` functionality against code size
90 * footprint.
91 *
92 * The format of this string is simply a concatenated list of the desired
93 * conversion specifiers (with the leading `%` character). For example,
94 * to support both `%f` and `%$L` set `extendedFormats` to `"%$L%f"`.
95 *
96 * To disable all optional converstions, set `extendedFormats` to `null`
97 * or the empty string ("").
98 *
99 * For a complete list of supported extensions, see the
100 * {@link #printf System_printf} "Extended_Format_Specifiers" section.
101 *
102 * @(Note)
103 * If an optional conversion is used by some part of the application and
104 * it is not specified in `extendedFormats`, the conversion character(s)
105 * and leading `%` are treated as ordinary characters to be output. As
106 * a result, all subsequent arguments will almost certainly be converted
107 * using the wrong conversion specifier!
108 *
109 * @see #printf
110 */
111 metaonly config String extendedFormats = "%$L";
112
113 /*!
114 * ======== SupportProxy ========
115 * The implementation module of the low-level system functions.
116 *
117 * This configuration parameter allows one to "bind" a different
118 * implementation of the low-level services required to implement
119 * `System`.
120 * @p(code)
121 * var System = xdc.useModule("xdc.runtime.System");
122 * var SysStd = xdc.useModule("xdc.runtime.SysStd");
123 * System.SupportProxy = SysStd;
124 * @p
125 *
126 * If this parameter is not set, it defaults to `{@link SysMin}`.
127 */
128 proxy SupportProxy inherits ISystemSupport;
129
130 /*!
131 * ======== maxAtexitHandlers ========
132 * Maximum number of dynamic atexit handlers allowed in the system.
133 *
134 * Maximum number of `System` atexit handlers set during runtime via
135 * the `{@link System#atexit}` function.
136 *
137 */
138 config Int maxAtexitHandlers = 8;
139
140 /*!
141 * ======== abort ========
142 * Print a message and abort currently running executable.
143 *
144 * This is called when an executable abnormally terminates.
145 * The `System` gate is entered, the
146 * `{@link #SupportProxy}`'s `abort` function is called
147 * and `abort` is called.
148 * No exit functions bound via `System_atexit()` or the ANSI C Standard
149 * Library `atexit()` functions are executed.
150 *
151 * @param(str) abort message (not a format string)
152 */
153 Void abort(String str);
154
155 /*!
156 * ======== atexit ========
157 * Add an exit handler
158 *
159 * `System_atexit` pushes `handler` onto an internal stack of functions
160 * to be executed when system is exiting (e.g. `System_exit` or `exit` is
161 * called). Up to `{@link #maxAtexitHandlers}` functions can be specified
162 * in this manner. During the exit processing, the functions are popped
163 * off the internal stack and called until the stack is empty.
164 *
165 * The `System` gate is entered before the `System_atexit` functions
166 * are called.
167 *
168 * The `SupportProxy`'s `{@link ISystemSupport#exit}` function is called
169 * after all the atexit functions are called.
170 *
171 * @param(handler) the `AtexitHandler` to invoke during system
172 * exit processing.
173 *
174 * @a(Returns)
175 * If `FALSE` is returned, the exit handler was not added and it will
176 * not be called during an exit.
177 */
178 Bool atexit(AtexitHandler handler);
179
180 /*!
181 * ======== atexitMeta ========
182 * Add an exit handler during configuration
183 *
184 * This is the static counterpart to `System_atexit()`. This method can
185 * be used to add "atexit" handlers at configuration time. These
186 * handlers do not count against the `maxAtexitHandlers`.
187 *
188 * @param(handler) the `AtexitHandler` to invoke during system
189 * exit processing.
190 */
191 metaonly Void atexitMeta(AtexitHandler handler);
192
193 /*!
194 * ======== exit ========
195 * Exit currently running executable.
196 *
197 * This function is called when an executable needs to terminate
198 * normally. This function sets the exit code and simply calls `exit`.
199 * All functions bound via `System_atexit` or the ANSI C Standar Library
200 * `atexit` function are then executed. The `{@link #SupportProxy}`'s
201 * `exit` function is called during this time.
202 *
203 * @param(stat) exit status to return to calling environment.
204 */
205 Void exit(Int stat);
206
207 /*!
208 * ======== putch ========
209 * Output a single character
210 *
211 * The `{@link #SupportProxy}`'s `putch` function is called
212 * by this function.
213 *
214 * @param(ch) character to be output.
215 */
216 Void putch(Char ch);
217
218 /*!
219 * ======== flush ========
220 * Flush standard System I/O
221 *
222 * This function causes any buffered output characters are "written"
223 * to the output device.
224 *
225 * The `{@link #SupportProxy}`'s `flush` function is called
226 * by this function.
227 */
228 Void flush();
229
230 /*!
231 * ======== printf ========
232 * A smaller faster printf
233 *
234 * This function behaves much like the ANSI C Standard `printf`
235 * but does not support the full range of format strings specified by
236 * the C Standard. In addition, several non-standard format specifiers
237 * are recognized.
238 *
239 * @a(Format Strings)
240 * The format string is a character string composed of zero or
241 * more directives: ordinary characters (not %), which are copied
242 * unchanged to the output stream; and conversion specifications, each of
243 * which results in fetching zero or more subsequent arguments. Each
244 * conversion specification is introduced by the character %, and ends
245 * with a conversion specifier. In between there may be (in this order)
246 * zero or more flags, an optional minimum field width, an optional
247 * precision and an optional length modifier.
248 *
249 * @a(Flags)
250 * The following flags are supported:
251 * @p(dlist)
252 * - `-`
253 * The converted value is to be left adjusted on the field
254 * boundary (the default is right justification.)
255 * - `0`
256 * The value should be zero padded. For d, i, o, u, and x
257 * conversions, the converted value is padded on the left
258 * with zeros rather than blanks.
259 * @p
260 *
261 * @a(Field Width)
262 * The optional field width specifier is a decimal digit string (with
263 * nonzero first digit) specifying a minimum field width. If the
264 * converted value has fewer characters than the field width, it will
265 * be padded with spaces on the left (or right, if the left-adjustment
266 * flag has been given). Instead of a decimal digit string one may
267 * write `*` to specify that the field width is given in the next
268 * argument. A negative field width is taken as a '-' flag followed
269 * by a positive field width.
270 *
271 * @a(Precision)
272 * The optional precision specifier is a period ('.') followed by an
273 * optional decimal digit string. Instead of a decimal digit string
274 * one may write `*` to specify that the precision is given in the
275 * next argument which must be of type int.
276 *
277 * If the precision is given as just '.', or the precision is
278 * negative, the precision is taken to be zero. This gives the
279 * minimum number of digits to appear for d, i, o, u, and x
280 * conversions, or the maximum number of characters to be printed from
281 * a string for s conversions.
282 *
283 * @a(Length Modifiers)
284 * The optional length modifier is a single character from the following
285 * list.
286 * @p(dlist)
287 * - `l`
288 * A following integer conversion corresponds to a long int
289 * or unsigned long int argument
290 *
291 * @p
292 *
293 * @a(Conversion Specifiers)
294 * The following conversion specifiers are supported.
295 * @p(dlist)
296 * - `d`, `i`
297 * signed integer
298 * - `u`
299 * unsigned decimal
300 * - `x`
301 * unsigned hex
302 * - `o`
303 * unsigned octal
304 * - `p`
305 * pointer (@ + hex num)
306 * - `c`
307 * character
308 * - `s`
309 * string
310 * @p
311 * @a(Extended Conversion Specifiers)
312 * The following conversion specifiers are optionally supported. See
313 * the `{@link #extendedFormats}` configuration parameter for more
314 * information about how to enable these conversion specifiers.
315 *
316 * @p(dlist)
317 * - `f`
318 * decimal floating point.
319 * - `$`
320 * non-ANSI conversion prefix. This prefix indicates that the
321 * next character identifies a non-ANSI standard conversion.
322 *
323 * If the next character is `L` then the argument is treated as
324 * a pointer to a `{@link Types#Label}` and is converted to an
325 * appropriate string.
326 * @p
327 *
328 * @param(fmt) a 'printf-style' format string
329 *
330 * @a(Returns)
331 * `printf` returns the number of characters printed.
332 */
333 Int printf(String fmt, ...);
334
335 /*!
336 * ======== aprintf ========
337 * `{@link #printf}` where all optional arguments are `IArg`s
338 *
339 * This function will treat each argument as though it was widened to be
340 * of type `IArg` prior to being passed to the `{@link #printf}` function
341 *
342 * @see #printf
343 */
344 Int aprintf(String fmt, ...);
345
346 /*!
347 * ======== sprintf ========
348 * Write formated output to a character buffer
349 *
350 * This function is identical to `{@link #printf}` except that the
351 * output is copied to the specified character buffer `buf` followed
352 * by a terminating '\0' character.
353 *
354 * @param(buf) a character output buffer
355 * @param(fmt) a 'printf-style' format string
356 *
357 * @a(Returns)
358 * `sprintf` returns the number of characters output not including the
359 * '\0' termination character.
360 */
361 Int sprintf(Char buf[], String fmt, ...);
362
363 /*!
364 * ======== asprintf ========
365 * `{@link #sprintf}` where all optional arguments are `IArg`s
366 *
367 * This function will treat each argument as though it was widened to be
368 * of type `IArg` prior to being passed to the `{@link #sprintf}`
369 * function.
370 *
371 * @see #sprintf
372 */
373 Int asprintf(Char buf[], String fmt, ...);
374
375 /*!
376 * ======== vprintf ========
377 * A VaList printf
378 *
379 * This function is identical to `{@link #printf}` except that its
380 * arguments are passed via a VaList (a "varargs list").
381 *
382 * @param(fmt) a standard 'printf-style' format string.
383 * @param(va) an args list that points to the arguments referenced
384 * by the fmt string
385 *
386 * @a(Returns)
387 * `vprintf` returns the number of characters output.
388 */
389 Int vprintf(String fmt, VaList va);
390
391 /*!
392 * ======== avprintf ========
393 * `{@link #vprintf}` where all optional arguments are `IArg`s
394 *
395 * This function will treat each argument as though it was widened to be
396 * of type `IArg` prior to being passed to the `{@link #vprintf}`
397 * function.
398 *
399 * @see #vprintf
400 */
401 Int avprintf(String fmt, VaList va);
402
403 /*!
404 * ======== vsprintf ========
405 * A `VaList` sprintf
406 *
407 * This function is identical to `{@link #sprintf}` except that
408 * its arguments are passed via a `VaList` (a "varargs list").
409 *
410 * @param(buf) a character output buffer
411 * @param(fmt) a standard '`printf`-style' format string.
412 * @param(va) an arguments list that points to the arguments referenced
413 * by the `fmt` string
414 *
415 * @a(Returns)
416 * `vsprintf` returns the number of characters output.
417 */
418 Int vsprintf(Char buf[], String fmt, VaList va);
419
420 /*!
421 * ======== avsprintf ========
422 * `{@link #vsprintf}` where all optional arguments are `IArg`s
423 *
424 * This function is identical to `{@link #sprintf}` except that
425 * its arguments are passed via a `VaList` (a "varargs list").
426 *
427 * This function will treat each argument as though it was widened to be
428 * of type `IArg` prior to being passed to the `vsprintf` function
429 *
430 * @see #vsprintf
431 */
432 Int avsprintf(Char buf[], String fmt, VaList va);
433
434 internal:
435
436 /*! struct used to keep track of state during doPrint */
437 struct ParseData {
438 Int width;
439 Bool lFlag;
440 Bool lJust;
441 Int precis;
442 Int len;
443 Int zpad;
444 Char *end;
445 Bool aFlag;
446 Char *ptr;
447 };
448
449 /*! typedef for generated functions to process extended formats */
450 typedef Int (*ExtendFxn)(Char **, Char **, VaList, ParseData *);
451
452 /*! config parameter used to call generated function */
453 readonly config ExtendFxn extendFxn = '&xdc_runtime_System_printfExtend__I';
454
455 456 457 458 459 460 461 462 463 464
465 Int printfExtend (Char **bufp, Char **fmt, VaList va, ParseData *parse);
466
467 /*!
468 * ======== exitFxns ========
469 * @_nodoc
470 * List of functions statically plugged to be called at exit
471 *
472 */
473 metaonly config AtexitHandler exitFxns[];
474
475 /*!
476 * ======== mprintf ========
477 * @_nodoc
478 */
479 function mprintf(fmt, args);
480
481 /*!
482 * ======== doPrint ========
483 * @_nodoc
484 *
485 */
486 Int doPrint(Char buf[], String fmt, VaList va, Bool aFlag);
487
488 /*!
489 * ======== formatNum ========
490 * @_nodoc
491 *
492 */
493 Char *formatNum(Char *ptr, UInt32 n, Int zpad, Int base);
494
495 /*!
496 * ======== putchar ========
497 * @_nodoc
498 *
499 * Write character ch to the buffer and, if the buffer pointer is
500 * non-`NULL`, update the buffer pointer.
501 */
502 Void putchar(Char **bufp, Char ch);
503
504 /*!
505 * ======== rtsExit ========
506 * @_nodoc
507 */
508 Void rtsExit();
509
510 /*!
511 * ======== Module_State ========
512 * @_nodoc
513 */
514 struct Module_State {
515 AtexitHandler atexitHandlers[];
516 Int numAtexitHandlers;
517 Int exitStatus;
518 };
519 }
520 521 522
523