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