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 * - `$`
468 * non-ANSI conversion prefix. This prefix indicates that the
469 * next character identifies a non-ANSI standard conversion. See
470 * the next section for details.
471 * @p
472 *
473 * @a(Non ANSI Conversion Specifiers)
474 * Among the extended conversion specifiers are unique specifiers which
475 * are not part of ANSI printf. These are specified using a $, for
476 * example %$L.
477 *
478 * These unique specifiers do not support the minimum field width
479 * attribute. Certain specifiers have additional restrictions; see below.
480 *
481 * @p(dlist)
482 * - '$L'
483 * The argument is treated as a pointer to a `{@link Types#Label}`
484 * and is converted to an appropriate string.
485 * - '$F'
486 * Displays a file and line number; used for displaying the call
487 * site. This specifier consumes two arguments, the file and line
488 * number, in that order. See an example below.
489 * - '$S'
490 * The argument is treated as a format string, and is recursively
491 * formatted using any following arguments. This specifier does
492 * not support the use of the `precision` field for specifying
493 * maximum string length.
494 * @p
495 *
496 * The following are example uses of the %$F and %$S format specifiers.
497 *
498 * In this call using %$F, the compiler recognizes these symbols and
499 * fills in the file and line number.
500 * @p(code)
501 * System_printf("%$F", __FILE__, __LINE__);
502 * @p
503 * This call outputs, for example,
504 * @p(code)
505 * "MyCode.c", line 35:
506 * @p
507 * Here is an example using %$S, passing a recursive format string.
508 * @p(code)
509 * System_printf("Msg: %$S", "My msg, code: %d", 5);
510 * @p
511 * This outputs:
512 * @p(code)
513 * Msg: My msg, code: 5
514 * @p
515 *
516 * @param(fmt) a 'printf-style' format string
517 *
518 * @a(returns)
519 * This function returns the number of characters that would be printed if
520 * the underlying `{@link #SupportProxy}` implementation succesfully
521 * printed each character. If the underlying `SupportProxy` implementation
522 * is not ready to accept a character, that character is silently dropped,
523 * but the returned value is still incremented. If `SupportProxy` is not
524 * ready for the first character, `printf` exits immediately and returns
525 * -1.
526 */
527
528 Int printf(CString fmt, ...);
529
530 /*!
531 * ======== aprintf ========
532 * `{@link #printf}` where all optional arguments are `IArg`s
533 *
534 * This function will treat each argument as though it was widened to be
535 * of type `IArg` prior to being passed to the `{@link #printf}` function
536 *
537 * @see #printf
538 */
539
540 Int aprintf(CString fmt, ...);
541
542 /*!
543 * ======== sprintf ========
544 * Write formated output to a character buffer
545 *
546 * This function is identical to `{@link #printf}` except that the
547 * output is copied to the specified character buffer `buf` followed
548 * by a terminating '\0' character.
549 *
550 * @param(buf) a character output buffer
551 * @param(fmt) a 'printf-style' format string
552 *
553 * @a(returns)
554 * `sprintf` returns the number of characters output not including the
555 * '\0' termination character.
556 */
557
558 Int sprintf(Char buf[], CString fmt, ...);
559
560 /*!
561 * ======== asprintf ========
562 * `{@link #sprintf}` where all optional arguments are `IArg`s
563 *
564 * This function will treat each argument as though it was widened to be
565 * of type `IArg` prior to being passed to the `{@link #sprintf}`
566 * function.
567 *
568 * @see #sprintf
569 */
570
571 Int asprintf(Char buf[], CString fmt, ...);
572
573 /*!
574 * ======== vprintf ========
575 * A VaList printf
576 *
577 * This function is identical to `{@link #printf}` except that its
578 * arguments are passed via a VaList (a "varargs list").
579 *
580 * @param(fmt) a standard 'printf-style' format string.
581 * @param(va) an args list that points to the arguments referenced
582 * by the fmt string
583 *
584 * @a(returns)
585 * `vprintf` returns the number of characters output.
586 */
587
588 Int vprintf(CString fmt, VaList va);
589
590 /*!
591 * ======== avprintf ========
592 * `{@link #vprintf}` where all optional arguments are `IArg`s
593 *
594 * This function will treat each argument as though it was widened to be
595 * of type `IArg` prior to being passed to the `{@link #vprintf}`
596 * function.
597 *
598 * @see #vprintf
599 */
600
601 Int avprintf(CString fmt, VaList va);
602
603 /*!
604 * ======== vsprintf ========
605 * A `VaList` sprintf
606 *
607 * This function is identical to `{@link #sprintf}` except that
608 * its arguments are passed via a `VaList` (a "varargs list").
609 *
610 * @param(buf) a character output buffer
611 * @param(fmt) a standard '`printf`-style' format string.
612 * @param(va) an arguments list that points to the arguments referenced
613 * by the `fmt` string
614 *
615 * @a(returns)
616 * `vsprintf` returns the number of characters output.
617 */
618
619 Int vsprintf(Char buf[], CString fmt, VaList va);
620
621 /*!
622 * ======== avsprintf ========
623 * `{@link #vsprintf}` where all optional arguments are `IArg`s
624 *
625 * This function is identical to `{@link #sprintf}` except that
626 * its arguments are passed via a `VaList` (a "varargs list").
627 *
628 * This function will treat each argument as though it was widened to be
629 * of type `IArg` prior to being passed to the `vsprintf` function
630 *
631 * @see #vsprintf
632 */
633
634 Int avsprintf(Char buf[], CString fmt, VaList va);
635
636 /*!
637 * ======== snprintf ========
638 * Write formated output to a character buffer
639 *
640 * This function is identical to `{@link #sprintf}` except that at most
641 * `n` characters are copied to the specified character buffer `buf`.
642 * If n is zero, nothing is written to character buffer. Otherwise,
643 * output characters beyond the `n` - 1 are discarded rather than
644 * being written to the character buf, and a null character is written
645 * at the end of the characters written into the buffer.
646 *
647 * @param(buf) a character output buffer
648 * @param(n) the maximum number of characters, including '\0', written to
649 * the output buffer `buf`
650 * @param(fmt) a 'printf-style' format string
651 *
652 * @a(returns)
653 * `snprintf` returns the number of characters that would have been
654 * written had `n` been sufficiently large, not counting the terminating
655 * '\0' character. However, if extended conversion specifiers are used
656 * (@see #printf), the return value may be lower than the number of
657 * characters that would be written had `n` been sufficiently large.
658 */
659
660 Int snprintf(Char buf[], SizeT n, CString fmt, ...);
661
662 /*!
663 * ======== vsnprintf ========
664 * A `VaList` snprintf
665 *
666 * This function is identical to `{@link #snprintf}` except that
667 * its arguments are passed via a `VaList` (a "varargs list").
668 *
669 * @param(buf) a character output buffer
670 * @param(n) at most number of characters including '\0' written to
671 * output buffer
672 * @param(fmt) a standard '`printf`-style' format string.
673 * @param(va) an arguments list that points to the arguments referenced
674 * by the `fmt` string
675 *
676 * @a(returns)
677 * `vsnprintf` returns the number of characters that would have been
678 * written had `n` been sufficiently large, not counting the terminating
679 * '\0' character. However, if extended conversion specifiers are used
680 * (@see #printf), the return value may be lower than the number of
681 * characters that would be written had `n` been sufficiently large.
682 */
683
684 Int vsnprintf(Char buf[], SizeT n, CString fmt, VaList va);
685
686 internal:
687
688 /*! struct used to keep track of state during doPrint */
689 struct ParseData {
690 Int width;
691 Bool lFlag;
692 Bool lJust;
693 Int precis;
694 UInt len;
695 Int zpad;
696 Char *end;
697 Bool aFlag;
698 Char *ptr;
699 };
700
701 /*! typedef for generated functions to process extended formats */
702 typedef Int (*ExtendFxn)(Char **, CString *, VaList *, ParseData *);
703
704 /*! config parameter used to call generated function */
705 readonly config ExtendFxn extendFxn = '&xdc_runtime_System_printfExtend__I';
706
707 708 709 710 711 712 713 714 715 716
717 Int printfExtend (Char **bufp, CString *fmt, VaList *va, ParseData *parse);
718
719 /*!
720 * ======== exitFxns ========
721 * @_nodoc
722 * List of functions statically plugged to be called at exit
723 *
724 */
725 metaonly config AtexitHandler exitFxns[];
726
727 /*!
728 * ======== mprintf ========
729 * @_nodoc
730 */
731 function mprintf(fmt, args);
732
733 /*!
734 * ======== doPrint ========
735 * @_nodoc
736 */
737 Int doPrint(Char buf[], SizeT n, CString fmt, VaList *pva, Bool aFlag);
738
739 /*!
740 * ======== lastFxn ========
741 * @_nodoc
742 *
743 * Calls atexit() after all other modules have been initialized
744 * This used to be done in System_Module_startup() but this caused
745 * problems since atexit() uses a heap which isn't necessarily
746 * initialized.
747 */
748 Void lastFxn();
749
750 /*!
751 * ======== putchar ========
752 * @_nodoc
753 *
754 * Write character ch to the buffer and, if the buffer pointer is
755 * non-`NULL`, update the buffer pointer.
756 *
757 * Keeps track of the number of characters written into the buffer by
758 * modifying bufsize `n`. Atmost, `n` - 1 characters are written.
759 */
760 Void putchar(Char **bufp, Char ch, SizeT *n);
761
762 /*!
763 * ======== rtsExit ========
764 * @_nodoc
765 */
766 Void rtsExit();
767
768 /*!
769 * ======== atexitDone ========
770 * @_nodoc
771 */
772 Bool atexitDone();
773
774 /*!
775 * ======== Module_State ========
776 * @_nodoc
777 */
778 struct Module_State {
779 AtexitHandler atexitHandlers[];
780 Int numAtexitHandlers;
781 };
782 }
783 784 785
786