The GVPatch Implementation Manual

Steve Temple, November 2, 1982
File [Indigo]<Grapevine>Tools>GVPImpl.tioga


Introduction
  This document describes the way in which the GVPatch system is implemented and is intended to be useful should the need to alter the program arise. The programs are commented also and should be consulted in addition to this document.
  
  
System Structure
  The GVPatch system has two parts, the part which runs on the Grapevine server which is being patched is a single module called GVPServer and is described in a later part of this document. The driver program is a multi-module configuration named GVPatch which will be described shortly.

Source Files
  All sources are currently kept in the directory [Indigo]<Grapevine>Tools>, the files in this directory are as follows:
 
      GVPServer.mesa          the server program source
      GVPServer.bcd           the server program BCD (Alto-Mesa code)
      GVPServer.df             a DF describing GVPServer (for reference only)

      GVPatch.bcd              the driver program code
      GVPatch.df                DF file for GVPatch driver
      GVPatch.config           binder configuration file
      GVPDefs.mesa             Defs file for GVPatch driver
      GVPDefs.bcd              BCD for above
      GVPBrowser.mesa, bcd   implements browser mode viewer
      GVPMain.mesa, .bcd     start code and server mode viewer code
      GVPEditor.mesa, .bcd    editor mode viewer code
      GVPDriver.mesa, .bcd    implements the bytestream interface to GVPServer
      GVPProcs.mesa, .bcd     mostly heap manipulation procedures
      
      GVPatch.tioga             GVPatch User Manual
      GVPImpl.tioga             this manual
      
      GVPExternal.mesa        a sample external patching procedure


GVPatch - the driver program

  This configuration runs in the Cedar environment and provides a viewer based user interface. Five program modules are used, together with the Defs file GVPDefs. Thus all modules must be recompiled if GVPDefs but otherwise there are no compilation order requirements..

Overall approach
  The are a number of styles which are adopted throughout all the modules in the GVPatch driver. Any global state is held in one of two places, if it needs to be freely passed around it is in a record of type GVPRec, a pointer to which is an argument to many procedures. If the state is useful only within one module then it is kept in the global frame of that module. Only one instance of the GVPatch viewer is allowed, this restriction is implemented in GVPMain. In order to keep the data in global frames valid between program incarnations, each module other than GVPMain has two procedures ModuleInit and ModuleTidyUp. These are called at the start and end of each incarnation and their job is to take or give back storage and keep other state in the global frame consistent. 
  Many procedures which have a notion of success or failure communicate this by returning a ROPE with either NIL or some useful message in it. The message can then be placed on the screen or passed up to a higher level.
  The layout of each module is such that all global frame declarations appear first in the source (Mesa) file, followed by procedure declarations, then the Init and TidyUp procedures.

Module GVPDefs
  This module consists of useful system wide declarations of types and record structures and declarations of procedures which are called across module boundaries. Funnies in here include a fudge of heap object type from an enumerated type to CARDINAL and the declaration of the number of pages in a heap segment which may change from time to time. Otherwise it's all fairly straightforward and descriptions of the procedures defined in here appear in the appropriate module documentation.

Module GVPMain
  This module contains the start code for the system and is also concerned with implementing the server interface. All the procedures invoked when buttons are clicked are to be found here, in GVPEditor or in GVPBrowser. These three modules are a MONITOR and many of the button procedures are ENTRY procedures The lock is kept in GVPMain and the purpose of the monitor is to prevent certain pairs buttons being active at once. The unprotected buttons are either harmless or used to stop an already running button. The viewer itself is a container containing a label as a message window, a small viewer, and six other viewers, two for each display mode.
  Each mode has a container containing the buttons and data input viewers for that mode, and a typescript for text output. The viewers for the two modes not in use are kept off the screen and juggled around when the mode changes. The procedure MainInit builds the viewer by creating a container and the calling procedures to make viewers for each of the modes. A small viewer called focus is a fudge and used to hold the current selection while the mode is changing (gets round a viewers bug). When the main viewer is destroyed the procedure DestroyProc is called to tidy up, it calls each of the TidyUp procedures and destroys the global data record. Procedure descritions for most PROCs now follow
  
    MainInit, DestroyProc   see above
    ToFocus                     put the selection in focus while moving viewers
    Set, Flash, Failed, Fail   put various things in the message window
    GetHandle                  returns the REF to the main data record, only used once
    NumFromRope             reads octal or decimal # from given place in a rope. Returns number
                                  and end position. (/  or empty rope returns last CARDINAL)
    MakeServerButtons        called from MainInit to make buttons, note passing of data record
                                  also note that logText has the backing file GVPatch.log
    ServerButton               juggle the screen to put server mode viewer up
    other server buttons      mostly just call procedures from other modules or put selection
    ParseLength                get file length supplied, BOOL to say if OK
    ResetEdit                   clears editor typescript, moves current selection out first!
    DoIt                         the registered command, does nothing if viewer already up.
    StartPatch                  makes new record, calls each Init procedure
    
    * the start code            say we want to know if user hits destroy, register command and
                                  start the whole thing up.


