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