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 `System`
28 * gate must be enterable by any thread in a multi-threaded environments. For
29 * example, in many real-time multi-threaded environments some types of
30 * threads, such as Interrupt Service Routines (ISRs), are not allowed to call
31 * operations that block the caller. In such an environment, either the
32 * `System` gate must disable all interrupts or ISRs must never call a function
33 * in the `xdc.runtime` package.
34 */
35
36 @Template("./System.xdt")
37 @Gated
38 @ModuleStartup
39 @DirectCall
40 module System {
41
42 /*!
43 * ======== AtexitHandler ========
44 * `System`'s atexit function prototype.
45 *
46 * Functions of this type can be added to the list of functions that
47 * are executed during application termination.
48 *
49 * @see #atexit
50 */
51 typedef Void (*AtexitHandler)(Int);
52
53 /*!
54 * ======== STATUS_UNKNOWN ========
55 * Unknown exit status value
56 *
57 * When the program exits by calling {@link #exit System_exit()} the
58 * `System`'s `atexit` functions are passed the status value passed to
59 * `System_exit()`. However, if the program exits using the ANSI C
60 * Standard Library `exit()` function, the `System`'s `atexit` functions
61 * are passed `System_STATUS_UNKNOWN`; ANSI C `atexit` functions are not
62 * passed the exit status.
63 */
64 const Int STATUS_UNKNOWN = 0xCAFE;
65
66 /*!
67 * ======== AbortFxn ========
68 * System abort function prototype.
69 *
70 * Functions of this type can be plugged into `System`'s abort function
71 * that will be executed during abnormal application termination.
72 *
73 * @see #abort
74 */
75 typedef Void (*AbortFxn)();
76
77 /*!
78 * ======== ExitFxn ========
79 * System exit function prototype.
80 *
81 * Functions of this type can be plugged into `System`'s exit function that
82 * will be executed during normal application termination.
83 *
84 * @see #exit
85 */
86 typedef Void (*ExitFxn)(Int);
87
88 /*! @_nodoc */
89 @XmlDtd
90 metaonly struct Module_View {
91 String atexitHandlers[];
92 Int numAtexitHandlers;
93 };
94
95 /*! @_nodoc */
96 metaonly struct PathEntryView {
97 String entry;
98 }
99
100 /*!
101 * ======== rovViewInfo ========
102 * @_nodoc
103 */
104 @Facet
105 metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
106 xdc.rov.ViewInfo.create({
107 viewMap: [
108 ['XDCROOT',
109 {
110 type: xdc.rov.ViewInfo.MODULE_DATA,
111 viewInitFxn: 'viewInitXdcRoot',
112 structName: 'PathEntryView'
113 }
114 ],
115 ['XDCPATH',
116 {
117 type: xdc.rov.ViewInfo.MODULE_DATA,
118 viewInitFxn: 'viewInitXdcPath',
119 structName: 'PathEntryView'
120 }
121 ],
122 ]
123 });
124
125 /*!
126 * ======== A_cannotFitIntoArg ========
127 * Assert that the target's `Float` type fits in an `IArg`
128 *
129 * This assertion is triggered when the `%f` format specifier is used,
130 * the argument treated as an `IArg`, but for the current target
131 * `sizeof(Float)` > `sizeof(IArg)`.
132 */
133 config Assert.Id A_cannotFitIntoArg = {
134 msg: "A_cannotFitIntoArg: sizeof(Float) > sizeof(Arg)"
135 };
136
137 /*!
138 * ======== extendedFormats ========
139 * Optional conversions supported by `{@link #printf System_printf}`
140 *
141 * This string specifies the set of optional argument conversion
142 * specifiers required by the application. By reducing the number of
143 * optional conversions understood by the `System {@link #printf}`
144 * methods, it is possible to significantly reduce the code size footprint
145 * of the `System` module. This configuration parameter enables one to
146 * balance `printf` functionality against code size footprint.
147 *
148 * The format of this string is simply a concatenated list of the desired
149 * conversion specifiers (with the leading `%` character). For example,
150 * to support both `%f` and `%$L` set `extendedFormats` to `"%$L%f"`.
151 *
152 * To disable all optional conversions, set `extendedFormats` to `null`
153 * or the empty string ("").
154 *
155 * For a complete list of supported extensions, see the
156 * `{@link #printf System_printf}` "Extended_Format_Specifiers" section.
157 *
158 * @a(Note)
159 * If an optional conversion is used by some part of the application and
160 * it is not specified in `extendedFormats`, the conversion character(s)
161 * and leading `%` are treated as ordinary characters to be output. As
162 * a result, all subsequent arguments will almost certainly be converted
163 * using the wrong conversion specifier!
164 *
165 * @see #printf
166 */
167
168 metaonly config String extendedFormats = "%$L%$S%$F";
169
170 /*!
171 * ======== SupportProxy ========
172 * The implementation module of the low-level system functions.
173 *
174 * This configuration parameter allows one to "bind" a different
175 * implementation of the low-level services required to implement `System`.
176 * @p(code)
177 * var System = xdc.useModule("xdc.runtime.System");
178 * var SysStd = xdc.useModule("xdc.runtime.SysStd");
179 * System.SupportProxy = SysStd;
180 * @p
181 *
182 * If this parameter is not set, it defaults to `{@link SysMin}`.
183 */
184
185 proxy SupportProxy inherits ISystemSupport;
186
187 /*!
188 * ======== maxAtexitHandlers ========
189 * Maximum number of dynamic atexit handlers allowed in the system.
190 *
191 * Maximum number of `System` `atexit` handlers set during runtime via
192 * the `{@link System#atexit}` function.
193 *
194 */
195
196 config Int maxAtexitHandlers = 8;
197
198 /*!
199 * ======== abortFxn ========
200 * Abort handler function
201 *
202 * This configuration parameter allows user to plug in their own abort
203 * function. By default `{@link #abortStd}` which calls ANSI C Standard
204 * `abort()` is plugged in. Alternatively `{@link #abortSpin}` can be
205 * plugged which loops infinitely.
206 *
207 */
208
209 config AbortFxn abortFxn = System.abortStd;
210
211 /*!
212 * ======== exitFxn ========
213 * Exit handler function
214 *
215 * This configuration parameter allows user to plug in their own exit
216 * function. By default `{@link #exitStd}` which calls ANSI C Standard
217 * `exit()` is plugged in. Alternatively `{@link #exitSpin}` can be
218 * plugged which loops infinitely.
219 *
220 */
221
222 config ExitFxn exitFxn = System.exitStd;
223
224 /*!
225 * ======== abort ========
226 * Print a message and abort currently running executable.
227 *
228 * This is called when an executable abnormally terminates.
229 * The `System` gate is entered, the `{@link #SupportProxy}`'s `abort`
230 * function is called and then `{@link #abortFxn}` is called.
231 * No exit functions bound via `System_atexit()` or the ANSI C Standard
232 * Library `atexit()` functions are executed.
233 *
234 * @param(str) abort message (not a format string)
235 */
236
237 Void abort(CString str);
238
239 /*!
240 * ======== abortStd ========
241 * ANSI C Standard implementation of abortFxn function
242 *
243 * This function calls ANSI C Standard `abort()` to terminate currently
244 * running executable. This function is used by default in
245 * `{@link #abortFxn}`.
246 *
247 */
248
249 Void abortStd();
250
251 /*!
252 * ======== abortSpin ========
253 * Lightweight implementation of abortFxn function
254 *
255 * This function loops indefinitely. It can be used as an alternative
256 * `{@link #abortFxn}` when a lightweight implementation is
257 * required instead of the ANSI C Standard `abort()`.
258 */
259
260 Void abortSpin();
261
262 /*!
263 * ======== atexit ========
264 * Add an exit handler
265 *
266 * `System_atexit` pushes `handler` onto an internal stack of functions
267 * to be executed when the system is exiting (e.g. `System_exit` is
268 * called). Up to `{@link #maxAtexitHandlers}` functions can be specified
269 * in this manner. During the exit processing, the functions are popped
270 * off the internal stack and called until the stack is empty.
271 *
272 * The `System` gate is entered before the `System_atexit` functions
273 * are called.
274 *
275 * The `SupportProxy`'s `{@link ISystemSupport#exit}` function is called
276 * after all the atexit functions are called.
277 *
278 * @param(handler) the `AtexitHandler` to invoke during system
279 * exit processing.
280 *
281 * @a(returns)
282 * If `FALSE` is returned, the exit handler was not added and it will
283 * not be called during an exit.
284 */
285
286 Bool atexit(AtexitHandler handler);
287
288 /*!
289 * ======== atexitMeta ========
290 * Add an exit handler during configuration
291 *
292 * This is the static counterpart to `System_atexit()`. This method can
293 * be used to add `atexit` handlers at configuration time. These
294 * handlers do not count against the `maxAtexitHandlers`.
295 *
296 * @param(handler) the `AtexitHandler` to invoke during system
297 * exit processing.
298 */
299
300 metaonly Void atexitMeta(AtexitHandler handler);
301
302 /*!
303 * ======== exit ========
304 * Exit currently running executable.
305 *
306 * This function is called when an executable needs to terminate normally.
307 * This function processes all functions bound via `System_atexit` and then
308 * calls `{@link #exitFxn}`. The `{@link #SupportProxy}`'s `exit` function
309 * is called during this time.
310 *
311 * @param(stat) exit status to return to calling environment.
312 */
313
314 Void exit(Int stat);
315
316 /*!
317 * ======== exitStd ========
318 * Implements an `exitFxn` function
319 *
320 * This function calls ANSI C Standard `exit()` to terminate currently
321 * running executable normally. This function is used by default in
322 * `{@link #exitFxn}`.
323 *
324 * @param(stat) exit status to return to calling environment.
325 */
326
327 Void exitStd(Int stat);
328
329 /*!
330 * ======== exitSpin ========
331 * Implements an `exitFxn` function
332 *
333 * This function loops indefinitely. It can be used as an alternative
334 * `{@link #exitFxn}` when a light weight implementation is required
335 * instead of the ANSI C Standard `exit()`.
336 *
337 * @param(stat) exit status to return to calling environment.
338 */
339
340 Void exitSpin(Int stat);
341
342 /*!
343 * ======== processAtExit ========
344 * Processes all functions bound via `System_atexit`
345 *
346 * This function is called by `System_exit` to process all functions
347 * bound via `System_atexit`. User can add this to ANSI C standard
348 * `atexit` function so that all functions bound via `System_atexit` are
349 * processed when ANSI C standard `exit` function is called.
350 *
351 * @param(stat) exit status which will be passed to all functions
352 * processed.
353 */
354
355 Void processAtExit(Int stat);
356
357 /*!
358 * ======== putch ========
359 * Output a single character
360 *
361 * This function calls `{@link #SupportProxy}`'s `putch` function.
362 *
363 * @param(ch) character to be output.
364 */
365
366 Void putch(Char ch);
367
368 /*!
369 * ======== flush ========
370 * Flush standard System I/O
371 *
372 * This function causes any buffered output characters are "written"
373 * to the output device.
374 *
375 * This function calls `{@link #SupportProxy}`'s `flush` function.
376 */
377
378 Void flush();
379
380 /*!
381 * ======== printf ========
382 * A smaller faster printf
383 *
384 * This function behaves much like the ANSI C Standard `printf`, but does
385 * not support the full range of format strings specified by the C
386 * Standard. In addition, several non-standard format specifiers
387 * are recognized.
388 *
389 * @a(Format Strings)
390 * The format string is a character string composed of zero or more
391 * directives: ordinary characters (not %), which are copied unchanged to
392 * the output stream; and conversion specifications, each of which results
393 * in fetching zero or more subsequent arguments. Each conversion
394 * specification is introduced by the character %, and ends with a
395 * conversion specifier. In between there may be (in this order) zero or
396 * more flags, an optional minimum field width, an optional precision and
397 * an optional length modifier.
398 *
399 * @a(Flags)
400 * The following flags are supported:
401 * @p(dlist)
402 * - `-`
403 * The converted value is to be left adjusted on the field
404 * boundary (the default is right justification.)
405 * - `0`
406 * The value should be zero padded. For d, i, o, u, and x
407 * conversions, the converted value is padded on the left
408 * with zeros rather than blanks.
409 * @p
410 *
411 * @a(Field Width)
412 * The optional field width specifier is a decimal digit string (with
413 * nonzero first digit) specifying a minimum field width. If the
414 * converted value has fewer characters than the field width, it will be
415 * padded with spaces on the left (or right, if the left-adjustment flag
416 * has been given). Instead of a decimal digit string one may write `*` to
417 * specify that the field width is given in the next argument. A negative
418 * field width is taken as a '-' flag followed by a positive field width.
419 *
420 * @a(Precision)
421 * The optional precision specifier is a period ('.') followed by an
422 * optional decimal digit string. Instead of a decimal digit string
423 * one may write `*` to specify that the precision is given in the
424 * next argument which must be of type int.
425 *
426 * If the precision is given as just '.', or the precision is negative, the
427 * precision is taken to be zero. This gives the minimum number of digits
428 * to appear for d, i, o, u, and x conversions, or the maximum number of
429 * characters to be printed from a string for s conversions.
430 *
431 * @a(Length Modifiers)
432 * The optional length modifier is a single character from the following
433 * list.
434 * @p(dlist)
435 * - `l`
436 * A following integer conversion corresponds to a long int
437 * or unsigned long int argument
438 *
439 * @p
440 *
441 * @a(Conversion Specifiers)
442 * The following conversion specifiers are supported.
443 * @p(dlist)
444 * - `d`, `i`
445 * signed integer
446 * - `u`
447 * unsigned decimal
448 * - `x`
449 * unsigned hex
450 * - `o`
451 * unsigned octal
452 * - `p`
453 * pointer (@ + hex num)
454 * - `c`
455 * character
456 * - `s`
457 * string
458 * @p
459 * @a(Extended Conversion Specifiers)
460 * The following conversion specifiers are optionally supported. See
461 * the `{@link #extendedFormats}` configuration parameter for more
462 * information about how to enable these conversion specifiers.
463 *
464 * @p(dlist)
465 * - `f`
466 * decimal floating point.
467 * The support for floating point numbers is limited to the
468 * range [-LONG_MAX, LONG_MAX]. For all the numbers outside of
469 * that range, the string "(error)" is displayed instead.
470 * - `$`
471 * non-ANSI conversion prefix. This prefix indicates that the
472 * next character identifies a non-ANSI standard conversion. See
473 * the next section for details.
474 * @p
475 *
476 * @a(Non ANSI Conversion Specifiers)
477 * Among the extended conversion specifiers are unique specifiers which
478 * are not part of ANSI printf. These are specified using a $, for
479 * example %$L.
480 *
481 * These unique specifiers do not support the minimum field width
482 * attribute. Certain specifiers have additional restrictions; see below.
483 *
484 * @p(dlist)
485 * - '$L'
486 * The argument is treated as a pointer to a `{@link Types#Label}`
487 * and is converted to an appropriate string.
488 * - '$F'
489 * Displays a file and line number; used for displaying the call
490 * site. This specifier consumes two arguments, the file and line
491 * number, in that order. See an example below.
492 * - '$S'
493 * The argument is treated as a format string, and is recursively
494 * formatted using any following arguments. This specifier does
495 * not support the use of the `precision` field for specifying
496 * maximum string length.
497 * @p
498 *
499 * The following are example uses of the %$F and %$S format specifiers.
500 *
501 * In this call using %$F, the compiler recognizes these symbols and
502 * fills in the file and line number.
503 * @p(code)
504 * System_printf("%$F", __FILE__, __LINE__);
505 * @p
506 * This call outputs, for example,
507 * @p(code)
508 * "MyCode.c", line 35:
509 * @p
510 * Here is an example using %$S, passing a recursive format string.
511 * @p(code)
512 * System_printf("Msg: %$S", "My msg, code: %d", 5);
513 * @p
514 * This outputs:
515 * @p(code)
516 * Msg: My msg, code: 5
517 * @p
518 *
519 * @param(fmt) a 'printf-style' format string
520 *
521 * @a(returns)
522 * This function returns the number of characters that would be printed if
523 * the underlying `{@link #SupportProxy}` implementation succesfully
524 * printed each character. If the underlying `SupportProxy` implementation
525 * is not ready to accept a character, that character is silently dropped,
526 * but the returned value is still incremented. If `SupportProxy` is not
527 * ready for the first character, `printf` exits immediately and returns
528 * -1.
529 */
530
531 Int printf(CString fmt, ...);
532
533 /*!
534 * ======== aprintf ========
535 * `{@link #printf}` where all optional arguments are `IArg`s
536 *
537 * This function will treat each argument as though it was widened to be
538 * of type `IArg` prior to being passed to the `{@link #printf}` function
539 *
540 * @see #printf
541 */
542
543 Int aprintf(CString fmt, ...);
544
545 /*!
546 * ======== sprintf ========
547 * Write formated output to a character buffer
548 *
549 * This function is identical to `{@link #printf}` except that the
550 * output is copied to the specified character buffer `buf` followed
551 * by a terminating '\0' character.
552 *
553 * @param(buf) a character output buffer
554 * @param(fmt) a 'printf-style' format string
555 *
556 * @a(returns)
557 * `sprintf` returns the number of characters output not including the
558 * '\0' termination character.
559 */
560
561 Int sprintf(Char buf[], CString fmt, ...);
562
563 /*!
564 * ======== asprintf ========
565 * `{@link #sprintf}` where all optional arguments are `IArg`s
566 *
567 * This function will treat each argument as though it was widened to be
568 * of type `IArg` prior to being passed to the `{@link #sprintf}`
569 * function.
570 *
571 * @see #sprintf
572 */
573
574 Int asprintf(Char buf[], CString fmt, ...);
575
576 /*!
577 * ======== vprintf ========
578 * A VaList printf
579 *
580 * This function is identical to `{@link #printf}` except that its
581 * arguments are passed via a VaList (a "varargs list").
582 *
583 * @param(fmt) a standard 'printf-style' format string.
584 * @param(va) an args list that points to the arguments referenced
585 * by the fmt string
586 *
587 * @a(returns)
588 * `vprintf` returns the number of characters output.
589 */
590
591 Int vprintf(CString fmt, VaList va);
592
593 /*!
594 * ======== avprintf ========
595 * `{@link #vprintf}` where all optional arguments are `IArg`s
596 *
597 * This function will treat each argument as though it was widened to be
598 * of type `IArg` prior to being passed to the `{@link #vprintf}`
599 * function.
600 *
601 * @see #vprintf
602 */
603
604 Int avprintf(CString fmt, VaList va);
605
606 /*!
607 * ======== vsprintf ========
608 * A `VaList` sprintf
609 *
610 * This function is identical to `{@link #sprintf}` except that
611 * its arguments are passed via a `VaList` (a "varargs list").
612 *
613 * @param(buf) a character output buffer
614 * @param(fmt) a standard '`printf`-style' format string.
615 * @param(va) an arguments list that points to the arguments referenced
616 * by the `fmt` string
617 *
618 * @a(returns)
619 * `vsprintf` returns the number of characters output.
620 */
621
622 Int vsprintf(Char buf[], CString fmt, VaList va);
623
624 /*!
625 * ======== avsprintf ========
626 * `{@link #vsprintf}` where all optional arguments are `IArg`s
627 *
628 * This function is identical to `{@link #sprintf}` except that
629 * its arguments are passed via a `VaList` (a "varargs list").
630 *
631 * This function will treat each argument as though it was widened to be
632 * of type `IArg` prior to being passed to the `vsprintf` function
633 *
634 * @see #vsprintf
635 */
636
637 Int avsprintf(Char buf[], CString fmt, VaList va);
638
639 /*!
640 * ======== snprintf ========
641 * Write formated output to a character buffer
642 *
643 * This function is identical to `{@link #sprintf}` except that at most
644 * `n` characters are copied to the specified character buffer `buf`.
645 * If n is zero, nothing is written to character buffer. Otherwise,
646 * output characters beyond the `n` - 1 are discarded rather than
647 * being written to the character buf, and a null character is written
648 * at the end of the characters written into the buffer.
649 *
650 * @param(buf) a character output buffer
651 * @param(n) the maximum number of characters, including '\0', written to
652 * the output buffer `buf`
653 * @param(fmt) a 'printf-style' format string
654 *
655 * @a(returns)
656 * `snprintf` returns the number of characters that would have been
657 * written had `n` been sufficiently large, not counting the terminating
658 * '\0' character. However, if extended conversion specifiers are used
659 * (@see #printf), the return value may be lower than the number of
660 * characters that would be written had `n` been sufficiently large.
661 */
662
663 Int snprintf(Char buf[], SizeT n, CString fmt, ...);
664
665 /*!
666 * ======== vsnprintf ========
667 * A `VaList` snprintf
668 *
669 * This function is identical to `{@link #snprintf}` except that
670 * its arguments are passed via a `VaList` (a "varargs list").
671 *
672 * @param(buf) a character output buffer
673 * @param(n) at most number of characters including '\0' written to
674 * output buffer
675 * @param(fmt) a standard '`printf`-style' format string.
676 * @param(va) an arguments list that points to the arguments referenced
677 * by the `fmt` string
678 *
679 * @a(returns)
680 * `vsnprintf` returns the number of characters that would have been
681 * written had `n` been sufficiently large, not counting the terminating
682 * '\0' character. However, if extended conversion specifiers are used
683 * (@see #printf), the return value may be lower than the number of
684 * characters that would be written had `n` been sufficiently large.
685 */
686
687 Int vsnprintf(Char buf[], SizeT n, CString fmt, VaList va);
688
689 internal:
690
691 /*! struct used to keep track of state during doPrint */
692 struct ParseData {
693 Int width;
694 Bool lFlag;
695 Bool lJust;
696 Int precis;
697 UInt len;
698 Int zpad;
699 Char *end;
700 Bool aFlag;
701 Char *ptr;
702 };
703
704 /*! typedef for generated functions to process extended formats */
705 typedef Int (*ExtendFxn)(Char **, CString *, VaList *, ParseData *);
706
707 /*! config parameter used to call generated function */
708 readonly config ExtendFxn extendFxn = '&xdc_runtime_System_printfExtend__I';
709
710 711 712 713 714 715 716 717 718 719
720 Int printfExtend (Char **bufp, CString *fmt, VaList *va, ParseData *parse);
721
722 /*!
723 * ======== exitFxns ========
724 * @_nodoc
725 * List of functions statically plugged to be called at exit
726 *
727 */
728 metaonly config AtexitHandler exitFxns[];
729
730 /*!
731 * ======== mprintf ========
732 * @_nodoc
733 */
734 function mprintf(fmt, args);
735
736 /*!
737 * ======== doPrint ========
738 * @_nodoc
739 */
740 Int doPrint(Char buf[], SizeT n, CString fmt, VaList *pva, Bool aFlag);
741
742 /*!
743 * ======== lastFxn ========
744 * @_nodoc
745 *
746 * Calls atexit() after all other modules have been initialized
747 * This used to be done in System_Module_startup() but this caused
748 * problems since atexit() uses a heap which isn't necessarily
749 * initialized.
750 */
751 Void lastFxn();
752
753 /*!
754 * ======== putchar ========
755 * @_nodoc
756 *
757 * Write character ch to the buffer and, if the buffer pointer is
758 * non-`NULL`, update the buffer pointer.
759 *
760 * Keeps track of the number of characters written into the buffer by
761 * modifying bufsize `n`. Atmost, `n` - 1 characters are written.
762 */
763 Void putchar(Char **bufp, Char ch, SizeT *n);
764
765 /*!
766 * ======== rtsExit ========
767 * @_nodoc
768 */
769 Void rtsExit();
770
771 /*!
772 * ======== atexitDone ========
773 * @_nodoc
774 */
775 Bool atexitDone();
776
777 /*!
778 * ======== Module_State ========
779 * @_nodoc
780 */
781 struct Module_State {
782 AtexitHandler atexitHandlers[];
783 Int numAtexitHandlers;
784 };
785 }
786 787 788
789