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