OpenAccess Wiki for Public View/Login Edit

Si2oaD/User Extensions

From oacwiki

Jump to: navigation, search

The native Si2oaD code is extendable in a few, limited ways. User-defined viewers for byte-type Prop or AppDef data, and CMaps, as well as Observer implementation code can be hooked into the OAD library at run-time. Sort routines for Object Collections can be defined, as well.

Contents

1 Prop/AppDef Data

AppProp, DataAppDef, and VarDataAppDef values can be arbitrarily long. Mindlessly displaying them on the console or GUI could cause an excess of output. The maxextdata option sets a limit on how much of this data to show. A setting < 1 will force all data to be displayed. Any positive value will show only that number of bytes with a trailing "..." sentinel to indicate the rest of the data was truncated in the display. In GUI interactive mode, clicking on these dots will cause a callback for the full wad of data to be displayed in a separate window.

  • If the dlldatadisp option is not "0", it must be the path of a DLL to be loaded. If the first character is a "$" the rest is interpreted as an environment variable, which will be accessed for the actual path. That DLL must implement a function with "C" linkage, which will be called to display truncated data as. The declaration for this function is as follows, with 0 to be returned on successful display, and any other return value fed back to the OAD user via log message:
    int oadViewData( oaByte *val, oaUInt4 size );
  • If the dlldatadisp option is "0", then a click on truncated data sentinel will cause the data to be written to a file and the path specified by the sysdatadisp option will be executed in a system() call, passing to it the name of that file as an argument. Since the dlldatadisp DLL is always checked first, if it is set, even if sysdatadisp is also set, it is ignored.

The DLL is loaded as a result initial setting or changing of dlldatadisp option. Any DLL already loaded as a result of this option setting is first unloaded, and the current value of the option is used as a path to load a new DLL, called in subsequent requests to display truncated extension data.

2 CMap

Currently, there is no way to get CMap data into console [file] output. The cmap attribute, essentially a sentinal for the CMap data itself, is always displayed with the value, "...". There is no public API method for uncovering which layerNums have CMap data. This must be specified by the user and currently can only be accomplished via input to a javascript prompt when the sentinel is clicked. The layerNum solicited by this dialog is passed via callback to a either a DLL or system executable for display in a separate window.

  • If the dllcmapdisp option is not "0", it must be the path of a DLL to be loaded. If the first character is a "$" the rest is interpreted as an environment variable, which will be accessed for the actual path. That DLL must implement a function with "C" linkage, which will be called to display CMap data for the specified layerNum. The declaration for this function is as follows, with 0 to be returned on successful display, and any other return value fed back to the OAD user via log message:
    int oadViewCMap( oaCMap *cmap, oaLayerNum layerNum );
  • If the dllcmapdisp option = "0", then a click on truncated data sentinel will cause the data to be written to a file and the path specified by the syscmapdisp option will be executed in a system() call, passing to it the name of that file as an argument. Since the dllcmapdisp DLL is always checked first, if it is set, even if syscmapdisp is also set, it is ignored.

The DLL is loaded as a result initial setting or changing of dlldatadisp option. Any DLL already loaded as a result of this option setting is first unloaded, and the current value of the option is used as a path to load a new DLL, called in subsequent requests to display CMap data.

3 Observers

Observers can be linked with an application to create useful trace output even without ever calling an oad() function to dump data. Alternatively, the observer implementation code itself might include oad() calls to display selected Objects. The implementation is arbitrary and could even include code that changes the RTM, though that would be at odds with the overall spirit of OAD as a diagnostic, rather than editing tool.

Note that traversing the model as a result of an oad() call will cause firing of the relevant Observers injected via this technique.

The si2dis/si2oadObserve.cpp file has a skeleton implementation of an Observer that can be used to track events as the application runs. The file that implements the Observer code can have any name; however, it must be linked as a shared object (DLL). If the observer option is set to the path of this DLL, then Si2oaD will open it as the application is loaded into memory.

3.1 Declarations

The declarations for the Observer variables should be global (static) in that compilation module (or otherwise allocated as a result of initialization) to give the Observers a chance to be registered as the DLL is loaded.

  • If declared in static scope, the Observers will be unregistered automatically when the Si2oaD option is set to 0 and the DLL is unloaded.
  • If the Observer variables are allocated, then they will continue to be registered even though the DLL is unloaded, unless the Observer class destructor explicitly frees them.

