1    /*
     2     * Copyright (c) 2012-2013, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     * */
    32    
    33    /*
    34     *  ======== LogSnapshot.xdc ========
    35     */
    36    package ti.uia.runtime;
    37    import xdc.runtime.Types;
    38    import ti.uia.runtime.LoggerTypes;
    39    import xdc.runtime.ILogger;
    40    import ti.uia.runtime.CtxFilter;
    41    import xdc.runtime.ILogger;
    42    import xdc.runtime.Diags;
    43    import xdc.runtime.Text;
    44    import ti.uia.events.UIASnapshot;
    45    import ti.uia.runtime.IUIATraceSyncClient;
    46    
    47    /*!
    48     *  ======== LogSnapshot ========
    49     *  Snapshot Event logging manager for logging blocks of memory, strings in memory
    50     *     and names of dynamically created objects
    51     *
    52     *  {@link ti.uia.events.UIASnapshot Snapshot events} are used to log dynamic
    53     *  target state information in order to
    54     *  capture the execution context of the application at a particular moment in
    55     *  time.  Types of information that can be logged include:
    56     *  @p(blist)
    57     *      - Blocks of memory (using the {@link #writeMemoryBlock LogSnapshot_writeMemoryBlock} API)
    58     *      - Strings that reside in memory (using the {@link #writeString LogSnapshot_writeString} API)
    59     *      - Names of dynamically created objects (using the {@link #writeNameOfReference LogSnapshot_writeNameOfReference} API)
    60     *  @p
    61     *  The host-side tooling can be instructed to treat a series of LogSnapshot
    62     *  events as representing the state of the target at the same moment in time by
    63     *  using the same non-zero value in the {@link #getSnapshotId snapshot ID} parameter
    64     *  of each of the LogSnapshot events in the series.
    65     *
    66     *  Snapshot events are logged by a logger that implements the
    67     *  {@link ti.uia.runtime.ILoggerSnapshot ILoggerSnapshot}
    68     *  interface (e.g. {@link ti.uia.runtime.LoggerCircBuf LoggerCircBuf},
    69     *  {@link ti.uia.runtime.LoggerStopMode LoggerStopMode},
    70     *  {@link ti.uia.runtime.LoggerProbePoint LoggerProbePoint}).
    71     *  Rather than invoking the logger's APIs directly, the APIs are
    72     *  called indirectly via the LogSnapshot module's APIs so that different types
    73     *  of loggers can be used without having to recompile the source code that is
    74     *  logging the snapshot events.
    75     * @a(Examples)
    76     *  @p(html)
    77     *  <B>Example 1: A simple 2-line configuration script</B>
    78     *  @p
    79     *  The following configuration script shows the simplest way
    80     * to configure an application to use log snapshot events:
    81     * @p(code)
    82     * var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');
    83     * var LogSnapshot   = xdc.useModule('ti.uia.runtime.LogSnapshot');
    84     * @p
    85     * The first line causes the {@link ti.uia.sysbios.LoggingSetup LoggingSetup}
    86     * module's .xs script to automatically create a 32K Byte logger and assign it to
    87     * xdc.runtime.Main.common$.logger.  It also sets any unconfigured Diags masks
    88     * for the Main module to Diags.RUNTIME_ON, enabling the events to be logged.
    89     * @p
    90     * The second line causes the LogSnapshot .xs script to run during the configuration
    91     * process when building the application. The script detects that a logger has
    92     * not been assigned to the LogSnapshot module, so it checks if
    93     * a logger has been configured for either the Main module or the Defaults module.
    94     * Since there is a logger for the Main module, the script configures the LogSnapshot
    95     * module to log events to the same logger instance.
    96     *
    97     *  @p(html)
    98     *  <hr />
    99     *  <B>Example 2: Using a dedicated low priority logger for snapshot events</B>
   100     *  @p
   101     * In some situations, the amount of data logged by the LogSnapshot
   102     * APIs may exceed the ability of the target to move the event data out of the
   103     * Main module's logger's circular buffer and up to the host.  One way of
   104     * ensuring that the other events that are logged are not dropped due to this
   105     * type of situation is to configure the LogSnapshot module to write events
   106     * to a separate lower priority logger.
   107     * @p
   108     * The following is an example of a
   109     * configuration script that configures a logger for use by the LogSnapshot
   110     * module.  This example uses a LoggerCircBuf logger, which is appropriate for
   111     * uploading events in real-time as the target executes using either
   112     * JTAG RunMode(C6X targets) or using a non-JTAG transport such as Ethernet.
   113     * Assigning this logger a {@link ti.uia.runtime.IUIATransferlow#Priority_LOW
   114     * low priority} causes the contents of this logger to be uploaded after
   115     * higher priority events (e.g. sync point events, context change events,
   116     * and error, warning, info events) have been uploaded.
   117     * @p
   118     * @p(code)
   119     * var Logger = xdc.useModule('ti.uia.runtime.LoggerCircBuf');
   120     * var LogSnapshot   = xdc.useModule('ti.uia.runtime.LogSnapshot');
   121     *
   122     * // Create a low priority logger and use it for snapshot events
   123     * var IUIATransfer = xdc.useModule('ti.uia.runtime.IUIATransfer');
   124     * var loggerParams = new Logger.Params();
   125     * loggerParams.priority = IUIATransfer.Priority_LOW;
   126     * // set the logger buffer size in bytes
   127     * loggerParams.transferBufSize = 32768;
   128     * var snapshotLogger = Logger.create(loggerParams);
   129     * snapshotLogger.instance.name = "SnapshotLog";
   130     * LogSnapshot.common$.logger = snapshotLogger;
   131     * @p
   132     * Using different types of loggers:
   133     * @p(blist)
   134     *      - To upload events by JTAG when the target halts (JTAG StopMode),
   135     * replace the first line in the example with
   136     * @p(code)
   137     * Logger = xdc.useModule('ti.uia.runtime.LoggerStopMode');
   138     * @p(blist)
   139     *      - To upload events by JTAG whenever an event is logged using probe point
   140     * breakpoints (i.e. momentarily halting the target while the event is uploaded
   141     * and then resuming execution), replace the first line in the example with
   142     * @p(code)
   143     * Logger = xdc.useModule('ti.uia.runtime.LoggerProbePoint');
   144     * @p
   145     *
   146     *
   147     *  @p(html)
   148     *  <hr />
   149     *  <B>Example 3: Using Diags masks to control snapshot events</B>
   150     *  @p
   151     *  The generation of a 'Snapshot' event is controlled by a module's diagnostics
   152     *  mask, which is described in details in the CDoc for xdc.runtime.Diags. Each
   153     *  {@link ti.uia.events.UIASnapshot snapshot event} is controlled using the
   154     *  Diags.ANALYSIS mask, and will only be logged when the diagnostics mask for
   155     *  the module that is logging the code has the Diags.ANALYSIS bit
   156     *  configured as either ALWAYS_ON or RUNTIME_ON.
   157     *  @p
   158     *  The `LogSnapshot` function call sites are implemented in such a way that an
   159     *  optimizer can completely eliminate `LogSnapshot` code from the program if
   160     *  the module's `ANALYSIS` events have been disabled at configuration time. If
   161     *  the 'ANALYSIS' events are permanently turned on at configuration time,
   162     *  then the optimizer can eliminate all runtime conditional checking and
   163     *  simply invoke the 'LogSnapshot' functions directly. Runtime checking is
   164     *  performed only when the ANALYSIS events are configured to be runtime
   165     *  modifiable.
   166     *  @p
   167     * The following is an example of the configuration script used
   168     * to configure the default mask for modules to have Analysis events such as
   169     * the UIASnapshot events always on.
   170     * @p(code)
   171     *  // Configure all modules to always log Analysis events
   172     *  var Diags = xdc.useModule('xdc.runtime.Diags');
   173     *  var Defaults = xdc.useModule('xdc.runtime.Defaults');
   174     *  Defaults.common$.diags_ANALYSIS = Diags.ALWAYS_ON;
   175     * @p
   176     *
   177     */
   178    
   179    @CustomHeader
   180    module LogSnapshot inherits IUIATraceSyncClient {
   181    
   182        /*!
   183         *  ======== EventRec ========
   184         *  The target representation of a recorded event
   185         *
   186         *  This structure defines how events are recorded on the target.
   187         */
   188        struct EventRec {
   189            Types.Timestamp64 tstamp; /*! time event was written */
   190            Bits32 serial; /*! serial number of event */
   191            Types.Event evt; /*! target encoding of an Event */
   192            Int snapshotId;
   193            IArg fmt;
   194            Ptr pData;
   195            UInt16 lengthInMAUs; /*! arguments passed via Log_write/print */
   196        }
   197        /*!
   198         *  ======== maxLengthInMAUs ========
   199         *  Maximum number of MAUs (miniumum addressable units, e.g. bytes)
   200         *     supported by `LogSnapshot` events.
   201         *
   202         *  Attempting to write more than the maximum length results in the
   203         *  multiple events being logged.  The maxLengthInMAUs must be
   204         *  lower than the size of the buffer that the events are being logged to.
   205         *  Must be less than 1400 in order to support streaming of event
   206         *  data over UDP.
   207         */
   208        config Int maxLengthInMAUs = 512;
   209    
   210        /*!
   211         *  ======== isTimestampEnabled ========
   212         *  used to enable or disable logging the 64b local CPU timestamp
   213         *  at the start of each event
   214         */
   215        config Bool isTimestampEnabled = true;
   216    
   217        /*! @_nodoc
   218         *  ======== loggerDefined ========
   219         *  set to true in the configuration script when a logger that implements
   220         *  ILoggerSnapshot is attached
   221         */
   222        config Bool loggerDefined = false;
   223        /*!
   224         *  ======== loggerObj ========
   225         *  handle of the logger that is to be used to log snapshot events
   226         */
   227        config Ptr loggerObj = null;
   228    
   229        /*! @_nodoc */
   230        config ti.uia.runtime.LoggerTypes.LogMemoryRangeFxn loggerMemoryRangeFxn = null;
   231        /*======================================================================*/
   232    
   233        /*!
   234         *  ======== putMemoryRange ========
   235         *  Unconditionally put the specified `Types` event.
   236         *  Supports both writeMemoryRange and writeString.
   237         *
   238         *  This method unconditionally puts the specified memoryRange`{@link Types#Event}`
   239         *  `evt` into the log.  This type of event is created either implicitly
   240         *  (and passed to an `{@link ISnapshotLogger}` implementation) or explicitly
   241         *  via `{@link Types#makeEvent()}`.
   242         *
   243         *  @param(evt)         the `Types` event to put into the log
   244         *  @param(mid)         the module ID of the caller
   245         *  @param(snapshotId)  unique ID that binds together a series of events used to
   246         *                      log a large memory range.  Upper 16b hold the ID Tag (0 for UIA)
   247         *  @param(fileName)    the name of the file that the event was logged from
   248         *  @param(lineNum)     the line number that the event was logged from
   249         *  @param(fmt)         a user-specified print format string
   250         *  @param(startAdrs)   the start address of the memory range to log
   251         *  @param(lengthInMAUs)   the number of minimum addressable units (e.g. bytes) to log
   252         *  @a(return)          value to use as snapshotId parameter for subsequent events
   253         */
   254        @Macro Void putMemoryRange(Types.Event evt, Types.ModuleId mid,
   255          IArg fileName, IArg lineNum, UInt32 snapshotID, IArg fmt, IArg startAdrs, IArg lengthInMAUs);
   256    
   257        /*!
   258         *  ======== writeMemoryBlockWithIdTag ========
   259         *  Generate a `LogSnapshot` event for a block of memory
   260         *
   261         * @a(Examples)
   262         * Example: The following C code shows how to log a snapshot event to
   263         *   capture a block of memory.
   264         *
   265         *  @p(code)
   266         *  #include <ti/uia/runtime/LogSnapshot.h>
   267         *  ...
   268         *  UInt32* pIntArray = (UInt32 *)malloc(sizeof(UInt32) * 200);
   269         *  ...
   270         *  UInt16 myCustomIdTag = 1;
   271         *  LogSnapshot_writeMemoryBlockWithIdTag(myCustomIdTag,0,"pIntArray ptr=0x%x, numBytes=%d",(UInt32)pIntArray,200);
   272         *  ...
   273         *  @p
   274         *  The following text will be displayed for the event, if it was logged
   275         *  from file demo.c at line 1234 and all 200 bytes were logged in the
   276         *  same event.
   277         *  @p(code)
   278         *  Memory Snapshot at [demo.c:1234] [snapshotID=0,adrs=0x80002000,
   279         *    numMAUsDataInEvent=200,numMAUsDataInRecord=200] ptr=0x80002000, numBytes=200
   280         *  @p
   281         *  If the 200 bytes were spread across multiple events,
   282         *  the numMAUsDataInRecord would indicate how many bytes were in the
   283         *  memory block, and numMAUsDataInEvent would indicate how many bytes
   284         *  were stored in that particular event.
   285         *  @p
   286         *  @param(idTag)      ID used to identify who logged the event. Set to 0 for a
   287         *                     standard UIA event.  Can be used to filter snapshot events on host.
   288         *  @param(snapshotID) ID used to identify snapshot events taken at the same
   289         *                     time. Set to 0 for first in series, set rest to return
   290         *                     value of LogSnapshot API.  {@link #getSnapshotId see getSnapshotId()}
   291         *  @param(fmt)        a constant string that provides a user-readable description
   292         *                     of what information the event is capturing
   293         *  @param(pMemoryRange)  the start address of the range of memory
   294         *  @param(lengthInMAUs) the number of MAUs of data payload for the
   295         *                     multi-event data record
   296         */
   297        @Macro Void writeMemoryBlockWithIdTag(UInt16 idTag, UInt32 snapshotID, IArg fmt, Ptr pMemoryRange,
   298          UInt16 lengthInMAUs);
   299    
   300        /*!
   301         *  ======== writeMemoryBlock ========
   302         *  Generate a `LogSnapshot` event for a block of memory
   303         *
   304         * @a(Examples)
   305         * Example: The following C code shows how to log a snapshot event to
   306         *   capture a block of memory.
   307         *
   308         *  @p(code)
   309         *  #include <ti/uia/runtime/LogSnapshot.h>
   310         *  ...
   311         *  UInt32* pIntArray = (UInt32 *)malloc(sizeof(UInt32) * 200);
   312         *  ...
   313         *  LogSnapshot_writeMemoryBlock(0,"pIntArray ptr=0x%x, numBytes=%d",(UInt32)pIntArray,200);
   314         *  ...
   315         *  @p
   316         *  The following text will be displayed for the event, if it was logged
   317         *  from file demo.c at line 1234 and all 200 bytes were logged in the
   318         *  same event.
   319         *  @p(code)
   320         *  Memory Snapshot at [demo.c:1234] [snapshotID=0,adrs=0x80002000,
   321         *    numMAUsDataInEvent=200,numMAUsDataInRecord=200] ptr=0x80002000, numBytes=200
   322         *  @p
   323         *  If the 200 bytes were spread across multiple events,
   324         *  the numMAUsDataInRecord would indicate how many bytes were in the
   325         *  memory block, and numMAUsDataInEvent would indicate how many bytes
   326         *  were stored in that particular event.
   327         *  @p
   328         *  @param(snapshotID) ID used to identify snapshot events taken at the same
   329         *                     time. Set to 0 for first in series, set rest to return
   330         *                     value of LogSnapshot API.  {@link #getSnapshotId see getSnapshotId()}
   331         *  @param(fmt)        a constant string that provides a user-readable description
   332         *                     of what information the event is capturing
   333         *  @param(pMemoryRange)  the start address of the range of memory
   334         *  @param(lengthInMAUs) the number of MAUs of data payload for the
   335         *                     multi-event data record
   336         */
   337        @Macro Void writeMemoryBlock(UInt32 snapshotID, IArg fmt, Ptr pMemoryRange,
   338          UInt16 lengthInMAUs);
   339    
   340        /*!
   341         *  ======== writeStringWithIdTag ========
   342         *  Generate a `LogSnapshot` event for a string in memory
   343         *
   344         *  @a(Example)
   345         *   The following C code shows how to log a snapshot event to log the
   346         *   contents of a string in memory.
   347         *
   348         *  @p(code)
   349         *  #include <ti/uia/runtime/LogSnapshot.h>
   350         *  ...
   351         *  Void myFunc(String name){
   352         *     ...
   353         *     UInt16 myCustomIdTag = 1;
   354         *     LogSnapshot_writeStringWithIdTag(myCustomIdTag,0,"User-defined name=%s.",name, strlen(name));
   355         *  }
   356         *  @p
   357         *  The following text will be displayed for the event, if it was logged
   358         *  from file demo.c at line 1234 and all bytes in the 40 character string
   359         *  was logged in the same event.
   360         *  @p(code)
   361         *  String Snapshot at [../demo.c:1234] [snapshotID=0,adrs=0x80001234,40,40] User-defined name=ValueOfParm.
   362         *  @p
   363         *  @param(idTag)      ID used to identify who logged the event. Set to 0 for a
   364         *                     standard UIA event.  Can be used to filter snapshot events on host.
   365         *  @param(snapshotID) ID used to identify snapshot events taken at the same
   366         *                     time. Set to 0 for first in series, set rest to return
   367         *                     value of LogSnapshot API. {@link #getSnapshotId see getSnapshotId()}
   368         *  @param(fmt)        a constant string that provides a user-readable description
   369         *                     of what information the event is capturing
   370         *  @param(pString)    the start address of the string in memory
   371         *  @param(lengthInMAUs) the number of MAUs to log (e.g. strlen(pString))
   372         */
   373        @Macro Void writeStringWithIdTag(UInt16 idTag, UInt32 snapshotID, IArg fmt, Ptr pString,
   374        UInt16 lengthInMAUs);
   375    
   376        /*!
   377         *  ======== writeString ========
   378         *  Generate a `LogSnapshot` event for a string in memory
   379         *
   380         *  @a(Example)
   381         *   The following C code shows how to log a snapshot event to log the
   382         *   contents of a string in memory.
   383         *
   384         *  @p(code)
   385         *  #include <ti/uia/runtime/LogSnapshot.h>
   386         *  ...
   387         *  Void myFunc(String name){
   388         *     ...
   389         *     LogSnapshot_writeString(0,"User-defined name=%s.",name, strlen(name));
   390         *  }
   391         *  @p
   392         *  The following text will be displayed for the event, if it was logged
   393         *  from file demo.c at line 1234 and all bytes in the 40 character string
   394         *  was logged in the same event.
   395         *  @p(code)
   396         *  String Snapshot at [../demo.c:1234] [snapshotID=0,adrs=0x80001234,40,40] User-defined name=ValueOfParm.
   397         *  @p
   398         *  @param(snapshotID) ID used to identify snapshot events taken at the same
   399         *                     time. Set to 0 for first in series, set rest to return
   400         *                     value of LogSnapshot API. {@link #getSnapshotId see getSnapshotId()}
   401         *  @param(fmt)        a constant string that provides a user-readable description
   402         *                     of what information the event is capturing
   403         *  @param(pString)    the start address of the string in memory
   404         *  @param(lengthInMAUs) the number of MAUs to log (e.g. strlen(pString))
   405         */
   406        @Macro Void writeString(UInt32 snapshotID, IArg fmt, Ptr pString,
   407        UInt16 lengthInMAUs);
   408    
   409        /*!
   410         *  ======== nameOfReference ========
   411         *  Used to log the contents of a dynamic string on the heap so that host-side
   412         *  tooling can display this string as the name of handle / reference ID
   413         *
   414         *  @a(Example)
   415         *   The following C code shows how to log a task name for use by task
   416         *   execution graphs etc.
   417         *
   418         *  @p(code)
   419         *  #include <ti/uia/runtime/LogSnapshot.h>
   420         *  #include <ti/sysbios/BIOS.h>
   421         *  #include <ti/sysbios/knl/Task.h>
   422         *  ...
   423         *  // Task create hook function that logs the task name.
   424         *  // Notes: Task name is not trequired when creating a BIOS task. Please \
   425         *  // make sure a name is provided in order for the host side analysis tool
   426         *  // to work properly.
   427         *  Void  tskCreateHook(Task_Handle hTask, Error_Block *eb) {
   428         *          String name;
   429         *          name = Task_Handle_name(hTask);
   430         *          LogSnapshot_writeNameOfReference(hTask,"Task_create: name=%s",
   431         *            name,strlen(name)+1);
   432         *  }
   433         *  @p
   434         *  This event prints the Log call site (%$F) and a format string (%$S)
   435         *  which describes what information the event is logging.
   436         *  The following text will be displayed for the event:
   437         *  @p(code)
   438         *  nameOfReference at  [demo.c:line 1234] [refID=0x80002000,adrs=0x80001234,40,40] Task_create: name=10msThread.
   439         *  @param(refID)        reference ID (e.g. task handle) that the name is
   440         *                       associated with
   441         *  @param(pString)      the start address of the string on the heap
   442         *  @param(lengthInMAUs) the number of MAUs to log (e.g. strlen(pString))
   443         *  @param(fmt)          a constant string that provides format specifiers
   444         *                       describing the string
   445         */
   446        @Macro Void writeNameOfReference(UInt32 refID, IArg fmt, Ptr pString,
   447        UInt16 lengthInMAUs);
   448    
   449        /*!
   450         * ======== getSnapshotId ========
   451         * returns a unique ID to use to group a set of snapshot event logs together
   452         *
   453         * Allows tooling to treat a set of consecutive event logs as a unit and
   454         * display all of the relevent data together as a set
   455         *  @a(Example)
   456         *   The following C code shows how to log two snapshot events that capture
   457         *   the target state of two different data structures, using a common unique
   458         *   non-zero snapshot ID provided by the getSnapshotId to inform the host-side
   459         *   tooling that the events represent the target state at the same point in time
   460         *  @p(code)
   461         *  #include <ti/uia/runtime/LogSnapshot.h>
   462         *  ...
   463         *  MyStruct1 myStruct1;
   464         *  MyStruct2 myStruct2;
   465         *  UInt32 snapshotId;
   466         *  ...
   467         *  snapshotId = LogSnapshot_getSnapshotId();
   468         *  LogSnapshot_writeMemoryBlock(snapshotId,"myStruct1 ptr=0x%x, numBytes=%d",(UInt32)&myStruct1,sizeof(MyStruct1));
   469         *  LogSnapshot_writeMemoryBlock(snapshotId,"myStruct2 ptr=0x%x, numBytes=%d",(UInt32)&myStruct2,sizeof(MyStruct2));
   470         *  ...
   471         *  @p
   472         * @a(return) a unique non-zero snapshot ID to pass in as a parameter to the
   473         *    LogSnapshot APIs
   474         */
   475        @DirectCall
   476        UInt32 getSnapshotId();
   477    
   478        /*!
   479         *  ======== doPrint ========
   480         *  Render an event as text via `{@link System#printf System_printf}`
   481         *
   482         *  This method is not currently implemented.
   483         *
   484         *  @param(evRec)   a non`NULL` pointer to an initialized `
   485         *     LogSnapshot_EventRec`structure to be formated via
   486         *     {@link System#printf System_printf}`.
   487         */
   488        Void doPrint(EventRec *er);
   489    
   490        /* @_nodoc
   491         *  ======== idToInfo ========
   492         *  Map event ID strings into a string of the form <eventName>::<eventMsg>
   493         */
   494        metaonly config String idToInfo[string] = [];
   495    
   496    }