1    /* 
     2     *  Copyright (c) 2016 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     *  ======== Registry.xdc ========
    15     */
    16    
    17    /*!
    18     *  ======== Registry ========
    19     *  Register modules that are not statically configured
    20     *
    21     *  This module provides a mechanism by which legacy C code can have its own
    22     *  module logging support, including having a name and its own diags mask.
    23     *
    24     *  Without the `Registry`, all logging done by legacy C code is handled by the
    25     *  `xdc.runtime.Main` module. This means that all `{@link Log}` events will
    26     *  be marked as coming from "`xdc.runtime.Main`", and there is only a single
    27     *  diagnostics mask for the runtime control of logging across all legacy C
    28     *  code. The `Registry` module allows legacy C code to have the same granular
    29     *  control over logging as statically defined RTSC modules.
    30     *
    31     *  To use the `Registry` module, legacy code must define the symbol
    32     *  `Registry_CURDESC` to be the name of an externally declared
    33     *  `Registery_Desc` structure.  This symbol must be defined before the
    34     *  inclusion of any `xdc/runtime` header files. If any `xdc/runtime` header
    35     *  files are included before the definition of this symbol, the `Registry`
    36     *  module may not function properly.
    37     *
    38     *  Note: by defining this symbol on the compile line, rather than in the
    39     *  file, one can easily compile code to be used in one of two environments:
    40     *  @p(nlist)
    41     *    - a fixed configuration environment where modules are registered
    42     *      via `{@link #addModule Registry_addModule()}`, or
    43     *
    44     *    - a "normal" configurable environment in which this code is
    45     *      assumed to be part of the `{@link Main}` module.
    46     *  @p
    47     *  The `Registry_Desc` structure must then be registered by calling
    48     *  `{@link #addModule Registry_addModule()}`. The structure is typically
    49     *  registered and initialized within `main()`.
    50     *
    51     *  For example:
    52     *
    53     *  @p(code)
    54     *  //Define the required symbol, Registry_CURDESC, to this file's 
    55     *  //Registry_Desc object
    56     *  #define Registry_CURDESC    mainDesc
    57     *  #include <xdc/runtime/Registry.h>
    58     *
    59     *  //Declare the Registry_Desc object, the name is unimportant
    60     *  Registry_Desc mainDesc;
    61     *
    62     *  Int main(Int argc, String argv[]) {  
    63     *
    64     *  //Register this file as a module "main"
    65     *  Registry_addModule(&mainDesc, "main");
    66     *  @p
    67     *
    68     *  Once registered, the legacy code may call `{@link Log}` APIs without any
    69     *  other change and the formatted `Log` events will show as coming from the
    70     *  registered modules. Also, the logging by the legacy code is now filtered
    71     *  by its own diagnostic mask. The bits of this mask can be set using
    72     *  `{@link Diags#setMask Diags_setMask}`.
    73     *
    74     *  Continuing the previous example:
    75     *  @p(code)
    76     *  //Initialize the legacy code's diags mask to enable USER1.
    77     *  Diags_setMask("main=1");
    78     *  @p
    79     *
    80     *  All events logged by registered modules will be sent to the logger
    81     *  configured for the `Registry` module. For example, to configure the
    82     *  logger for use by all modules managed by `Registry`:
    83     *  @p(code)
    84     *  Registry.common$.logger = LoggerBuf.create();
    85     *  @p
    86     *
    87     *  Since the registered modules are not known until runtime, it is not
    88     *  possible to statically configure the diagnostics masks for individual
    89     *  registered modules. However, it is possible to configure diagnostics
    90     *  categories to be permanently off or on for ALL registered modules. This
    91     *  is done by configuring the diagnostic mask for the `Registry` module.
    92     *  Diagnostic categories set to `{@link Diags#ALWAYS_OFF Diags.ALWAYS_OFF}`
    93     *  will be permanently off for all `Registry` modules. Categories set to
    94     *  `{@link Diags#ALWAYS_ON Diags.ALWAYS_ON}` will be permanently on for all
    95     *  modules managed by `Registry`.
    96     *
    97     *  In order to enable runtime configuration of individual `Registry` module
    98     *  masks, all relevant diagnostic categories must be set to
    99     *  `{@link Diags#RUNTIME_OFF Diags.RUNTIME_OFF}` or
   100     *  `{@link Diags#RUNTIME_ON Diags.RUNTIME_ON}` in the `Registry` module's
   101     *  mask.
   102     */
   103    @CustomHeader
   104    @DirectCall
   105    module Registry
   106    {
   107        /*!
   108         *  ======== RegisteredModuleView ========
   109         *  @_nodoc
   110         *  View element for the 'Registered Modules' ROV view.
   111         */
   112        metaonly struct RegisteredModuleView {
   113            String modName;
   114            Int id;
   115            String mask;
   116            Ptr descAddr;
   117        }
   118    
   119        /*!
   120         *  ======== rovViewInfo ========
   121         *  @_nodoc
   122         */
   123        @Facet
   124        metaonly config xdc.rov.ViewInfo.Instance rovViewInfo = 
   125            xdc.rov.ViewInfo.create({
   126                viewMap: [
   127                    ['Registered Modules',
   128                        {
   129                            type: xdc.rov.ViewInfo.MODULE_DATA,
   130                            viewInitFxn: 'viewInitRegisteredModules',
   131                            structName: 'RegisteredModuleView'
   132                        }
   133                    ]
   134                ]
   135            });
   136    
   137        /*!
   138         *  ======== Result ========
   139         *  Status codes
   140         */
   141        enum Result {
   142            SUCCESS,        /*! The module was added successfully */
   143            ALLOC_FAILED,   /*! reserved */
   144            ALREADY_ADDED,  /*! The module has already been added or another
   145                             *  module with the same name is present
   146                             */
   147            ALL_IDS_USED    /*! No more module ids available for new modules */
   148        };
   149    
   150        /*!
   151         *  ======== RegDesc ========
   152         *  Registry module descriptor
   153         */
   154        typedef Types.RegDesc Desc;
   155    
   156        /*!
   157         *  ======== addModule ========
   158         *  Add a runtime module to the registry with the specified name
   159         *
   160         *  The `desc` parameter and the `modName` string provided must both be 
   161         *  permanent since the `Registry` will maintain references to both of
   162         *  these.
   163         *
   164         *  @param(desc)    non-`NULL` pointer to a `{#Desc Registry_Desc}`
   165         *                  structure.
   166         *  @param(modName) non-`NULL` string name of the module being registered.
   167         *
   168         *  @a(returns)
   169         *  `Registry_addModule` returns one of the following
   170         *  `{@link #Result Result}` status values indicating success or the
   171         *  cause of failure:
   172         *  @p(blist)
   173         *  - `{@link #SUCCESS SUCCESS}`
   174         *  - `{@link #ALREADY_ADDED ALREADY_ADDED}`
   175         *  - `{@link #ALL_IDS_USED ALL_IDS_USED}`  There are a total of 16,384 - 1
   176         *    module ids available for use by `Registry`.
   177         *  @p
   178         */
   179        Result addModule(Desc *desc, CString modName);
   180    
   181        /*!
   182         *  ======== findByName ========
   183         *  Find the registered module with the given name
   184         *
   185         *  @param(modName) non-`NULL` string name of a registered module
   186         *
   187         *  @a(returns)
   188         *  If the name `modName` is registered via
   189         *  `{@link #addModule Registry_addModule()}`, this function
   190         *  returns the pointer to the registered `Registry_Desc` structure;
   191         *  otherwise it returns `NULL`.
   192         */
   193        Desc *findByName(CString modName);
   194    
   195        /*!
   196         *  ======== findByNamePattern ========
   197         *  @_nodoc
   198         *  Find all registered modules matching the specified pattern.
   199         *
   200         *  This API is intended for use by Diags_setMask.
   201         *
   202         *  The name pattern can be an exact module name or it can contain '%'
   203         *  as a wildcard. The `len` parameter is the string length of the pattern.
   204         *
   205         *  This function returns one module at a time, but can be called
   206         *  repeatedly to find all modules matching the pattern. On the first
   207         *  call, pass `NULL` as the `prev` parameter. In all following calls,
   208         *  pass the last returned descriptor. This function returns `NULL` when
   209         *  it can't find any more modules matching the name pattern.
   210         */
   211        Desc *findByNamePattern(CString namePat, Int len, Desc *prev);
   212    
   213        /*!
   214         *  ======== findById ========
   215         *  Find registered module's descriptor from its module ID
   216         *
   217         *  @param(mid) any module id
   218         *
   219         *  @a(returns)
   220         *  If the ID `mid` is registered via
   221         *  `{@link #addModule Registry_addModule()}`, this function
   222         *  returns the pointer to the registered `Registry_Desc` structure;
   223         *  otherwise it returns `NULL`.
   224         */
   225        Desc *findById(Types.ModuleId mid);
   226    
   227        /*!
   228         *  ======== getMask ========
   229         *  Get the specified module's diagnostic mask
   230         *
   231         *  @param(modName) non-`NULL` string name of a registered module
   232         *  @param(mask)    non-`NULL` pointer to a mask to be initialized
   233         *                  to the the current state of the diagnostics mask
   234         *                  associated with `modName`
   235         *
   236         *  @a(returns)
   237         *  The function returns `TRUE` if `name` identifies a registered module;
   238         *  otherwise, it return `FALSE`.
   239         */
   240        Bool getMask(CString name, Types.DiagsMask *mask);
   241    
   242        /*!
   243         *  ======== isMember ========
   244         *  Determines if the specified module ID belongs to a registered module
   245         *
   246         *  @param(mid) any module id
   247         *
   248         *  @a(returns)
   249         *  This function returns `TRUE` if and only if the specified module id
   250         *  is a valid `Registry` module id. It does not search registered
   251         *  module ids, but simply checks if the id is within the range of valid
   252         *  `Registry` module ids.
   253         */
   254        Bool isMember(Types.ModuleId mid);
   255        
   256        /*!
   257         *  ======== getNextModule ========
   258         *  Scan the current list of registered modules
   259         *
   260         *  This function used to scan the list of all `Registry_Desc` structures
   261         *  currently being managed by the `Registry` module.
   262         *
   263         *  @param(desc)    optionally `NULL` pointer to a `Registry_Desc`
   264         *                  structure.  If `desc` is `NULL`, a pointer to the
   265         *                  first structure is returned.  If `desc` is non-`NULL`
   266         *                  and equal to a previous return value of this function,
   267         *                  a pointer to the "next" `Registry_Desc` structure
   268         *                  is returned.
   269         *
   270         *  @a(returns)
   271         *  This function returns a non-`NULL` pointer to one of the
   272         *  `Registry_Desc` structures added via `Registry_Desc` structures or
   273         *  `NULL` in the case that
   274         *  @p(blist)
   275         *      - there are no more module's in the list after `desc`, or
   276         *      - there are no modules registered
   277         *  @p
   278         */
   279        Desc *getNextModule(Desc *desc);
   280        
   281        /*!
   282         *  ======== getModuleName ========
   283         *  Get the module name associated with a specified module descriptor
   284         *
   285         *  @param(desc)    non-`NULL` pointer to a `{#Desc Registry_Desc}`
   286         *                  structure.
   287         *
   288         *  @a(returns)
   289         *  If the specified module descriptor has been initialized via a
   290         *  successful call to `{@link #addModule Registry_addModule()}`, this
   291         *  function returns the module name passed `Registry_addModule()`;
   292         *  otherwise, its return value is indeterminate.
   293         */
   294        CString getModuleName(Desc *desc);
   295        
   296        /*!
   297         *  ======== getModuleId ========
   298         *  Get the module id associated with a specified module descriptor
   299         *
   300         *  @param(desc)    non-`NULL` pointer to a `{#Desc Registry_Desc}`
   301         *                  structure.
   302         *
   303         *  @a(returns)
   304         *  If the specified module descriptor has been initialized via a
   305         *  successful call to `{@link #addModule Registry_addModule()}`, this
   306         *  function returns the module id assigned by `Registry_addModule()`;
   307         *  otherwise, its return value is indeterminate.
   308         */
   309        Types.ModuleId getModuleId(Desc *desc);
   310        
   311    internal:
   312        
   313        Desc *findByNameInList(CString name, Desc *listHead);
   314        Void newModule(Desc *desc, CString modName);
   315        Bool matchPattern(CString pattern, Int len, CString modName);
   316        
   317        /* Functions for accessing the Registry at ROV-time. */
   318        function isMemberRov(modId);
   319        function lookupModIdRov(modId);
   320        
   321        /*
   322         *  ======== Module_State ========
   323         */
   324        struct Module_State {
   325            Desc            *listHead;
   326            Types.ModuleId  curId;
   327        }
   328    }
   329    /*
   330     *  @(#) xdc.runtime; 2, 1, 0,0; 2-8-2017 14:15:56; /db/ztree/library/trees/xdc/xdc-D05/src/packages/
   331     */
   332