.first title
.no number
.page size 45, 70
.set paragraph 0

.set date 7, 10, 1986
.title Using the DEC/CMS Callable Interface

.figure 10
.center; Using the CMS Callable Interface
.center; LT101
.center; Tuesday October 7, 1986
.center; 10:00 a.m. - 10:30 a.m.
.blank
.center; Del Merritt
.center; Computer Sciences Corporation
.center; Moorestown, NJ

.page
.list 'o'
.le
Overview
.list 0 '-'
.le
Reasons to use the CMS callable interface

.le
What the CMS callable interface is

.end list

.le
VAX FORTRAN Examples
.list 0 '-'
.le
CMS$SET__LIBRARY
.le
CMS$SHOW__GENERATION
.le
CMS$GET__STRING
.le
CMS$FETCH__OPEN
.le
CMS$FETCH__GET
.le
CMS$FETCH__CLOSE
.end list

.le
Conclusion
.list 0 ' '
.le
'_+'s
.le
'-'s
.le
Bugs
.end list

.le
Questions?

.end list

.page
.title Reasons to use the CMS callable interface
.fill .justify

.list 'o'
.le
Providing special source auditing tools to generate reports

.le
Adding additional tracking information to library insertions

.le
Adding  security features that the present implentation of the DCL interface
lacks, like:
.list 0 '-'
.le

a "UAF" for a library to allow users different accesses to CMS elements

.le

notifying a library manager of changes to the library AS THEY HAPPEN  

.end list

.le
Generating  your  own  interface if you can't stand DEC's

.le

