OpenVMS documentation is some of the best I've seen but nothing is 100% accurate which is why you need other options. If you write programs requiring OpenVMS system calls, then doing a simple hack of the Starlet library is one such option. The whole purpose of the next example is to produce a searchable text file of the BASIC definition for the Starlet system library (known as BASIC$STARLET.TLB) in order to "double check" passing mechanisms, variable types and variable sizes described in official OpenVMS documentation.
BTW, the following procedure requires ~ 7900 blocks for OpenVMS-8.3 so be careful.
Legend: <ur> = user response <sr> = system response ------------------------------ <sr> $ ! this is the default prompt <ur> set def sys$library <sr> $ <ur> dir *.tlb ! see all TLB files <sr> Directory SYS$COMMON:[SYSLIB] BASIC$STARLET.TLB;1 DECC$RTLDEF.TLB;1 EPC$FACILITY.TLB;1 ERFLIB.TLB;1 LIB_ADA_SUBSET.TLB;1 NTA.TLB;1 STARLETSD.TLB;1 STARLET_RECENT_ADA_SUBSET.TLB;1 SYS$LIB_C.TLB;1 SYS$STARLET_C.TLB;1 TCPIP$TEMPLATES.TLB;1 Total of 11 files. $ <ur> lib/list BASIC$STARLET.TLB/text ! see library chapters <sr>
Directory of TEXT library SYS$COMMON:[SYSLIB]BASIC$STARLET.TLB;1 on 25-MAR-2012 09:18:11 Creation date: 12-AUG-2010 17:23:28 Creator: Librarian A09-30 Revision date: 12-AUG-2010 17:23:30 Library format: 3.0 Number of modules: 318 Max. key length: 39 Other entries: 0 Preallocated index blocks: 31 Recoverable deleted blocks: 0 Total index blocks used: 15 Max. Number history records: 20 Library history records: 0 Library is in DCX data reduced format $ACCDEF $ACCESSDEF $ACEDEF $ACLDEF $ACMEDEF $ACMEMSGDEF $ACMEVMSDEF $ACRDEF $AFRDEF $AGNDEF $ALPHADEF $ARGDEF $ARMDEF $ATRDEF $BASDEF $BRKDEF $CAPDEF $CBODEF $CHFDEF $CHKPNTDEF $CHPDEF $CLIDEF $CLIMSGDEF $CLISERVDEF $CLIVERBDEF $CLSDEF $CLUEVTDEF $CMBDEF $COBDEF $CONVDEF $CONVMSGDEF $CPUIDEF $CQUALDEF $CRDEF $CREDEF $CRFDEF $CRFMSG $CSTDEF $CVTDEF $CVTFNMDEF $CVTMSG $DCDEF $DDTMDEF $DDTMMSGDEF $DELPRCSYMDEF $DEVDEF $DIBDEF $DIRENTDEF $DMTDEF $DPSDEF $DSCDEF $DSTDEF $DTIDEF $DTKDEF $DTKMSG $DVIDEF $DVSDEF $EEOMDEF $EFNDEF $EGPSDEF $EGSDEF $EGSTDEF $EGSYDEF $EIDCDEF $EMHDEF $ENVDEF $EOBJRECDEF $EOMDEF $EOMWDEF $EPMDEF $EPMMDEF $EPMVDEF $EPMWDEF $ERADEF $ESDFDEF $ESDFMDEF $ESDFVDEF $ESGPSDEF $ESRFDEF $ETIRDEF $EVAX_INSTRDEF $EVENTDEF $FABDEF $FALDEF $FDLDEF $FDLMSGDEF $FIBDEF $FIDDEF $FLTDEF $FMLDEF $FORDEF $FSCNDEF $GEN64DEF $GETSPIDEF $GLOCKDEF $GPSDEF $GSDEF $GSYDEF $HLPDEF $HWDEF $IACDEF $ICCDEF $IDCDEF $IEEEDEF $ILEDEF $INDICTDEF $INITDEF $IODEF $IOSADEF $IOSBDEF $ISSDEF $JBCMSGDEF $JPIDEF $JPIFDEF $KGBDEF $LADEF $LATDEF $LATMSGDEF $LBRCTLTBL $LBRDEF $LCKDEF $LDDEF $LEPMDEF $LGIDEF $LHIDEF $LIBCLIDEF $LIBDCFDEF $LIBDEF $LIBDTDEF $LIBFILDEF $LIBFISDEF $LIBVMDEF $LIBWAITDEF $LICENSEDEF $LKIDEF $LKSBDEF $LMFDEF $LNKDEF $LNMDEF $LOGTYPDEF $LPDEF $LPRODEF $LSDFDEF $LSRFDEF $LSYDEF $MACIDDEF $MAILDEF $MAILMSGDEF $MAPPINGDEF $MHDDEF $MHDEF $MMEMSGDEF $MMIDEF $MNTDEF $MOUNDEF $MSGDEF $MSGHLPDEF $MT2DEF $MT3DEF $MTADEF $MTDEF $MTHDEF $NAMDEF $NCSDEF $NETDEF $NSADEF $NSAMSGDEF $NSARECDEF $OBJRECDEF $OPCDEF $OPCMSG $OPRDEF $OSSDEF $OTSDEF $PCCDEF $PDSCDEF $PMMDEF $POSIX_SERVICEDEF $POWERDEF $PPLDEF $PPROPDEF $PQLDEF $PRCDEF $PRDEF $PRODEF $PROMDEF $PROVDEF $PROWDEF $PRTDEF $PRVDEF $PRXDEF $PSCANDEF $PSIGDEF $PSLDEF $PSMMSGDEF $PTDDEF $QSRVDEF $QUIDEF $RABDEF $RBLDDEF $REGDEF $REGMSG $RMEDEF $RMIDEF $RMSDEF $RNHBLKDEF $RSDMDEF $S2DGBDEF $SBKDEF $SCRDEF $SDBDEF $SDDEF $SDFDEF $SDFMDEF $SDFVDEF $SDFWDEF $SDVDEF $SECDEF $SECIDDEF $SECSRVDEF $SECSRVMSGDEF $SGPSDEF $SHRDEF $SJCDEF $SMBMSGDEF $SMGDEF $SMGMSG $SMGTRMPTR $SMRDEF $SORDEF $SRFDEF $SRMDEF $SSDEF $SSIODEF $STENVDEF $STRDEF $STSDEF $SYIDEF $SYSEVTDEF $TBKDEF $TEBDEF $TIRDEF $TPADEF $TPUDEF $TRMDEF $TT2DEF $TT3DEF $TTCDEF $TTDEF $TTYDPORTDEF $UAF070DEF $UAIDEF $UICDEF $UIDDEF $USGDEF $USRIDEF $UTCBLKDEF $VADEF $VAXDEF $VA_RANGEDEF $WBEMIDEF $WWIDDEF $XABALLDEF $XABCXFDEF $XABCXRDEF $XABDATDEF $XABDEF $XABFHCDEF $XABITMDEF $XABJNLDEF $XABKEYDEF $XABPRODEF $XABRDTDEF $XABRUDEF $XABSUMDEF $XABTRMDEF $XADEF $XKDEVDEF $XKSTSDEF $XMDEF $XWDEF ACLEDIT$ROUTINES CIADEF CLI$ROUTINES CMA$DEF CONV$ROUTINES CSHDEF CVT$ROUTINES DCX$ROUTINES DTK$ROUTINES EDT$ROUTINES ELFDATYP ELFDEF ESFDEF EVX_OPCODES FDL$ROUTINES LBR$ROUTINES LIB$ROUTINES LIBICB MAIL$ROUTINES MMEDEF MTH$ROUTINES NCS$ROUTINES OTS$ROUTINES PAGEDEF PPL$DEF PPL$ROUTINES PSM$ROUTINES SMB$ROUTINES SMG$ROUTINES SNAPEVTDEF SOR$ROUTINES STARLET STR$ROUTINES TBK$ROUTINES TPU$ROUTINES UTIL$ROUTINES VERSION_INFO $
<ur> lib BASIC$STARLET.TLB/text/extract=* ! dump all chapters to file BASIC$STARLET.TXT <sr> $ <ur> lib BASIC$STARLET.TLB/text/extract=$IOSBDEF/out=BASIC$STARLET_$IOSBDEF.TXT <sr> $ <ur> lib BASIC$STARLET.TLB/text/extract=$ILEDEF /out=BASIC$STARLET_$ILEDEF.TXT <sr> $ <ur> lib BASIC$STARLET.TLB/text/extract=starlet /out=BASIC$STARLET_startlet.txt <sr> $ <ur> dir basic$starlet*.txt/siz/width=file=30 <sr> Directory SYS$COMMON:[SYSLIB] BASIC$STARLET.TXT;12 8017 BASIC$STARLET_$ILEDEF.TXT;1 9 BASIC$STARLET_$IOSBDEF.TXT;2 8 BASIC$STARLET_STARTLET.TXT;1 658 Total of 4 files, 8692 blocks. $ <ur> edit/read BASIC$STARLET.TXT ! comment: use "edit/tpu/read" to invoke EVE
Now that you've created a text file representation of the whole library called "BASIC$STARLET.TXT", use your favorite editor to open it, then search for the string "sys$qio" and you'll see the following:
$QIO Queue I/O Request $QIO [efn] ,chan ,func ,[iosb] ,[astadr] ,[astprm] ($QIOW) ,[p1] ,[p2] ,[p3] ,[p4] ,[p5] ,[p6] efn = number of event flag to set on completion chan = number of channel on which I/O is directed func = function code specifying action to be performed iosb = address of quadword I/O status block to receive final completion status astadr = address of entry mask of AST routine astprm = value to be passed to AST routine as argument p1..p6 = optional device- and function-specific parameters EXTERNAL LONG FUNCTION SYS$QIO & ( LONG BY VALUE , & WORD BY VALUE , & WORD BY VALUE , & BASIC$QUADWORD BY REF, & LONG BY REF , & LONG BY VALUE , & ANY BY REF , & LONG BY VALUE , & LONG BY VALUE , & LONG BY VALUE , & LONG BY VALUE , & LONG BY VALUE & )
System Call Starlet
DefinitionOpenVMS 7.2-1
CD-ROM (1999)OpenVMS 7.3-1
CD-ROM (2002)lib$bbcci long by ref,
long by value
always correctlong by ref,
address by ref
incorrectlong by ref,
address by value
correctlib$bbssi long by ref,
long by value
always correctlong by ref,
address by ref
incorrectlong by ref,
address by value
correct
To properly reference BASIC$STARLET text library declarations from within OpenVMS-BASIC (DEC-BASIC, Compaq-BASIC, HP-BASIC) you'll need to employ something similar to this code fragment:
! ! <<< system declarations >>> ! %include "starlet" %from %library "sys$library:basic$starlet" ! system services (e.g. sys$qio) %include "$ssdef" %from %library "sys$library:basic$starlet" ! ss$ %include "lib$routines" %from %library "sys$library:basic$starlet" ! lib$ %include "$uaidef" %from %library "sys$library:basic$starlet" ! uai$ ! Note: Make sure to include every module required by your program. For more information just click here to check out some of my fully-functional free demo programs.
1000 %title "timer_demo_xxx" ! %ident "version_101.1" ! option type = explicit ! no kid stuff... declare string constant k_program = "timer_demo" , & k_version = "101.1" ! !======================================================================= ! title : timer_demo_xxx.bas ! author : Neil Rieck ! created: 2004.01.01 !======================================================================= set no prompt ! ! ! system declarations ! %include "starlet" %from %library "sys$library:basic$starlet" ! system services %include "$ssdef" %from %library "sys$library:basic$starlet" ! ss$ %include "lib$routines" %from %library "sys$library:basic$starlet" ! lib$ ! ! home brewed functions ! external long function get_timer_bit_vector(long) ! required for used with SYS$WFLOR ! declare long rc% ,! return code & timer_event_flag% ,! timer event flag & timer_ef_state% ,! timer event flag state & tcp_event_flag% ,! tcp event flag & tcp_ef_state% ,! tcp event flag state & mask% ,! required for sys$wflor & junk% ,! & basic$QuadWord DeltaQuad ! for sys$bintim etc. ! !======================================================================= ! main !======================================================================= main: margin #0, 132 ! width for the log file print k_program +"_"+ k_version ! print string$(len(k_program +"_"+ k_version), asc("=")) ! underline previous line (how will this optimize?) ! ! <<< get some event flags for later >>> ! if tcp_event_flag% = 0 then ! if not yet allocated rc% = lib$get_EF( tcp_event_flag% ) ! get an event flag if ((rc% and 7%) <> 1) then ! print "lib$get_EF-1 rc: ";str$(rc%) ! goto rc_exit ! end if ! end if ! ! if timer_event_flag% = 0 then ! if not yet allocated rc% = lib$get_EF( timer_event_flag% ) ! get another event flag if ((rc% and 7%) <> 1) then ! print "lib$get_EF-2 rc: ";str$(rc%) ! goto rc_exit ! end if ! end if ! ! ! <<< arm a timer to expire 'x' time from now >>> ! print "-i- arming timer-1 (timer) for 10 seconds from now" ! declare string constant k_delay010 = "0 00:00:10" ! set delay time 10 seconds from now rc% = sys$bintim(k_delay010, DeltaQuad ) ! init delta time ('x' time from now) print "-e- sys$bintim rc: "+ str$(rc%) if ((rc% and 1%) <> 1%) ! rc% = sys$setimr(timer_event_flag%,DeltaQuad by ref,,,) ! now use it to schedule a wake up print "-e- sys$setimr rc: "+ str$(rc%) if ((rc% and 1%) <> 1%) ! ! ! <<< use a second timer to simulate some sort of TCP timeout > ! print "-i- arming timer-2 (fake tcp) for 20 seconds from now" ! declare string constant k_delay020 = "0 00:00:20" ! set delay time 20 seconds from now rc% = sys$bintim(k_delay020, DeltaQuad ) ! init delta time ('x' time from now) print "-e- sys$bintim rc: "+ str$(rc%) if ((rc% and 1%) <> 1%) ! rc% = sys$setimr(tcp_event_flag%,DeltaQuad by ref,,,) ! now use it to schedule a wake up print "-e- sys$setimr rc: "+ str$(rc%) if ((rc% and 1%) <> 1%) ! ! ! note: for the SYS$WFLOR call to work, both event flags must be in the same event flag cluster. ! The first parameter is only used to determine which event flag cluster to test. ! The second parameter (mask) contains bits representing event flags within that cluster ! mask% = get_timer_bit_vector( tcp_event_flag%) ! insert vector 1 into mask mask% = mask% or get_timer_bit_vector(timer_event_flag%) ! insert vector 2 into mask ! ! <<< wait for either the 'TCP event flag' or the 'TIMER event flag' to change state >>> ! print "-i- waiting for event flag "+ str$(tcp_event_flag%) +" or event flag "+ str$(timer_event_flag%) ! rc% = sys$wflor( tcp_event_flag%, mask%) ! wait for a response from one of two flags print "-e- sys$waitfr rc: "+ str$(rc%) if ((rc% and 1%) <> 1%) ! ! ! <<< cancel all timer requests (if any) >>> ! print "-i- Calling $CanTim" ! rc% = sys$cantim(,) ! cancel all timer requests print "-e- sys$cantim rc: "+ str$(rc%) if ((rc% and 1%) <> 1%) ! ! ! which event flag is set? TCP or TIMER? ! rc% = sys$readEF(tcp_event_flag%, junk%) ! test TCP event flag select rc% ! case SS$_WASCLR ! tcp_ef_state% = 0 ! case SS$_WASSET ! tcp_ef_state% = 1 ! case else ! print "-e- sys$readef-tcp rc: "+ str$(rc%) ! end select ! print "-i- TCP EF State : ";str$(tcp_ef_state%) ! ! rc% = sys$readEF(timer_event_flag%, junk%) ! test TIMER event flag select rc% ! case SS$_WASCLR ! timer_ef_state% = 0 ! case SS$_WASSET ! timer_ef_state% = 1 ! case else ! print "-e- sys$readef-timer rc: "+ str$(rc%) ! end select ! print "-i- Timer EF State: ";str$(timer_ef_state%) ! ! ! at this point either the TCP-EF or the TIMER-EF could be set ! if (timer_ef_state% = 1) and ! if the TIMER-EF is set & ( tcp_ef_state% = 0) ! and the TCP-EF is clear then ! then something timed out print "-i-the tcp event timed out" end if !======================================================================= ! <<< adios... >>> !======================================================================= fini: rc% = 1 ! vms -s- ! ! rc% must be set up b4 this point (and must not be changed) ! rc_exit: 30000 end program rc% ! !####################################################################### ! ! <<< external functions >>> ! !====================================================================== ! get timer bit vector ! (see OpenVMS system services documentation for "sys$wflor") ! ! notes: cluster event flags ! 0 00- 31 ! 1 32- 63 ! 2 64- 95 ! 3 96-127 !====================================================================== 31040 function long get_timer_bit_vector(long event_flag) option type = explicit declare long temp ! select event_flag case <= 31 temp = event_flag case <= 63 temp = event_flag - 32 case <= 95 temp = event_flag - 64 case else temp = event_flag -96 end select ! select temp ! this code will avoid an integer overflow case 31 ! need to set bit #31 ! 33222222222211111111110000000000 ! 10987654321098765432109876543210 get_timer_bit_vector = B"10000000000000000000000000000000"L ! so return this case else ! get_timer_bit_vector = (2% ^ temp) ! else return this end select ! end function ! get_timer_bit_vector ! !#######################################################################