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