Module GVPEditor
  This module implements the page editing functions of GVPatch. The main data structure is the edit buffer, a 256 word MDS zone which holds a page while it is being edited. It is referenced by pointers pageWords and pageBytes.  A 256 word SEQUENCE editModeVec contains the associated display mode for each word in the edit buffer. The SEQUENCE values holds replacement words when editing is being made (maximum 40 words). BOOLs are used to say if the buffer contains a valid page and if so, if it has been changed.
  
  MakeEditorButtons        much the same as its server counterpart
  PageOK                     called by many routines to check that buffer holds a valid page
  SelectIndex                 returns indices of first and last word touched by the current
                                  selection. Some fairly dodgy arithmetic here. Returns first>last
                                  if selection in wrong viewer or no page in buffer. Results always
                                  in [0..255]
  IndexSelect                 places selection over words [first..last], ERROR if args bad. Again 
                                  wierd arithmetic (bound to change with every Cedar release).


  Page handling buttons - all use the page read/write facilities in GVProcs  
    ResetPageButton        gets current page from server, resets display mode and various BOOLs
    GetPageButton          gets current page from local if possible else from server, then as above
    GetNextButton          calls NextItem (GVPProcs) then as GetPageButton
    GetPrevButton          calls PrevItem then as above
    NewPage                 resets things when new page in buffer, prints it

  ShowPageButton          buffer must be valid, then call ShowPageProc
  
  Data structure display buttons - all check for valid page and selection in editor typescript
    ObjectButton            must be enough room for header, 5 values is max PutFR can handle
    TimeStampButton       check that it fits, don't attempt a partial print
    SizeButton               Only sensible for the current page, lots more work to span pages
    RNameButton            proceed if at least 2 words on page

  ReplaceButton            call ParseValues to get numbers, then be careful about whether 
                                to proceed
  
  CharsButton, WordsButton  easy
  
  ExternalButton            Get capability for the bcd and try to load and start it
  GetEditBuffer              If selection is good make a SEQUENCE of the words and return REF
  PutEditBuffer              If REF#NIL make edits and log changes made
  
  EditInfo                    put what we know about the current page in our label
  
  ShowPageProc             long but straightforward. Calls to ShowHeader, Break, Look
                                 and PutNum made from here. index used to index the buffer
  Look                         change the look of subsequent chars sent to the typescript
  ShowHeader                 set bold look and then print 3 items calling Break between each
  Break                        if called with index on a line break then put a newline and 
                                  word count out in the standard look. Note pointer comparison
                                  to decide on look changes.
  PutNum                   only called for "data" words, use editModeVec to decide how to print

  ParseValues             tricky PROC reads octal nums or strings from a rope. Spaces or tabs 
                               allowed between items, last string OK without closing quote. Returns 
                               number of words needed or last CARDINAL if it didn't like something.
  EditorInit                get the storage we need, no checks made if anything fouls up here
  EditorTidyUp            just free the store


Module GVPBrowser.
  This module provides the browser mode viewer. There is a 256 word MDS zone referenced by pageBuffer used here.
  
  MakeBrowserButtons     same as others
  BrowserButton            same as others
  ShowAuto                 print the current page if autoShow flag is on
  PlaceRope                 return a rope with the current page in it
  SetLogicalButton
  SetPhysicalButton
  Reset                       these 3 all call procedures in GVPProcs
  NextButton
  PrevButton                these 2 may repeat and may do a page print when invoked
  ShowButton               use ShowAuto to print current page
  ShowModeButton
  RepeatButton
  AutoShowButton          these 3 just flip BOOLs and change their contents
  ScanErrorButton
  ScanMatchButton         mark us stoppable and call the scan routine in GVPProcs
  StopButton
  StopRequested             one sets, the other tests and clears the stop flag
  ValueButton
  RepeatCountButton
  PatternButton             just put selection in the right viewer
  GetRepeatCount           if repeat flag set return the count else return 1
  GetSearchPattern          complex. Get two nums and string, return LAST CARDINAL if /
  ObjectRope                given object type [0..15] return name as rope, can ask for full or brief
  ObjectIndex               given rope object type return [0..15], only first 3 chars count, return
                                 16 if something wrong or LAST CARDINAL if rope was /
  ShowItem                  print page according to mode flag
  PrintPageFull             print current page in max detail
  PrintPageBrief            quick summary of page contents, print position if multiple of segSize