Provide input to compilers that are smart enough to get information from the
library. That way, source may live in just ONE place. (that's a hint, DEC...)

.end list

.page
.title What the CMS Callable Interface Is
.list 'o'
.le

A set  of  entry  points  into  the  CMS  sharable  image for each DCL-level
command.   Most   routines   are   named   after   the   DCL  command  (eg.,
CMS_$SHOW__GENERATION)

.le

Many routines  allow  you to specify your own output and/or message handling
routines

.le

Additional routines to:
.list 0 '-'
.le
FETCH an element a line at a time
.le
translate strings returned from or given to CMS
.end list 0

.le

Programs using  the callable interface can exist with each other and the DCL
interface;  both use the CMS sharable image

.end list

.p

At our  site,  we  have a "special" version of CMS (S2.1-3), and are running
VMS V4.3.

.page
.title Callable CMS routines
.no justify .no fill

CMS$ANNOTATE
CMS$DIFFERENCES
CMS$FETCH
CMS$FETCH__CLOSE
CMS$FETCH__GET
CMS$FETCH__OPEN
CMS$GET__STRING
CMS$INSERT__ELEMENT
CMS$INSERT__GENERATION
CMS$INSERT__GROUP
CMS$MODIFY__CLASS
CMS$MODIFY__ELEMENT
CMS$MODIFY__GROUP
CMS$MODIFY__LIBRARY
CMS$PUT__STRING
CMS$REMARK
CMS$REMOVE__ELEMENT
CMS$REMOVE__GENERATION
CMS$REMOVE__GROUP
CMS$REPLACE
CMS$SET__LIBRARY
CMS$SHOW__CLASS
CMS$SHOW__ELEMENT
CMS$SHOW__GENERATION
CMS$SHOW__GROUP
CMS$SHOW__HISTORY
CMS$SHOW__LIBRARY
CMS$SHOW__RESERVATIONS
CMS$SHOW__VERSION
CMS$UNRESERVE
CMS$VERIFY

.page
.title Callable CMS return statuses
.justify .fill
.list 'o'
.le
The routines  return  statuses  in  the  same manner as the run time library
routines (in R0)

.le

There is no _$CMSDEF in FORSYSDEF (and probably not in other language's text
libraries); you  must  refer  to the status codes with the _%LOC function in
FORTRAN (or its equivalent)

.end list
.p

There is   no   single   list   of  possible  return  status  codes  in  the
documentation.  Instead, they are listed as appropriate after each routine's
description. The following is a reasonably complete list.


.page
.title Callable CMS return statuses
.no justify .no fill
CMS$__ABSTIM
CMS$__CREATED
CMS$__CREATES
CMS$__DELETED
CMS$__DELETIONS
CMS$__DIFFERENT
CMS$__EOF
CMS$__ERRCREATES
CMS$__ERRDELETIONS
CMS$__ERREPLACEMENTS
CMS$__ERRESERVATIONS
CMS$__ERRFETCHES
CMS$__ERRINSERTIONS
CMS$__ERRMODIFIES
CMS$__ERRREMOVALS
CMS$__ERRUNRESERVES
CMS$__EXCLUDE
CMS$__FETCHED
CMS$__FETCHES
CMS$__GENCREATED
CMS$__GENINSERTED
CMS$__GENNOINSERT
CMS$__GENNOREMOVE
CMS$__GENNOTFOUND
CMS$__GENREMOVED
CMS$__HISTDEL
CMS$__IDENTICAL
CMS$__ILLCLSNAM
CMS$__ILLELEXP
CMS$__ILLGEN
CMS$__ILLGRPNAM
CMS$__INSERTED
CMS$__INSERTIONS
CMS$__INVFETDB
CMS$__LIBSET
CMS$__MODIFICATIONS
CMS$__MODIFIED
CMS$__NOCLS
CMS$__NOCREATE
CMS$__NODELETE
CMS$__NOELE
CMS$__NOFETCH
CMS$__NOFILE
CMS$__NOGRP
CMS$__NOHIS
CMS$__NOINSERT
CMS$__NOMODIFY
CMS$__NORECOVER
CMS$__NOREF
CMS$__NOREMARK
CMS$__NOREMOVAL
CMS$__NOREPAIR
CMS$__NOREPLACE
CMS$__NORMAL
CMS$__NOSINCE
CMS$__NOTFOUND
CMS$__NOUNRESERVE
CMS$__NOVERIFY
CMS$__OPENIN1
CMS$__OPENIN2
CMS$__OPENOUT
CMS$__QUALCONFLICT
CMS$__READIN
CMS$__RECOVERED
CMS$__REMARK
CMS$__REMOVALS
CMS$__REMOVED
CMS$__REPAIRED
CMS$__REPLACEMENTS
CMS$__RESERVED
CMS$__SEQUENCED
CMS$__STOPPED
CMS$__TIMEORDER
CMS$__UNFOUT
CMS$__UNRESERVED
CMS$__UNRESERVES
CMS$__UNSUPFRMY
CMS$__USERERR
CMS$__VERIFIED

.page
.title Callable CMS bit masks
.justify .fill

.list 'o'
.le

In addition to the return status codes, there are some bit masks to use when
specifying options to certain routines. Again, there is no one list of them,
and they must be referenced by _%LOC or its equivalent.

.end list

.page
.title Callable CMS bit masks
.no justify .no fill

CMS$M__CMD__COPY
CMS$M__CMD__CREATE
CMS$M__CMD__DELETE
CMS$M__CMD__FETCH
CMS$M__CMD__INSERT
CMS$M__CMD__MODIFY
CMS$M__CMD__REMARK
CMS$M__CMD__REMOVE
CMS$M__CMD__REPLACE
CMS$M__CMD__RESERVE
CMS$M__CMD__UNRESERVE
CMS$M__CMD__VERIFY
CMS$M__IGNORE__CASE
CMS$M__IGNORE__FORM
CMS$M__IGNORE__LEAD
CMS$M__IGNORE__SPACE
CMS$M__IGNORE__TRAIL

.page
.title Structures for Dealing with Callable CMS
.justify .fill

There are  two  special structures that you must use when accessing your CMS
library with the callable interface.

.list 'o'
.le
The library data block is set up by a call to CMS_$SET__LIBRARY, and must be
passed  to  most  of  the  CMS  routines.  In  general,  if the routine gets
information  about  a group, class, or element in the library, you must pass
the  library  data block. NEVER ALTER THE CONTENTS OF THE LIBRARY DATA BLOCK
OR YOU MAY HARM THE CONTENTS OF YOUR CMS LIBRARY!!!

.le

The fetch  data block must be passed to the routines for fetching in element
line   by  line.  It  is  used  by  CMS_$FETCH__OPEN,  CMS_$FETCH__GET,  and
CMS_$FETCH__CLOSE.

.end list

.page
.title Structures for Dealing with Callable CMS
A VAX FORTRAN example of setting up the library and fetch data blocks.
.blank

.no justify .no fill

      STRUCTURE	/LIBRARY__DATA__BLOCK/
       UNION
        MAP
         INTEGER*4	%FILL(1:50)
        END MAP
        MAP
         INTEGER*4	LENGTH, STATUS, DESCRIPTOR(1:2)
         INTEGER*4	%FILL(5:50)
        END MAP
       END UNION
      END STRUCTURE

.BLANK
      STRUCTURE	/FETCH__DATA__BLOCK/
         INTEGER*4	%FILL(1:5)
      END STRUCTURE

.BLANK
      STRUCTURE	/SIGNAL__ARRAY/
         INTEGER*4	%FILL(1:16)
      END STRUCTURE

.BLANK
      STRUCTURE	/MECHANISM__ARRAY/
         INTEGER*4	%FILL(1:5)
      END STRUCTURE

.page
.title Example - LIBED
.fill .justify

LIBED is  a simple CMS LIBrary EDitor. Along with the CMS interface, it uses
the SMG runtime routines to format output and control the user interface.

.p

LIBED will  help  to  demonstrate:
.list 0 ' '
.le
CMS_$SET__LIBRARY
.le
CMS_$SHOW__GENERATION
.le
CMS_$GET__STRING
.le
CMS_$FETCH__OPEN
.le
CMS_$FETCH__GET
.le
CMS_$FETCH__CLOSE.
.end list

.p

LIBED's source is included in the handout.

.page
.title Using CMS_$SET__LIBRARY
.literal
		:
      num_windows = 0
      do while (cli$get_value('ELEMENT', element))
         num_windows = num_windows + 1
         display(num_windows).element = element

cc   Get the name of the library to be looked at.  (if not specified, it
cc   will be CMS$LIB.)
         cli_status = cli$get_value('LIBRARY', display(num_windows).library)
         cli_status = cli$get_value('GENERATION',
     +			display(num_windows).generation)

         CMS_STATUS = CMS$SET_LIBRARY(
     +		LIBDB(NUM_WINDOWS), 
     +		DISPLAY(NUM_WINDOWS).LIBRARY,
     +		 	)	! place holder for user message routine.

         call make_string( libdb(num_windows).descriptor, library )
         display(num_windows).library = library
		:
      enddo
.end literal

.page
.title Using CMS_$SHOW__GENERATION
.literal
		:
cc Loop through all the element spec's for the valid CMS Libraries.  Put
cc the element names on the associated virtual display.
      do i = 1, num_windows
		:
cc   Call CMS with the element and generation specification.  (wildcards
cc   and group names may result in more than one invocation of the output
cc   routine.)
         CMS_STATUS = CMS$SHOW_GENERATION( 
     +		LIBDB(I),
     +		ADD_ELEMENT_TO_DISPLAY, DISPLAY(I),
     +		DISPLAY(I).ELEMENT(1:CHKLEN(DISPLAY(I).ELEMENT)),
     +		DISPLAY(I).GENERATION(1:CHKLEN(DISPLAY(I).GENERATION)),
     +		,	! place holder for from_generation expression.
     +		,	!   "    "  "   "  ancestors flag.
     +		,	!   "    "  "   "  decendants flag.
     +		,	!   "    "  "   "  class member list flag.
     +		    )	!   "    "  "   "  user message routine.
		:
      enddo
		:
.end literal

.p

"CHKLEN" is  an  integer  function  that  returns  the  length of the string
without  its  trailing  blanks.  If  an  element's name were "FOO.BAR", then
passing CMS the element name "FOO.BAR#####" would result in CMS's failure to
find the element.  The same holds true for other strings passed to CMS.

.page
.title Callback/User Output Routines and CMS_$GET__STRING

This is    the    format    of    the   callback/user-output   routine   for
CMS_$SHOW__GENERATION.
.blank

.literal
      INTEGER FUNCTION ADD_ELEMENT_TO_DISPLAY( NEW_ELEMENT, LDB,
     +		DISPLAY,	! the user supplied parameter
     +		ELEMENT_ID, GENERATION_ID, USER_NAME_ID,
     +		TRANS_TIME, CREATE_TIME, REVISION_TIME, REMARK_ID,
     +		CLASS_LIST_ID, FORMAT, ATTRIBUTES, REVISION_NUMBER,
     +		RESERVATIONS )
		:
		:
      CMS_STATUS = CMS$GET_STRING( ELEMENT_ID, ELEMENT_NAME )
		:
.end literal

.page
.title LIBED Menu Display
.literal
$ libed *.for/lib=[uxdsybd02.cms]	! the DCL line to invoke LIBED

+-----------------------DISK$PG22:[UXDSYBD02.CMS], 1+------------------------+
|A8TODB.FOR        ACDATA.FOR        ACOK.FOR          ADDASS.FOR            |
|ASTOB.FOR         BASTOI.FOR        BILD.FOR          BILDT.FOR             |
|BITOA.FOR         BLDTCB.FOR        BTOD.FOR          BUG.FOR               |
|CABORT.FOR        CACHER.FOR        CADARI.FOR        CADD.FOR              |
|CBLDEX.FOR        CBLDHD.FOR        CBLDRC.FOR        CBUG.FOR              |
|CCDCAS.FOR        CCLDBS.FOR        CCOCAS.FOR        CCODE.FOR             |
|CCSRCU.FOR        CCSRCW.FOR        CCTRAN.FOR        CD2A.FOR              |
|CDDOUT.FOR        CDIREC.FOR        CDRIST.FOR        CDSTAK.FOR            |
|CEOB.FOR          CERROR.FOR        CFLUDT.FOR        CFNDAC.FOR            |
|CFNDCH.FOR        CGENFN.FOR        CGINFO.FOR        CGJLGN.FOR            |
|CGNL.FOR          CHECK_SUM.FOR     CHKDEL.FOR        CHKFLG.FOR            |
|CHSCLN.FOR        CI.FOR            CINC.FOR          CITRAN.FOR            |
|CKAUTO.FOR        CKSRCU.FOR        CKSRCW.FOR        CLEAR.FOR             |
|CLINK.FOR         CLINK1.FOR        CLO2UP.FOR        CLTOCF.FOR            |
|CLZASS.FOR        CLZINF.FOR        CMDLOD.FOR        CMDSAV.FOR            |
|CPROPT.FOR        CRADIR.FOR        CRDJCL.FOR        CREATE.FOR            |
|CNWGEN.FOR        COPASS.FOR        CPAGES.FOR        CPARSE.FOR            |
|CRECPR.FOR        CS.FOR            CSBPRS.FOR        CSECCK.FOR            |
|CSEDIT.FOR        CSETUP.FOR        CSPCED.FOR        CSPSEG.FOR            |
|CSREAD.FOR        CSRTRV.FOR        CSTGEN.FOR        CSWRIT.FOR            |
|CTDRIV.FOR        CTXIOC.FOR        CUPDAT.FOR        CUPDIR.FOR            |
|CUPPR.FOR         CURSOR.FOR        CUTD.FOR          CUTDSN.FOR            |
------------------------------------------------------------------------------
                                      Press ?, PF2, or "HELP" for Help
.end literal

.page
.title LIBED Functions
LIBED currently provides two capabilities:

.list 'o'
.le
ZOOM - Displays interesting information about an element generation.
.le
VIEW - Types the element generation to the screen.
.end list

.page
.title Using CMS_$SHOW__GENERATION for ZOOM
.literal
		:
cc Ask CMS about the element.
      CMS_STATUS = CMS$SHOW_GENERATION( 
     +	LIBDB,
     +	ADD_ELEMENT_TO_DISPLAY, Z_DISP,	! user output routine and arg.
     +	Z_DISP.ELEMENT(1:CHKLEN(Z_DISP.ELEMENT)),
     +	Z_DISP.GENERATION(1:CHKLEN(Z_DISP.GENERATION)),
     +		,	! place holder for from_generation expression.
     +		,	!   "    "  "   "  ancestors flag.
     +		,	!   "    "  "   "  decendants flag.
     +	1,		! set the class member list flag.
     +		    )	! place holder for user message routine.
		:
.end literal

.page
.title CMS_$GET__STRING used by Callback Routine
.literal
		:
cc   show the "real" generation of the element.
         CMS_STATUS = CMS$GET_STRING( GENERATION_ID, STRING )
         string = 'Generation: '//string
		:
cc   show the username of the person who created the element.
         CMS_STATUS = CMS$GET_STRING( USER_NAME_ID, STRING )
         string = 'Created by: '//string
		:
cc   display the time that the element was placed in the library, and the
cc   source file's creation time.
         sys_status = sys$asctim( , trans_time_str, trans_time, )
         sys_status = sys$asctim( , create_time_str, create_time, )

         string = 'Placed in library: '//trans_time_str
		:
cc   indicate if the element is on reserve.	(NOTE: never set!)
         if (reservations) then
            string = 'Element is Reserved'
            smg_status = smg$put_line( display.id, string )
         endif
		:
.end literal

.page
.title ZOOM Output
.literal
+-----------------------DISK$PG22:[UXDSYBD02.CMS], 1+------------------------+
|A8TODB.FOR        ACDATA.FOR        ACOK.FOR          ADDASS.FOR            |
|ASTOB.FOR         BASTOI.FOR        BILD.FOR          BILDT.FOR             |
|BITOA.FOR         BLDTCB.FOR        BTOD.FOR          BUG.FOR               |
|CABORT.FOR        CACHER.FOR        CADARI.FOR        CADD.FOR              |
|CBLDEX.+-----------------------A8TODB.FOR, 1+-----------------------+       |
|CCDCAS.|Generation: 1                                               |       |
|CCSRCU.|Created by: U_SMITH                                         |       |
|CDDOUT.|Placed in library:  1-OCT-1986 15:09:14.67                  |       |
|CEOB.FO|File created:      26-AUG-1986 16:30:47.96                  |       |
|CFNDCH.|Remark: CPPR 33923                                          |       |
|CGNL.FO+------------------------------------------------------------+       |
|CHSCLN.FOR        CI.FOR            CINC.FOR          CITRAN.FOR            |
|CKAUTO.FOR        CKSRCU.FOR        CKSRCW.FOR        CLEAR.FOR             |
|CLINK.FOR         CLINK1.FOR        CLO2UP.FOR        CLTOCF.FOR            |
|CLZASS.FOR        CLZINF.FOR        CMDLOD.FOR        CMDSAV.FOR            |
|CMDTRA.FOR        CMSGP.FOR         CNUMWD.FOR        CNVERT.FOR            |
|CNWGEN.FOR        COPASS.FOR        CPAGES.FOR        CPARSE.FOR            |
|CPROPT.FOR        CRADIR.FOR        CRDJCL.FOR        CREATE.FOR            |
|CRECPR.FOR        CS.FOR            CSBPRS.FOR        CSECCK.FOR            |
|CSEDIT.FOR        CSETUP.FOR        CSPCED.FOR        CSPSEG.FOR            |
|CSREAD.FOR        CSRTRV.FOR        CSTGEN.FOR        CSWRIT.FOR            |
|CTDRIV.FOR        CTXIOC.FOR        CUPDAT.FOR        CUPDIR.FOR            |
|CUPPR.FOR         CURSOR.FOR        CUTD.FOR          CUTDSN.FOR            |
+----------------------------------------------------------------------------+
                                      Press ?, PF2, or "HELP" for Help
.end literal

.page
.title Using CMS_$FETCH__OPEN, __GET, AND __CLOSE for VIEW
.literal
		:
cc Open the element.
      CMS_STAT = CMS$FETCH_OPEN(
     +			FETDB, 
     +			DISPLAY.LIBRARY(1:CHKLEN(DISPLAY.LIBRARY)),
     +			ELEMENT(1:CHKLEN(ELEMENT)),
     +			DISPLAY.GENERATION(1:CHKLEN(DISPLAY.GENERATION)),
     +			1,	! no history.
     +			1,	! no notes.
     +			GENERATION,
     +			  )	! place holder for user message routine.
		:
      done = .not. cms_stat
      more = .true.
      count = 0

cc Loop until EOF or until the user wants no more.
      do while (.not. done)

cc   FETCH a line of the element
         CMS_STAT = CMS$FETCH_GET( FETDB, STRING )
         count = count + 1

cc   Check to see if we've reache EOF.
cc	NOTE: CMS returns RMS$_EOF, not CMS$_EOF as documented.
         DONE = CMS_STAT .EQ. RMS$_EOF
		:
      enddo

cc Close the element.
      CMS_STAT = CMS$FETCH_CLOSE( FETDB )
.end literal

.page
.title VIEW Output
.literal
--------------------------------A8TODB.FOR, 1---------------------------------
      SUBROUTINE A8TODB( NAME, TYPE )
C*****************************************************************************
C   
C               Author: Randall Smith
C   
C  Date of Last Update: 07/09/86 (1)
C   
C     Revision History: (1) Created for CPPR 33923
C   
C         Parameters: NAME  (IN/ ) - 8 char name to be stored
C		      TYPE  (IN/ ) - DD for directory, DI for data page/word
C   
C         Local Data: TEMP   - Storable version of NAME
C   
C         Function: Takes an 8 char name and stores it into the next 2 words
C		    of either the directory or data section of the SDB.
C   
C****************************************************************************** 
C   
      IMPLICIT NONE 

------------------------------------------------------------------------------
                                                                       More?
.end literal

.page
.title Conclusions - CMS Strong Points
.fill .justify

.list '+'
.le
Accessing  CMS  is  done  in  the  high-level language of your choice versus
having DCL as the sole interface

.le
Like  the  CMS_>  command  submode, you can save on image activations if you
have a lot to do in the library

.le
UNLIKE  the  DCL  version,  your program may access AS MANY LIBRARIES AS YOU
WISH (and have virtual memory for...)

.le

You may supply your own output routine to most routines

.le

The interface  can  be integrated with all the other tools VMS has to offer:
SMG,  RTL,  SYS,  TPU,  Scan,  etc.  (Imagine  an  animated  history of your
project's software development - a comedy, or a tragedy?)

.end list

.page
.title Conclusions - Weak Points
.fill .justify

.list '-'
.le

The interface  is  not  item list oriented. Every major function has its own
specific  call  and  ways of working. Thus, for "FETCH" you have CMS_$FETCH;
for  "SHOW  HISTORY",  you have CMS_$SHOW__HISTORY; for "ANNOTATE", you have
CMS_$ANNOTATE,  etc. If DEC decides to add a couple of arguments, you may be
left high  and dry. The item list method may be tedious at times, but it can
provide a stable hook into the interface.

.le

Output/callback routine arguments differ for each CMS_$ routine.

.le

Output passed to the user-supplied output routine for CMS_$ANNOTATE includes
the page headers you would see in a CMS produced .ANN file.

.le

Error handling  can  be  painful.  While  you may provide a message handling
routine  which  CMS  will call on your behalf, you may still need to do some
back  flips  to  provide  usefull  error  recovery.  CMS should provide more
information (eg., the name of the offending element in a wildcard search).

.le

No support in FORSYSDEF (yet)

.le

You can't   call   CMS   routines   from   callback   routines  (except  for
CMS_$GET__STRING and CMS_$PUT__STRING)

.end list

.page
.title Conclusions - Bugs
.fill .justify

Our version of CMS appears to have several bugs:

.list 'o'
.le
The RESERVATIONS argument to the user supplied output routine is never set

.le
When  using  an output routine, CMS_$ANNOTATE FAILS after reaching the end of
the element with the error:
.literal
%CMS-F-BUG, there is something wrong with CMS or something it calls
-CMS-F-BADIOBLENGTH, The passed iob has an invalid length
.end literal

.le
As noted earlier, return status codes are not always as documented

.end list

.page
.title

.figure 10

.center; Questions?