3.2 Events

Most oaObjects have standard notifications that will only fire if the Object is created/destroyed/modified – meaningful if Si2oaD is linked with an application that performs such actions. Observers for Objects that have postOpen, preDestroy, or similar events, will fire simply as a result of Si2oaD traversal activity, even with the stand-alone, persistent OA data display tool.

3.3 Example

The following console output illustrates selective load/register and unload/unregister of an Observers DLL to capture/ignore the Prop create events of the application (with some lines omitted and replaced by "..."):

[q@localhost si2distest]$ make gdb
...
Breakpoint 1 at 0x8063039: file testcase.cpp, line 32.
No observers library was loaded.
Breakpoint 1, main (argc=1, argv=0xbfffafc4) at testcase.cpp:32
32 if ( argc > 1 ) {
(gdb) call oad("w") <------- Export current options settings
Write option settings to replace file path/name [or ? to cancel] oad.conf
(Point option 26 to a DLL that implements desired Observer code)
(gdb) shell sed 's;26.*;26 ../si2dis/si2oadObserve.so;' oad.conf >oadObs.conf
(gdb) call oad("r") <------- Load the changed options settings
Read in option settings from file path/name [or ? for NONE] oadObs.conf
Opening ../si2dis/si2oadObserve.so <-------- User Observer code being loaded
Constructing Observer<oaProp> priority=4 <-- Observers being registered
Loaded dllObservers OK.
(gdb) b 59
c
Breakpoint 2 at 0x8063280: file testcase.cpp, line 59.
(gdb) Continuing.
onPostCreate: propName=iprop1mod <---------- Observers firing
onPostCreate: propName=iprop2mod
onPostCreate: propName=iprop1block
Breakpoint 2, main (argc=1, argv=0xbfffafc4) at testcase.cpp:59
59*iProp2block = oaIntProp::create( block, "iprop2block", 72 ),
(gdb) call oad("r") <---------- Reload options file prior to change
Read in option settings from file path/name [or ? for NONE] oad.conf
Closing observers library ... <---------- User Observer code being unloaded
Destructing Observer<oaProp> <---------- Observers being unregistered
(gdb) n <---------- No more Observer firing
60*iProp2ablock = oaIntProp::create( iProp2block, "iprop2ablock", 752 ),
(gdb) n <---------- No more Observer firing
61*iProp2a1block = oaIntProp::create( iProp2ablock, "iprop2a1block", 725 );
(gdb) call oad(iProp2ablock)
<oaIntProp id='b75d0296' name='iprop2ablock' valueAsStr='752' value='752'/>

4 Sort DLLs

In GUI mode, CONTROL-click on the leading + or – of a Collection entry will pop up a dialog box to solicit not only a regex filter, but a SELECT list from which a sort routine can be selected to present the Objects in a particular order. Collections can be sorted and resorted according to different criteria, and in combination with different regex filters selected in the same pop-up.

Each of the sort methods listed in the SELECT box corresponds to a DLL defined with a single entry point with the prototype:

void sortObjects( oaObject **objArray, int nObjs )

The DLL must be declared with extern“C” linkage since dlopen() loads it. The DLL may use any method to organize the array of Objects in the Collection to be sorted. The following example sort DLLs are included in the distribution as examples:

  • si2oadSortName.cpp uses Object names as the sort key. It reuses the getNameFromObject() method and so must include “si2oadglob.h”.
  • si2oadSortOaTypeName.cpp uses oaType.getName() values as sort keys.
  • si2oadSortInfoType.cpp uses the “information” type of the Object as a sort key − an arbitrary designation that means termType for Terms and sigType for Nets (and is ignored for other Types).

The paths to these are listed (a complete path name could be included if they were not in the current directory), separated by commas, as the value of the dllsorters option. Each time the options file is read, the template for the regexChoices.html popup dialog is recreated in outputpath filled in with the current list of these sort DLLs.

Any number of custom sort DLLs can be loaded dynamically to a running OAD process by setting (or changing) the dllsorters option in the .si2oadoptions file either in advance of an OAD session or dynamically when control has returned to the command line.

Personal tools