1    /* --COPYRIGHT--,ESD
     2     *  Copyright (c) 2008 Texas Instruments. All rights reserved. 
     3     *  This program and the accompanying materials are made available under the 
     4     *  terms of the Eclipse Public License v1.0 and Eclipse Distribution License
     5     *  v. 1.0 which accompanies this distribution. The Eclipse Public License is
     6     *  available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse
     7     *  Distribution License is available at 
     8     *  http://www.eclipse.org/org/documents/edl-v10.php.
     9     *
    10     *  Contributors:
    11     *      Texas Instruments - initial implementation
    12     * --/COPYRIGHT--*/
    13    /*
    14     *  ======== System.xdc ========
    15     *
    16     *! Revision History
    17     *! ================
    18     *! 06-Feb-2008 nitya   Fixed SDSCM00018899, SDSCM00020676, SDSCM00021045
    19     *! 23-Jul-2007 toddm   code review changes
    20     *! 13-Jun-2007 nitya   New rtsExit(), atexitMeta()
    21     *! 07-Jun-2007 nitya   abort takes a String, fail() deleted.
    22     *! 15-May-2007 toddm   Added flush interface function.
    23     *! 18-Apr-2007 nitya   Updated xdoc for System_atexit()
    24     *! 19-Mar-2007 toddm   Moved static functions into internal
    25     *! 06-Feb-2007 toddm   Added putch
    26     *! 31-Jan-2007 toddm   Added atexit handling
    27     *! 28-Nov-2006 toddm   Start revision history
    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;          /* width in format specifier */  
   456            Bool    lFlag;          /* length modifier flag */
   457            Bool    lJust;          /* left justify flag */
   458            Int     precis;         /* precision in format specifier */     
   459            Int     len;            /* length of formatted number */        
   460            Int     zpad;           /* leading zero pad flag */
   461            Char    *end;           /* pointer to end of local buf to hold num */
   462            Bool    aFlag;          /* deal with vars on stack as IArgs */
   463            Char    *ptr;           /* ptr to local buf after filling in num */
   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         * ======== printfExtend ======== 
   474         *  System_printfExtend is generated based on extendedFormats string
   475         *
   476         *  This generated function is accessed through an internal config so
   477         *  that it is an indirect call in the ROM case, but optimized to a direct
   478         *  call in the RAM case.
   479         *
   480         * @_nodoc
   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[];   /* array of atexit handlers       */
   533            Int            numAtexitHandlers;  /* Current num of atexit handlers */
   534            Int            exitStatus;         /* status for exit handlers       */
   535        };
   536    }
   537    /*
   538     *  @(#) xdc.runtime; 2, 0, 0, 0,214; 7-29-2009 14:53:44; /db/ztree/library/trees/xdc-t56x/src/packages/
   539     */
   540