RMSPAS User's Manual File: Dr:[7,37]RmsPas.Rno Author: Kurt W. Papke Date: November 24, 1980 R M S P A S U S E R M A N U A L RMSPAS User's Manual PAGE 2 1.0 Introduction When using RMS with OMSI Pascal, the user has a choice of two levels of interface. The lower level interface (RMS/Pascal) to RMS is describ ed in this document. The higher level interface (PRM) is described in document PRMPas.Doc. RMS/Pascal interface allows control of RMS on the same level as the Macro-11 interface. The user has complete a ccess to all RMS control fields and therefore must be careful to proper ly load all the necessary fields before performing any file or record operation. PRM (Pascal Record Management) is a higher level interface that loads the necessary fields for the user. PRM has more overhead (refer to PRM document) but eases the burden on th e user to remember the necessary steps in accessing RMS files. By design this document is very sketchy. For further information pertaining to usage of the RMS calls the "RMS Macro Pro grammer's Guide" should be consulted. 2.0 Interface Contents The interface is composed of three elements: 1. A set of Pascal CONSTants equivalent to the RMS Macro con stants. 2. A set of Pascal TYPEs equivalent to the RMS Macro FA B and RAB data types plus a few needed utility types. 3. A set of Macro procedures callable from Pascal that perform the RMS file and record primitives. The constant an d type declarations must be included in the Pascal source code. Th e primitive procedures may either be included as source or task-built in from a library as external procedures. 2.1 Constant Declarati ons The file containing the RMS constants is named "RMSCONST.P AS". It may be included at compile time with SLP or some other "include " processor, or it may be inserted statically with an editor. RMS Macro constants for referencing FAB or RAB contents take t he form respectively of "FB$xxx" and "RB$xxx". The form of the corr esponding Pascal constants are "FBxxx" and "RBxxx" since the Pascal language does not allow dollar signs to be imbedded in identifier s. As examples, the Macro symbol "FB$FIX" becomes RMSPAS Use r's Manual PAGE 3 "FBFIX" in Pascal and "RB$EOF" becomes "RBEOF". The list of constants i s complete for all fields in the FAB and RAB with the exception o f the STS field. The numerous error codes which may be returned by RMS may be added to the user source file at his/her discretion, or they m ay be referred to numerically. 2.2 Type Declarations The interface type declarations are contained in three files: " RMSTYPE.PAS", "FAB.PAS" and "RAB.PAS". These files may be inse rted in the same manner as the constant declarations. The "RMSTYP E.PAS" file contains declarations that are used for both the FAB and RA B, such as bytes, words, doublewords, etc. There are several dat a types in the FAB and RAB declarations which must be entered by the user. They are: 1. ^Filestring - the FAB requires a pointer to the user file name string which must be initialized by th e user. The data type is commonly defined as "ARRAY [1..15] O F CHAR". 2. ^Datarecord - the RAB requires pointers to the user record buffer. The data type is commonly a record, possibly with variants if multiple files are being accessed. 3. ^Keystring - the RAB requires a pointer to a key buffer when accessing indexed files in random mode. The data type to be defined by the user depends upon the types of keys used. Fields within the FAB and RAB data structures are accessed as normal Pascal record types. Note that data types must agree on assignments. All constants are defined as integers and many of the FAB and RAB elements are CHAR. For instance to set a FAB "o rg" field (defined as type BYTE = CHAR) an assignment such as "Fab.org := chr(fbseq)". 2.3 Primitive Procedures The primitive procedures are divided into three categories: ini tialization, file operations and record operations. The primit ives are commonly accessed as external procedures from the library file "RMSPAS.OLB". All primitives begin with the three letters "RMS " and end with the first three characters of the Macro primitive with out the dollar sign. For example "$OPEN" becomes "rmsope", "$GET" b ecomes "rmsget", etc. RMSPAS User's Manual PAGE 4 2.3.1 Initialization - Th ere is only one initialization routine, "rmsini". It has no parameters . The routine calls the RMS initialization routine "$INIT" and s ets up the GSA routine (see the section on buffer management). "R msini" also contains the "ORG$", which is currently set up to allow all sequential and indexed file operations, but no relative operations. 2.3.2 File Operations - There are three file ope ration primitives provided, all of which require the FAB as a "VAR" parameter. They are: 1. "rmsclo" - does a "$CLOSE" 2. "rmscre" - does a "$CREATE" 3. "rmsope" - does a "$OP EN" There are three additional RMS file operations that are n ot provided by the interface: "$DISPLAY", "$ERASE" and "$EXTEND". These haved not been required to date, however they may be added to the library as needed by the user. Although the "rmscre" p rimitive is provided it is currently able to create only sequential files, the reason being that an XAB data structure is not provided i n the interface to allow key specifications. All applications to date have used only indexed files which were previously created usin g the RMS utility program "RMSDEF". There is nothing in the st ructure of the interface however to prevent the extension to providing XAB's to allow users to create indexed files on the fly. 2.3.3 Record Operations - There are nine record operation p rimitives provided by the interface, all of which require the RAB as a "VAR" parameter. They are: 1. "rmscon" - does a "$ CONNECT" 2. "rmsdel" - does a "$DELETE" 3. "rm sdis" - does a "$DISCONNECT" 4. "rmsfin" - does a "$FIND" 5. "rmsflu" - does a "$FLUSH" 6. "rmsget" - does a "$GET" RMSPAS User's Manual PAGE 5 7. "rmsput" - does a "$PUT" 8. "rms rew" - does a "$REWIND" 9. "rmsupd" - does a "$UPDATE" There are four additional RMS record operations that are not provided by the interface. They are: "$FREE", "$NXTVOL", "$T RUNCATE" and "$WAIT". These haved not been required to date, howeve r they may be added to the library as needed by the user. 3.0 Bu ffer Management The RMS/Pascal interface employs the Pascal He ap for dynamic buffer allocation. The "rmsini" call to initialize RMS sets up a GSA routine which maps all RMS requests for buffer space to calls to the Pascal Operating-Time-System ($NEW and $DISPOSE). There are three ramifications of this technique: 1. The user does not have to hassle with the formulas for b uffer allocation. All buffers are obtained transparently to t he Pascal program. 2. As of release 1.2 of the OMSI compiler the task will automatically extend itself if it runs out of heap space up to the limit set by MAXEXT. Note however th at the task will NOT shrink as RMS gives up the buffers. 3. The GSA routine makes its requests for space to an internal routine which will NOT abort the task if the MAXEXT limit of the task is reached. Rather the GSA routine returns an error to RMS which in return sets the STS field in the FAB or RAB to ER$DME (-480.), hopefully allowing the task to recover gracefully !! 4.0 FAB and RAB Ini tialization The user must initialize ALL fields in the FAB's and RAB's used in his/her programs except for the "bid" and "bln " fields. Since these are the same for all programs, they are initializ ed by the "RmsOpe" and "RmsCon" procedures. APPENDIX A RMSCONST. PAS fbdel = 4B; { fab fac field: delete access } fbget = 2B; { fab fac field: get access } fbput = 1B; { fab fac field: put access } fbrea = 42B; { fab fac field: read access } fbtrn = 20B; { fab fac field: truncate access } f bupd = 10B; { fab fac field: update access } fbwrt = 41B; { fab fac field: write access } fbctg = 200B; { fab fop field: contiguous file } fbdfw = 20000B; { fab fop field: deferred write } fbd lk = 20B; { fab fop field: unlock } fbfid = 10000B; { fab fop fiel d: open by file id } fbmkd = 4000B; { fab fop field: mark for delete } fbnef = 1000B; { fab fop field: no EOF on magtape } fbpos = 10B; { fab fop field: position to last file } fbrwc = 2B; { fab fop field: rewind mag tape on close } fbrwo = 1B; { fab fop fi eld: rewind mag tape on open } fbsup = 400B; { fab fop field: supers ede if explicit vrsn } fbtmd = 6000B; { fab fop field: temp file - de lete on close } fbtmp = 2000B; { fab fop field: temp file - no delete } fbseq = 0; { fab org field: sequential } fbrel = 20B; { fab org field: relative } fbidx = 40B; { fab org field: inde xed } fbfix = 1B; { fab rfm field: fixed length records } fbwrt = 41B; { fab shr field: write sharing } rbkey = 1B; { r ab rac field: random access } rbrfa = 2B; { rab rac field: record' s file address } rbseq = 0; { rab rac field: sequential access } rbeof = 1B; { rab rop field: position to eof for append } rbfdl = 10000B; { rab rop field: fast delete } rbkge = 2000B; { rab rop field: >= key value } rbkgt = 4000B; { rab rop field: > key valu e } rbmas = 2B; { rab rop field: mass insert } rbloa = 20 B; { rab rop field: obey fill numbers on load } rbloc = 100B; { rab rop field: locate mode (vs. move mode } ereof = -592; { rab sts field: end-of-file } APPENDIX B RMSTYPE.PAS byte = char; word = integer; doubleword = { 2 words (VBN) } RECORD low : word; high : word END; { doubleword record } tripleword = { 3 words (RFA) } RECORD l ow : word; middle : word; high : word END; { tripleword record } fabptr = ^fabrec; { pointe r to fab } APPENDIX C FAB.PAS fabrec = RECORD bid : byte; { Fab identifier } bln : byte; { Rab length } ctx : word; { Available to user } ifi : word; { Pointer to ifab } sts : word; { Completion code } stv : word ; { More error information } alq : doubleword; { Allocati on quantity } deq : word; { * Automatic extension quantity } fac : byte; { Types of record operations } shr : byte; { File sharing } fop : word; { File processing options } rtv : byte; { Window size } org : byte; { * File organization } rat : byte; { * Record attributes } rfm : byte; { * Record format } xab : word; { Pointer to first xab } bpa : word; { Location of private I/O buffer } bps : word; { Size of private I/O buffer } mrs : word; { * Maximum record size } mrn : doubleword; { * Maximum record number } jnl : word; { Undocumented field (journal?) } n am : word; { Pointer to nam block } fna : ^filestring; { L ocation of filespec } dna : word; { Location of filepsec d efaults } fns : byte; { Size of filespec } dns : byte; { Size of filespec defaults } bls : word; { * Block size } fsz : byte; { * Size of fixed area for VFC } bks : byte; { * Bucket size } dev : byte; { Device characteristics } lch : byte; { Logi cal channel } jnk : ARRAY [1..34B] OF char END; { fa b rec } * Indicates field filled in by RMS on file open (RmsOpe) APPENDIX D RAB.PAS rabrec = RE CORD bid : byte; { rab block identifier } b ln : byte; { rab block length } ctx : word; { user defineable area } isi : word; { pointer to irab } sts : word; { completion status code } stv : word; { status value } rfa : tripleword; { record's file addres s } rac : byte; { record access mode } ksz : byte; { key buffer size } rop : word; { record pr ocessing options } usz : word; { input record buffer size } ubf : ^datarecord; { input record buffer address } rsz : word; { size of output record } rbf : ^datarecord ; { output record address } kbf : ^keystring; { key buffer addre ss } krf : byte; { key of reference } mbf : byte; { multibuffer count } mbc : byte; { multiblo ck count } jnk1 : byte; { not used } rhb : w ord; { fixed control area buffer } fab : fabptr; { fa b address } bkt : doubleword; { record number or VBN } jnk2 : ARRAY [1..46B] OF byte; { not used } END{ rab record } APPENDIX E Example RMS Pascal Program PROGRAM RM SPRG; { Program to demonstate use of the R MS/Pascal interface. Echoes lines typed on the terminal until ctrl Z ( end-of-file). } CONST fbdel = 4B; { f ab fac field: delete access } fbget = 2B; { fab fac field: get acc ess } fbput = 1B; { fab fac field: put access } fbrea = 42B; { fab fac field: read access } fbtrn = 20B; { fab fac field : truncate access } fbupd = 10B; { fab fac field: update access } fbwrt = 41B; { fab fac field: write access } fbctg = 200B ; { fab fop field: contiguous file } fbdfw = 20000B;{ fab fop field: deferred write } fbdlk = 20B; { fab fop field: unlock } fbfid = 10000B;{ fab fop field: open by file id } fbmkd = 4000B; { f ab fop field: mark for delete } fbnef = 1000B; { fab fop field: no EO F on magtape } fbpos = 10B; { fab fop field: position to last file } fbrwc = 2B; { fab fop field: rewind mag tape on close } fbrwo = 1B; { fab fop field: rewind mag tape on open } fbsup = 400B; { fab fop field: supersede if explicit vrsn } fbtmd = 6000B; { fab fop field: temp file - delete on close } fbtmp = 2000B; { fab fo p field: temp file - no delete } fbseq = 0; { fab org field: sequ ential } fbrel = 20B; { fab org field: relative } fbidx = 40B; { fab org field: indexed } fbfix = 1B; { fab rfm field: f ixed length records } rbkey = 1B; { rab rac field: random access } rbrfa = 2B; { rab rac field: record's file address } r bseq = 0; { rab rac field: sequential access } rbeof = 1B; { r ab rop field: position to eof for append } rbfdl = 10000B;{ rab rop f ield: fast delete } rbkge = 2000B; { rab rop field: >= key value } rbkgt = 4000B; { rab rop field: > key value } rbmas = 2B; { rab rop field: mass insert } rbloa = 20B; { rab rop field: obey fill numbers on load } rbloc = 100B; { rab rop field: locate mode (v s. move mode } Example RMS Pascal Program PAGE E-2 ereof = -592; { rab sts field: end-of-file } TYPE byte = char; word = integer; doubleword = { 2 words (VBN) } RECORD low : word; high : word END; { doubleword record } tripleword = { 3 words (RFA) } RECORD low : word; middle : word; high : word END; { triplew ord record } fabptr = ^fabrec; { pointer to fab } fab rec = RECORD bid : byte; { Fab identifier } bln : byte; { Rab length } ctx : word; { Available to user } ifi : word; { Pointer to ifab } sts : word; { Completion code } stv : word; { More error information } alq : doubleword; { Allocation quantity } deq : word; { * Automatic extension quantity } fac : byte; { Types of record operations } shr : byte; { File sharing } fop : word; { File pro cessing options } rtv : byte; { Window size } org : byte; { * File organization } rat : byte; { * Record attributes } rfm : byte; { * Record format } xab : word; { Pointer to first xab } bpa : wo rd; { Location of private I/O buffer } bps : word; { Size of private I/O buffer } mrs : word; { * Maximum rec ord size } mrn : doubleword; { * Maximum record number } jnl : word; { Undocumented field (journal?) } nam : word; { Pointer to nam block } fna : ^filestring; { Loca tion of filespec } dna : word; { Location of filepsec defa ults } fns : byte; { Size of filespec } dns : byte; { Size of filespec defaults } bls : word; { * Block size } fsz : byte; { * Size of fixed area for VF C } bks : byte; { * Bucket size } dev : byt e; { Device characteristics } lch : byte; { Logical channel } jnk : ARRAY [1..34B] OF char END; { fab r ec } rabrec = RECORD bid : byte; { rab block identifier } Example RMS Pascal Program PAGE E-3 bln : byte; { rab block length } ctx : word; { user defineable area } isi : word; { poi nter to irab } sts : word; { completion status code } stv : word; { status value } rfa : tripleword; { record's file address } rac : byte; { record access mod e } ksz : byte; { key buffer size } rop : w ord; { record processing options } usz : word; { in put record buffer size } ubf : ^datarecord; { input record buffer address } rsz : word; { size of output record } rbf : ^datarecord; { output record address } kbf : ^keystri ng; { key buffer address } krf : byte; { key of reference } mbf : byte; { multibuffer count } mbc : byte; { multiblock count } jnk1 : byte; { not used } rhb : word; { fixed control area buffer } fab : fabptr; { fab address } bkt : doubleword; { record nu mber or VBN } jnk2 : ARRAY [1..46B] OF byte { not used } END; { rab record } filestring = ARRAY [1..3] OF char; datarecord = ARRAY [1..80] OF char; keystring = integer; { dummy data type } VAR fab:fabrec; rab:rabrec; filename : filestring; buffer : datar ecord; PROCEDURE rmsini; EXTERNAL; PROCE DURE rmsope(VAR fab : fabrec); EXTERNAL; PROCEDURE rmscon(VA R rab : rabrec); EXTERNAL; PROCEDURE rmsget(VAR rab : rabrec ); EXTERNAL; PROCEDURE rmsput(VAR rab : rabrec); EXTERNAL; PROCEDURE rmsclo(VAR fab : fabrec); EXTERNAL; Example RMS Pascal Program PAGE E-4 BEGIN { rmsprg } rmsini; { Init RMS } filename := 'TI:'; { Set the file name } fab.fna := @filename; { Set the file name pointer } fab.fns := chr(3); { Set the file name length } fab.l ch := chr(7); { Set the LUN } rmsope(fab); { Open the f ile } IF fab.sts <> 1 THEN writeln('$OPEN error. STS: ', fab.sts:1, ' STV: ',fab.stv:1); rab.usz := 80; { Set us er buffer size } rab.ubf := @buffer; { Set user buffer address } rab.rsz := 80; { Set record buffer size } rab.rbf := @buffe r; { Set record buffer address } rab.fab := @fab; { set FAB address } rmscon(rab); { Connect access stream } IF rab.sts <> 1 THEN writeln('$CONNECT error. STS: ',rab.sts:1, ' STV: ',rab.stv:1); REPEAT rmsget(rab); { G et a line from the terminal } writeln(buffer:72) { Echo it back o ut } UNTIL rab.sts <> 1; writeln('$GET error. STS: ',rab .sts:1, ' STV: ',rab.stv:1); END. { rmsprg } APPENDIX F Example RMS Pascal Program PROGRAM Spell; { * Program to demonstate use of the RMS/Pascal interface. * Performs a rudimentary spelling check on a text file. * * Spelling checking is done by looking up each word of the input file * in a dictionary file. If the word i s in the dictionary, the * spelling is correct. If the word is not in t he dictionary, the * operator is asked if the word is spelled correctly. If he answers * affirmatively, the word is added to the dictionary. * * The dictionary file contains three fields: * * Key: A character string of "MaxWord" length. This is the * actual word. It is the primary key of the indexed * file. * Usage: An integer with value = (9999-number times ac cessed) * This program only initializes this field, but does * not update it. This is a hook which will allow a * caching algorithm to be implemented at a later time . * * Verifier: The initials of the person who verified (with * Datatrieve) that the spelling of this dictionary * entry was correct. * * This program requires the fo llowing task-build commands: * * >TKB * TKB>SPE LL/CP/FP=SPELL,RMSPAS/LB,PASLIB/LB,RMSLIB/LB * TKB>/ * TKB>UNITS=7 * TKB>TASK=...SPE * TKB>// * > * * The ordering of the input files to TKB is importa nt. If Paslib Example RMS Pascal Program PAGE F-2 and * Rmslib are reversed multiple definitions of the core allocation * routines will result * * Note that as with all programs using t he RMS/Pascal interface the * dictionary must be pre-defined with RMSDEF , RMSDFN or Datatrieve. } CONST MaxWord = 26; { Maximum word length for spelling check } FileNameLength = 15; {-- RMS symbol definitions --} fbdel = 4B; { Fab fac field: delete access } fbget = 2B; { Fab fac field: get access } fbput = 1B; { Fab fac field: put access } fbrea = 42B; { Fab fac field: read access } fbtrn = 20B; { Fab fac field: truncat e access } fbupd = 10B; { Fab fac field: update access } fbwrt = 41B; { Fab fac field: write access } fbctg = 200B; { Fab fop field: contiguous fi le } fbdfw = 20000B;{ Fab fop field: deferred write } fbdlk = 20B; { Fab fop field: unlock } fbfid = 10000B;{ Fab fop field: open by file id } fbm kd = 4000B; { Fab fop field: mark for delete } fbnef = 1000B; { Fab fop field : no EOF on magtape } fbpos = 10B; { Fab fop field: position to last file } fbrwc = 2B; { Fab fop field: rewind mag tape on close } fbrwo = 1B; { Fab fop field: rewind mag tape on open } fbsup = 400B; { Fab fop field: s upersede if explicit vrsn } fbtmd = 6000B; { Fab fop field: temp file - delet e on close } fbtmp = 2000B; { Fab fop field: temp file - no delete } fbseq = 0; { Fab org field: sequential } fbrel = 20B; { Fab org field: relat ive } fbidx = 40B; { Fab org field: indexed } fbfix = 1B; { Fab rfm f ield: fixed length records } rbkey = 1B; { Rab rac field: random access } rbrfa = 2B; { Rab rac field: record's file address } rbseq = 0; { R ab rac field: sequential access } rbeof = 1B; { Rab rop field: position to eof for append } rbfdl = 10000B;{ Rab rop field: fast delete } rbkge = 20 00B; { Rab rop field: >= key value } rbkgt = 4000B; { Rab rop field: > key va lue } rbmas = 2B; { Rab rop field: mass insert } rbloa = 20B; { Rab r op field: obey fill numbers on load } rbloc = 100B; { Rab rop field: locate mode (vs. move mode } ereof = -592; { Rab sts field: end-of-file } errnf = -1472;{ Rab sts field: record not found } TYPE Byte = char; Word = inte ger; DoubleWord = { 2 words (VBN) } RECORD Low : Word; Example RMS Pascal Program PAGE F-3 High : Wor d END; { doubleword record } TripleWord = { 3 words (RFA) } RECORD Low : Word; Middle : Word; High : Word END; { tripleword record } Fabptr = Fabrec; { pointer to Fab } Fabrec = RECORD bid : byte; { Fab identifier } bln : byte; { Rab length } ctx : word; { Available to user } ifi : wo rd; { Pointer to iFab } sts : word; { Completion code } stv : word; { More error information } alq : doubleword; { Al location quantity } deq : word; { * Automatic extension quantity } fac : byte; { Types of record operations } shr : byte; { File sharing } fop : word; { File processing options } rtv : byte; { Window size } org : byte; { * File organiza tion } rat : byte; { * Record attributes } rfm : byte; { * Record format } xab : word; { Pointer to first xab } bpa : word; { Location of private I/O buffer } bps : word; { Size of private I/O buffer } mrs : word; { * Maximum record siz e } mrn : doubleword; { * Maximum record number } jnl : word; { Undocumented field (journal?) } nam : word; { Pointer to nam block } fna : ^filestring; { Location of filespec } dna : word; { Location of filepsec defaults } fns : byte; { Size of file spec } dns : byte; { Size of filespec defaults } bls : word ; { * Block size } fsz : byte; { * Size of fixed area for V FC } bks : byte; { * Bucket size } dev : byte; { Dev ice characteristics } lch : byte; { Logical channel } jnk : ARRAY [1..34B] OF char END; { Fab rec } Rabrec = RECORD bid : byte; { Rab block identifier } bln : byte; { Rab block l ength } ctx : word; { user defineable area } isi : word; { pointer to iRab } sts : word; { completion status code } stv : word; { status value } rfa : tripleword; { record's fi le address } rac : byte; { record access mode } ksz : byte; { key buffer size } Example RMS Pascal Program PAGE F-4 rop : word; { record processing options } usz : word; { input record buffer size } ubf : ^datarecord; { input reco rd buffer address } rsz : word; { size of output record } r bf : ^datarecord; { output record address } kbf : ^keystring; { key buff er address } krf : byte; { key of reference } mbf : byte; { multibuffer count } mbc : byte; { multiblock count } jnk1 : byte; { not used } rhb : word; { fixed control area buffer } Fab : Fabptr; { Fab address } bkt : doubleword; { record number or VBN } jnk2 : ARRAY [1..46B] OF byte { not used } EN D; { Rab record } FileString = ARRAY [1..FileNameLength] OF char; Words = ARRAY [1..MaxWord] OF char; Initials = ARRAY [1..3] OF char; DataRecord = RECORD Key : Words; { Primary key = the word itself } Usage : integer; { Usage count - common words bubble up } Verifier : Initials; END; { RECORD } KeyString = Words; VAR Fab:Fabrec; Rab:Rabrec; FileName : FileString; Buffer : DataRecord; Ch : char; length,i : integer; Key : Words; InFile : Text; PROCE DURE rmsini; EXTERNAL; PROCEDURE rmsope(VAR Fab : Fabrec); EXTERNAL; PRO CEDURE rmscon(VAR Rab : Rabrec); EXTERNAL; PROCEDURE rmsget(VAR Rab : Rabrec ); EXTERNAL; PROCEDURE rmsput(VAR Rab : Rabrec); EXTERNAL; PROCEDURE rms clo(VAR Fab : Fabrec); EXTERNAL; BEGIN { Spell } rmsini; { Init RMS } FileName := 'DICO.DAT ';{ Set the file name } Fa b.fna := @FileName; { Set the file name pointer } Fab.fns := chr(8); { Set the file name length } Example RMS Pascal Program PAGE F-5 Fab.lch := chr(7); { Set the LUN } Fa b.fac := chr(fbget OR fbput);{ Ask for write access } Fab.fop := fbdlk; { Don't lock on abort } RmsOpe(Fab); { Open the fil e } IF Fab.sts <> 1 THEN writeln('Dictionary $OPEN error. STS: ',Fab.sts :1,' STV: ',Fab.stv:1) ELSE BEGIN Rab.ubf := @Buffer; { Se t user buffer address } Rab.usz := MaxWord+5; { Set user buffer size } Rab.rbf := @Buffer; { Set record buffer address } Rab.Fab := @Fab; { Set Fab address } Rab.kbf := @Key; { Set Key buffer address } Rab.krf := chr(0); { Set key of reference = primary } Rab.rac := chr(rbkey); { Set random access } Rab.rop := 0; { Zero record operations options } rmscon(Rab); { Connect access stream } IF Rab.sts <> 1 THEN writeln('Dictionary $CONNECT error. STS: ',Rab.sts:1,' STV: ',Rab.stv:1) ELSE BEGIN FOR i := 1 TO FileNameLength DO FileName[i] := ' '; IF Input^ <> ' ' THEN BEGIN REPEAT Read(ch); UNT IL (Input^ = ' ') or Eoln; IF NOT Eoln THEN REPEAT Read(ch); UNTIL (Input^ <> ' ') OR Eoln; EN D; IF (Input^ = ' ') OR Eoln THEN Write ('SPE> '); IF Eoln THEN Re adln; Readln(FileName); Reset(InFile, FileName); WHILE NOT Eof(InFile) DO BEGIN REPEAT i := 0; R EPEAT Read(InFile,Ch); IF (('A' <= Ch) AND (Ch <= 'Z ')) OR (('a' <= Ch) AND (Ch <= 'z')) THEN BEGIN i := i + 1; IF (('A' <= Ch) AND (Ch <= 'Z')) THE N Key[i] := Ch ELSE Key[i] : = chr( ord('A') - ord('a') + ord(Ch) ) END UNTIL ((i > 0) AND NOT((('A' <= Ch) AND (Ch <= 'Z')) OR (('a' <= Ch) AND (C h <= Example RMS Pascal Program PAGE F-6 'z')))) OR (i = MaxWord) OR Eof(InFile); UNTIL (i > 1) OR Eof(InFile); Length := i; WHILE i < MaxWord DO BEGIN i := i + 1; Key[i] := ' ' END; { WHILE } Rab.Ksz := chr(MaxWord); Rab.usz := MaxWord+5; { Set user buffer size } Rab.rsz := Rab.usz; RmsGet(Rab ); IF (Rab.sts < 1) AND (Rab.sts <> errnf) THEN Writeln('D ictionary $GET error. STS: ',Rab.sts:1,' STV: ',Rab.stv:1) ELSE IF R ab.sts = errnf THEN BEGIN Writeln('Word "',key:length,'" is not in the dictionary.'); Write('Should it be (is it spelled cor rectly !!) [Y/N]? '); Readln(Ch); IF (Ch = 'y') OR (ch = 'Y') THEN BEGIN Buffer.Key := Key; Bu ffer.Usage := 9999; Buffer.Verifier := ' '; Rab.usz := MaxWord+5; { Set user buffer size } Rab.rsz := Rab.usz; RmsPut(Rab); IF Rab.Sts < 1 THEN Wri teln('$PUT error. STS: ',Rab.sts:1,' STV: ',Rab.stv:1) END END END; { WHILE } RmsClo(Fab) END END END. { Spell }