Module GVPProcs
  This module holds a set of procedures which manipulate the local copy of the heap. The code is somewhat tricky in places. Global frame data includes  a page buffer (pageBuffer) and various SEQUENCES for tables of data.
  BitMap is such a SEQUENCE and is used when scanning to detect duplicate object numbers, the procedure SetBitFromObj sets a bit in this map and returns the old bit value. The bits are indexed via an object number.
  LList and PList are SEQUENCES of SegmentPtrs which detail the correspondence between physical segments in the heap file and their corresponding "logical" segments. LList is always indexed by a logical segment number and returns the corresponding physical segment. PList is indexed by a physical segment and does the reverse mapping. These structures are derived from the file Heap.Segments by the procedure GetChain.
  map is a SEQUENCE of CHARs which says whether a given heap page exists in full in the local heap and if so if it has been altered. This structure is copied to the file Heap.Map between sessions of GVPatch. The possible chars are "." (empty), "f" (full, unchanged) and "a" (full, altered). GetChain does the initialisation of the systems data structures opening the heap STREAM and making the SEQUENCEs LList, PList and map. It uses several MDS zones while doing this but gives them back when it finishes. Other procedures are detailed below
  
  SetLogical
  SetPhysical                 given a number, make that the current position or page.
  NextPage                    make the next position current
  PrevPage                    make the previous position current
  ResetCurrent                current _ position zero
  PositionRope                return current position for someone to read
  ReadHeapPage              put a page into callers buffer, get from local if possible else server
  ReadLocalPage              put local page into callers buffer
  WriteLocalPage             write callers buffer to local heap
  WriteHeap                  write all altered pages back to servers heap
  ScanHeap                    long and moderately simple proc runs thro heap from current place
                                   until stopped or at end. Notes possible errors and looks for search
                                   pattern if asked
  GetPageState                 returns map contents for given page
  SetPageState                  sets map contents for given page to given state
  CheckStructure              return if GetChain already called this session else call it
  
  ProcsInit                     get store for page buffer and bitmap
  ProcsTidyUp                 write the map file if necessary, close heap stream and release store


Module GVPDriver.
  This  module provides the byte stream interface to the server. Its only global data is the bytestream itself. The bytestream is closed whenever a server command fails and is reopened automatically when the next server command is attempted. Operations with the server are started by sending a command byte and then any additional data for the particular command. The server is expected to respond with either an error code (and a message) saying the command could not be performed or with the command byte and any data returned by the command. Procedures are
  
  KillByteStream              if the stream shows signs of life kill it
  CheckByteStream           if the stream appears dead open it, called by all basic routines
                                  which need to talk to the server
  ConnectToServer            open a bytestream to a server and send users name and password
  RestartServer                wrap up the command line into rem.cm, send that to the server 
                                   and then the restart command.
  ServerError                  when a command has been sent wait for error code or the 
                                    command byte to be returned. If error return the message
  GetHeapFile                 read the file Heap.Segments from the server and then the heap 
                                   structure. Make local heap.data (error if no room)  from the 
                                   structure.
  OpenFile                    open named file on the server, specify if it must be old
                                   Return length and error message (if any).
                                   File is always opened for WRITE
  SetFileLength               set the length of (already open) file on the server
  ReadPage                    read given page from server's open file
  WritePage                   write given page to server's open file
  ReadFile                     copy a server file to local with same name
  WriteFile                    obvious
  SetServerLength            open given file on the server (old only) and set its length
  SetLocalLength             set length of a local file
  ReadServerPage             open server's heap and read given page
  WriteServerPage            open server's heap and write given page
  DriverInit
  DriverTidyUp               start and stop the Pup package


Program GVPServer
  This program is written in Alto-Mesa and runs on the Grapevine server to be patched. It creates a byte stream listener on the GVPatch socket (047B) and waits for commands. A command is a byte followed by data for that command. The data is all received before anything is sent out in reply. If the command can be performed successfully the command byte is sent back to the user followed by any results. If the command fails an error code byte is sent along with a message string. When a stream is opened the first thing to be received must be the login command byte and the name and password of the user. If nobody is currently logged in to the GVPatch server this user is authenticated (must be temple.pa or in the group transport.ms) and if OK made the current user. The server now waits for commands from the use's machine.
  Only one session is allowed and so if another stream is opened by another user it is immediately closed. If another stream is opened by the same user then that is OK (we assume that his other session died at the other end and will go away soon).
  Global data is used to hold the name of the current user and info on the currently open file. Only one file may be open at once and opening a file closes the currently open one. Repeatedly opening the same file is handled efficiently.
 The program is fairly straightforward and the source should provide adequate documentation for any modifications to it.
�����ù �ÿ��ò�JöOú–bx!úOœbúÛûúÇû	úmûú#ûú◊–blúëûú£	ûúÎûú˛ûúÉûúÇûúûú„
ûúUûúÀû	úû	úûúUûú¬ûú‡ûú\û
ú∞ûú®û
ú.ûú`ûúcûúûúû
úÏûúûú„ûúûúûúûúöûú¶ûúüûúóò⁄ëó�Öó����H‹��I∫��