.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?