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