\begindata{text,10971136} \textdsversion{12} \template{default} \define{global } \define{concat } \define{sans } \flushright{16 July 1993 } \majorheading{Ness Hacker's Guide} \center{by Wilfred J. Hansen} \indent{\flushright{\smaller{_________________________________ Andrew Consortium Carnegie Mellon University _________________________________ }} Ness is a programming language for the Andrew ToolKit. With it, documents can be processed and can even contain active elements controlled by Ness scripts. The language features an innovative substring algebra for string processing. This document is intended for people who want to do unusual things with Ness. It describes how to extend the keyboard and menus with Ness, how to call methods and class procedures from Ness, how to access instance variables of objects, and how to utilize Ness from C code. For a description of the other Ness documents, see the \bold{Ness User's Manual}. 1. NessUseDialogBoxInsteadOfWarning 2. Accessing ATK objects: methods, class procedures, and instance variables 3. Redefining keys and menus for ATK Applications 4. Calling Ness from C code 5. Ness system files }\smaller{\ \begindata{bp,10693824} \enddata{bp,10693824} \view{bpv,10693824,70,0,0} } Copyright IBM Corporation 1988, 1989 - All Rights Reserved Copyright Carnegie Mellon University 1993 - All Rights Reserved\smaller{ \smaller{ $Disclaimer: Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice, this permission notice, and the following disclaimer appear in supporting documentation, and that the names of IBM, Carnegie Mellon University, and other copyright holders, not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. IBM, CARNEGIE MELLON UNIVERSITY, AND THE OTHER COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL IBM, CARNEGIE MELLON UNIVERSITY, OR ANY OTHER COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. $ $Log: nesshack.doc,v $ Revision 1.5 1993/07/17 04:31:45 wjh remove notes about future developments modernize layout, copyrights, etc. \begindata{bp,10694016} \enddata{bp,10694016} \view{bpv,10694016,71,0,0}}} \section{1. Ness preference options} Ness supports two preference options. When Ness scripts appear in documents or applications, they are normally surrounded with a warning text describing the dangers of freely using scripts from others. You may prefer to have a dialog box appear instead of the warning message. To get this the preference option is "NessUseDialogBoxInsteadOfWarning". To activate it, put in your ~/preferences file the line \leftindent{*.NessUseDialogBoxInsteadOfWarning: on} When you have installed this option, any Ness you encounter in documents or applications will be announced to you in a dialog box with four options: \leftindent{\sans{\bold{Ness script here. it from? Do you trust the user you got \leftindent{Cancel - Keep Ness script inactive Help - Add warning text to script Scan - Check for dangerous statements Empower - I trust the source of this script}}}} If you just want to eyeball the script, choose the first option and scroll through the Ness inset. When you are ready to compile, you can choose the compilation options from the Ness menu. Another preference option is NessPath. The value of this preference is a comma separated list of directories to be searched for library files. The default value is *.NessPath:/usr/andrew/lib/ness Incidentally: These directories are scanned once when Ness is initiated in a process. If new files are later added to the library, Ness will not learn about them; they will however, be available to proceses started after they are added. \section{2. Accessing ATK objects: methods, class procedures, and instance variables} Ness scripts may call functions defined by the ATK "class" preprocessor. Let <var>, <class>, <method>, and <proc> be identifiers and \italic{obj} an expression with an object as its value. Then: To retrieve the value of instance variable <var> of object \italic{obj} in class <class> write <class>_Get<var>(\italic{obj}) and to set the value write <class>_Set<var>(\italic{obj}, value) To call <method> in <class> on object \italic{obj} write <class>_<method>(\italic{obj}, other parameters) and to call the classprocedure <proc> in <class> write <class>_<proc>(parameter list) Before any of these can operate, the script must declare that it is going to utilize functions defined in class. This is done by writing a comment saying (exactly): --$enable class access \section{3. Redefining keys and menus for ATK Applications} During initialization, each ATK application reads ~/.atkinit or ~/.<applicationname>init if it exists. This file can contain specifications that redefine the keys and menus provided for various objects when viewed by the application. Ness can be used to write the code that is executed for these specifications. The first step is to have the ness processor available during initialization. This is done by adding to the .XYZinit file the line load ness which searches the CLASSPATH for ness.do and loads it. As it is loaded, Ness installs in the proctable the entry ness-load, which is used to load and compile Ness files which can themselves define entries in the proctable. Once Ness is loaded, the .XYZinit file can utilize ness-load to load specifications written in Ness: call ness-load /usr/andrew/lib/wc.n where the last component of the line is the filename of the Ness program. (This is Ness source code as text; it is not a Ness object.) Note that no security is applied; if your .XYZinit file loads a ness script it is compiled and its event handlers are activated without asking your permission. Ness programs utilize special \bold{extend} and \bold{on} syntax to bind key sequences and menu options to Ness code. The script extends the special name "view:\italic{viewname}", where \italic{viewname} is the name of a view class. To apply to all views, the string can be "view:view". Within such an extend block, event specifications are acceptable for \bold{on keys} and \bold{on menu}. This must be compiled BEFORE the window is created, so it is best done from call ness-load <filename> in .atkinit or one of your other .XYZinit files. For example, here is the section of /usr/andrew/lib/ness/wc.n which establishes a menu option for counting words: \example{\smaller{ extend "view:textview"\leftindent{ on menu"Search/Spell,Count Words"\leftindent{ wc_showcount()} end menu} end extend}} It is this event specification which is invoked by the lines shown above for the .XYZinit file. (As of this writing, this file contains 13993 words.) \section{4. Calling Ness from C code} A program in the C language can construct a Ness object, load it with a script, and cause its execution. First create a new instance of a ness object: \leftindent{ness_New() Ness. } returns a struct ness * pointing to a brand new The Ness object is a subclass of text, so all methods of the text data object can be used to construct the Ness script. If an argument is to be passed to the function main(), a pointer to it must be stored into the Ness. The pointer must refer to a struct nessmark value which provides the text of the argument. \leftindent{ness_SupplyMarkerArg(ness, markerptr)} The execution environment for a ness program consists of a defaulttext value and an arbiter value. The defaulttext is the one the program will refer to with the predefined variable of the same name. The arbiter is the name resolver that Ness will utilize for the \bold{extend} construct and the inset() function. There are two ways to establish this environment. Either variable can be set explicitly, or the EstablishViews method can be called to set them both. \leftindent{ness_SetArbiter(ness, arbiterp) surrounding arbiter. ness_Set DefaultText(ness, textview) defaulttext. Sets the pointer to the Sets the pointer to the ness_EstablishViews(ness, child) where the child is some view which is a child of the appropriate arbiter (or outside all arbiters, in which case it gets the default outer arbiter.) This function first sets the arbiter by scanning up the view tree from the child view. It then uses various hueristics to determine what is the defaulttext.} The ness is compiled automatically before Execution, but can be explicitly compiled: \leftindent{ness_Execute(ness, function-name) returns the error list. The ness is compiled and execution is initiated by calling the named function. By convention, the name is usually "main". If the return value is NULL, there were no errors. ness_Compile(ness) returns the error list. The Ness is compiled and not executed. If the return value is NULL, there were no errors.} To debug errors, it is preferable to install a nessview (if you have windows, a call to ness_Expose(ness) will usually display the ness). \leftindent{ness_Expose(ness) possible.} Causes the ness to be displayed if If you want the compilation to check for statements which might damage the user's environment, you can set the access level with ness_SetAccessLevel(nessobject, integer) where the access levels are defined in ness.ch: ness_codeRed, /* do not even compile */ ness_codeOrange, /* give compile errors for all modification ops */ ness_codeYellow, /* give compile errors for file system ops */ ness_codeGreen, /* prompt before first executing */ ness_codeBlue /* compile without prompting */ ness_codeUV /* no warningNotice and no dialog box */ When a compilation or execution has errors, a list of them is recorded in the struct ness object. Your program can manage this list with ClearError, NextError, and PreviousError. ness_ClearErrors(ness) Removes the list of errors; discards their space. ness_NextError(ness) returns a struct errornode *. Advances a pointer and returns the next errornode on the list. After visiting the last error, the next call returns NULL. A subsequent call will return the first error again. ness_PreviousError(ness) returns a struct errornode *. This function is the same as NexError, but it moves the pointer in the opposite direction. ness_printerrors(ness, file) returns the number of errors. errors to file. Prints the ness_PrintAllErrors(msg) returns the number of errors found. This classprocedure prints and counts all the error messages for all nesses in the process. \section{5. Ness system files} The files listed below constitute the installation of Ness. \bold{/usr/andrew/bin/nessrun} - Standalone execution of Ness programs. \bold{/usr/andrew/lib/ness} - Library of Ness functions; see nessfunc.doc. Also contains demos (next item). \bold{/usr/andrew/lib/ness/demos } Ness: A Short Tutorial. Demonstrations. See nesstut.doc, \bold{/usr/andrew/dlib/atk/} - Eleven dynamic objects constitute Ness. They are listed here with their superclasses lex.do () lexical analyzers; one for each compilation lexdef.do () classes of lexical analyzer; one for each grammar ness.do (text) the Ness compiler and interpreter nessmark.do (mark) the implementation of Ness markers nesssym.do (toksym) Ness symbol table entries nessv.do (scroll) user interface to ness.do sym.do () toksym.do (sym) symbol table entries for lex type.do (sym) parses .ch files and builds tables generic symbol table entries \bold{goodness} The Imakefile for andrew/atk/ness/objects alos includes the target 'goodness.' This program is identical to 'nessrun' except that in goodness many of the dynamic objects are statically linked instead of dynamically linked. This difference has two effects: run time: The runtime for nessrun isabout 2 seconds longer than goodness, primarily for the dynamic loading and linking. object module size: The goodness object module is 1411072 bytes unstripped and 456704 bytes when stripped. The nessrun module is 1030144 bytes unstripped and reduces to 362496 when stripped. Here are the sizes of each: \leftindent{ % \bold{size ../objects/nessrun} text data 221184 bss dec 139264 hex 22700 383148 5d8ac % \bold{size ../objects/goodness} text data 288768 bss dec 165888 hex 26756 481412 75884} The maximum memory during nessrun execution on one program was 247K, while it was only 228K for goodness on the same program. It is my guess that goodness avoids memory fragmentation by the loaded modules. \enddata{text,10971136}