1    /* 
     2     *  Copyright (c) 2016-2017 Texas Instruments Incorporated
     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     *  }
    79     *  @p
    80     *
    81     *  All events logged by registered modules will be sent to the logger
    82     *  configured for the `Registry` module. For example, to configure the
    83     *  logger for use by all modules managed by `Registry`:
    84     *  @p(code)
    85     *  Registry.common$.logger = LoggerBuf.create();
    86     *  @p
    87     *
    88     *  Since the registered modules are not known until runtime, it is not
    89     *  possible to statically configure the diagnostics masks for individual
    90     *  registered modules. However, it is possible to configure diagnostics
    91     *  categories to be permanently off or on for ALL registered modules. This
    92     *  is done by configuring the diagnostic mask for the `Registry` module.
    93     *  Diagnostic categories set to `{@link Diags#ALWAYS_OFF Diags.ALWAYS_OFF}`
    94     *  will be permanently off for all `Registry` modules. Categories set to
    95     *  `{@link Diags#ALWAYS_ON Diags.ALWAYS_ON}` will be permanently on for all
    96     *  modules managed by `Registry`.
    97     *
    98     *  In order to enable runtime configuration of individual `Registry` module
    99     *  masks, all relevant diagnostic categories must be set to
   100     *  `{@link Diags#RUNTIME_OFF Diags.RUNTIME_OFF}` or
   101     *  `{@link Diags#RUNTIME_ON Diags.RUNTIME_ON}` in the `Registry` module's
   102     *  mask.
   103     */
   104    @CustomHeader
   105    @DirectCall
   106    module Registry
   107    {
   108        /*!
   109         *  ======== RegisteredModuleView ========
   110         *  @_nodoc
   111         *  View element for the 'Registered Modules' ROV view.
   112         */
   113        metaonly struct RegisteredModuleView {
   114            String modName;
   115            Int id;
   116            String mask;
   117            Ptr descAddr;
   118        }
   119    
   120        /*!
   121         *  ======== rovViewInfo ========
   122         *  @_nodoc
   123         */
   124        @Facet
   125        metaonly config xdc.rov.ViewInfo.Instance rovViewInfo = 
   126            xdc.rov.ViewInfo.create({
   127                viewMap: [
   128                    ['Registered Modules',
   129                        {
   130                            type: xdc.rov.ViewInfo.MODULE_DATA,
   131                            viewInitFxn: 'viewInitRegisteredModules',
   132                            structName: 'RegisteredModuleView'
   133                        }
   134                    ]
   135                ]
   136            });
   137    
   138        /*!
   139         *  ======== Result ========
   140         *  Status codes
   141         */
   142        enum Result {
   143            SUCCESS,        /*! The module was added successfully */
   144            ALLOC_FAILED,   /*! reserved */
   145            ALREADY_ADDED,  /*! The module has already been added or another
   146                             *  module with the same name is present
   147                             */
   148            ALL_IDS_USED    /*! No more module ids available for new modules */
   149        };
   150    
   151        /*!
   152         *  ======== RegDesc ========
   153         *  Registry module descriptor
   154         */
   155        typedef Types.RegDesc Desc;
   156    
   157        /*!
   158         *  ======== addModule ========
   159         *  Add a runtime module to the registry with the specified name
   160         *
   161         *  The `desc` parameter and the `modName` string provided must both be 
   162         *  permanent since the `Registry` will maintain references to both of
   163         *  these.
   164         *
   165         *  @param(desc)    non-`NULL` pointer to a `{#Desc Registry_Desc}`
   166         *                  structure.
   167         *  @param(modName) non-`NULL` string name of the module being registered.
   168         *
   169         *  @a(returns)
   170         *  `Registry_addModule` returns one of the following
   171         *  `{@link #Result Result}` status values indicating success or the
   172         *  cause of failure:
   173         *  @p(blist)
   174         *  - `{@link #SUCCESS SUCCESS}`
   175         *  - `{@link #ALREADY_ADDED ALREADY_ADDED}`
   176         *  - `{@link #ALL_IDS_USED ALL_IDS_USED}`  There are a total of 16,384 - 1
   177         *    module ids available for use by `Registry`.
   178         *  @p
   179         */
   180        Result addModule(Desc *desc, CString modName);
   181    
   182        /*!
   183         *  ======== findByName ========
   184         *  Find the registered module with the given name
   185         *
   186         *  @param(modName) non-`NULL` string name of a registered module
   187         *
   188         *  @a(returns)
   189         *  If the name `modName` is registered via
   190         *  `{@link #addModule Registry_addModule()}`, this function
   191         *  returns the pointer to the registered `Registry_Desc` structure;
   192         *  otherwise it returns `NULL`.
   193         */
   194        Desc *findByName(CString modName);
   195    
   196        /*!
   197         *  ======== findByNamePattern ========
   198         *  @_nodoc
   199         *  Find all registered modules matching the specified pattern.
   200         *
   201         *  This API is intended for use by Diags_setMask.
   202         *
   203         *  The name pattern can be an exact module name or it can contain '%'
   204         *  as a wildcard. The `len` parameter is the string length of the pattern.
   205         *
   206         *  This function returns one module at a time, but can be called
   207         *  repeatedly to find all modules matching the pattern. On the first
   208         *  call, pass `NULL` as the `prev` parameter. In all following calls,
   209         *  pass the last returned descriptor. This function returns `NULL` when
   210         *  it can't find any more modules matching the name pattern.
   211         */
   212        Desc *findByNamePattern(CString namePat, UShort len, Desc *prev);
   213    
   214        /*!
   215         *  ======== findById ========
   216         *  Find registered module's descriptor from its module ID
   217         *
   218         *  @param(mid) any module id
   219         *
   220         *  @a(returns)
   221         *  If the ID `mid` is registered via
   222         *  `{@link #addModule Registry_addModule()}`, this function
   223         *  returns the pointer to the registered `Registry_Desc` structure;
   224         *  otherwise it returns `NULL`.
   225         */
   226        Desc *findById(Types.ModuleId mid);
   227    
   228        /*!
   229         *  ======== getMask ========
   230         *  Get the specified module's diagnostic mask
   231         *
   232         *  @param(modName) non-`NULL` string name of a registered module
   233         *  @param(mask)    non-`NULL` pointer to a mask to be initialized
   234         *                  to the the current state of the diagnostics mask
   235         *                  associated with `modName`
   236         *
   237         *  @a(returns)
   238         *  The function returns `TRUE` if `name` identifies a registered module;
   239         *  otherwise, it return `FALSE`.
   240         */
   241        Bool getMask(CString name, Types.DiagsMask *mask);
   242    
   243        /*!
   244         *  ======== isMember ========
   245         *  Determines if the specified module ID belongs to a registered module
   246         *
   247         *  @param(mid) any module id
   248         *
   249         *  @a(returns)
   250         *  This function returns `TRUE` if and only if the specified module id
   251         *  is a valid `Registry` module id. It does not search registered
   252         *  module ids, but simply checks if the id is within the range of valid
   253         *  `Registry` module ids.
   254         */
   255        Bool isMember(Types.ModuleId mid);
   256        
   257        /*!
   258         *  ======== getNextModule ========
   259         *  Scan the current list of registered modules
   260         *
   261         *  This function used to scan the list of all `Registry_Desc` structures
   262         *  currently being managed by the `Registry` module.
   263         *
   264         *  @param(desc)    optionally `NULL` pointer to a `Registry_Desc`
   265         *                  structure.  If `desc` is `NULL`, a pointer to the
   266         *                  first structure is returned.  If `desc` is non-`NULL`
   267         *                  and equal to a previous return value of this function,
   268         *                  a pointer to the "next" `Registry_Desc` structure
   269         *                  is returned.
   270         *
   271         *  @a(returns)
   272         *  This function returns a non-`NULL` pointer to one of the
   273         *  `Registry_Desc` structures added via `Registry_Desc` structures or
   274         *  `NULL` in the case that
   275         *  @p(blist)
   276         *      - there are no more module's in the list after `desc`, or
   277         *      - there are no modules registered
   278         *  @p
   279         */
   280        Desc *getNextModule(Desc *desc);
   281        
   282        /*!
   283         *  ======== getModuleName ========
   284         *  Get the module name associated with a specified module descriptor
   285         *
   286         *  @param(desc)    non-`NULL` pointer to a `{#Desc Registry_Desc}`
   287         *                  structure.
   288         *
   289         *  @a(returns)
   290         *  If the specified module descriptor has been initialized via a
   291         *  successful call to `{@link #addModule Registry_addModule()}`, this
   292         *  function returns the module name passed `Registry_addModule()`;
   293         *  otherwise, its return value is indeterminate.
   294         */
   295        CString getModuleName(Desc *desc);
   296        
   297        /*!
   298         *  ======== getModuleId ========
   299         *  Get the module id associated with a specified module descriptor
   300         *
   301         *  @param(desc)    non-`NULL` pointer to a `{#Desc Registry_Desc}`
   302         *                  structure.
   303         *
   304         *  @a(returns)
   305         *  If the specified module descriptor has been initialized via a
   306         *  successful call to `{@link #addModule Registry_addModule()}`, this
   307         *  function returns the module id assigned by `Registry_addModule()`;
   308         *  otherwise, its return value is indeterminate.
   309         */
   310        Types.ModuleId getModuleId(Desc *desc);
   311    
   312    internal:
   313    
   314        Desc *findByNameInList(CString name, Desc *listHead);
   315        Void newModule(Desc *desc, CString modName);
   316        Bool matchPattern(CString pattern, UShort len, CString modName);
   317    
   318        /* Functions for accessing the Registry at ROV-time. */
   319        function isMemberRov(modId);
   320        function lookupModIdRov(modId);
   321        
   322        /*
   323         *  ======== Module_State ========
   324         */
   325        struct Module_State {
   326            Desc            *listHead;
   327            Types.ModuleId  curId;
   328        }
   329    }
   330    /*
   331     *  @(#) xdc.runtime; 2, 1, 0,0; 8-21-2019 13:22:47; /db/ztree/library/trees/xdc/xdc-H25/src/packages/
   332     */
   333