0% found this document useful (0 votes)
36 views506 pages

4 VMS Programming Concepts Vol2

This document provides information about calling OpenVMS system routines and run-time library routines from programs. It describes the standard call format for OpenVMS routines, including the headings for procedure call format, returns, arguments, and condition values returned. It also covers basic calling standard conventions for OpenVMS like register usage, stack usage, argument passing mechanisms, and returning function values and condition values.

Uploaded by

cemal bulbul
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
36 views506 pages

4 VMS Programming Concepts Vol2

This document provides information about calling OpenVMS system routines and run-time library routines from programs. It describes the standard call format for OpenVMS routines, including the headings for procedure call format, returns, arguments, and condition values returned. It also covers basic calling standard conventions for OpenVMS like register usage, stack usage, argument passing mechanisms, and returning function values and condition values.

Uploaded by

cemal bulbul
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 506

OpenVMS Programming

Concepts Manual, Volume II


Order Number: AA–PV67E–TK

April 2001

This manual is volume two of two volumes. It describes the features


that the OpenVMS operating system provides to programmers.

Revision/Update Information: This manual supersedes the OpenVMS


Programming Concepts Manual,
Version 7.2.
Software Version: OpenVMS Alpha Version 7.3
OpenVMS VAX Version 7.3

Compaq Computer Corporation


Houston, Texas
© 2001 Compaq Computer Corporation
Compaq, AlphaServer, VAX, VMS, and the Compaq logo Registered in U.S. Patent and Trademark
Office.
Alpha, OpenVMS, PATHWORKS, DECnet, and DEC are trademarks of Compaq Information
Technologies Group, L.P. in the United States and other countries.
UNIX and X/Open are trademarks of The Open Group in the United States and other countries.
All other product names mentioned herein may be trademarks of their respective companies.
Confidential computer software. Valid license from Compaq required for possession, use, or copying.
Consistent with FAR 12.211 and 12.212, Commercial Computer Software, Computer Software
Documentation, and Technical Data for Commercial Items are licensed to the U.S. Government
under vendor’s standard commercial license.
Compaq shall not be liable for technical or editorial errors or omissions contained herein. The
information in this document is provided "as is" without warranty of any kind and is subject
to change without notice. The warranties for Compaq products are set forth in the express
limited warranty statements accompanying such products. Nothing herein should be construed as
constituting an additional warranty.
Printed in the U.S.A.

ZK6641
The Compaq OpenVMS documentation set is available on CD–ROM.
Contents

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii

Part I OpenVMS Programming Interfaces: Calling a System Routine

17 Call Format to OpenVMS Routines


17.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–1
17.2 Format Heading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–2
17.2.1 Procedure Call Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–3
17.2.2 JSB Call Format (VAX only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–4
17.3 Returns Heading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–4
17.3.1 Condition Values Returned in a Register . . . . . . . . . . . . . . . . . . . . . . . 17–4
17.3.2 Other Returned Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–5
17.3.3 Condition Values Signaled . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–6
17.4 Arguments Heading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–6
17.4.1 OpenVMS Usage Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–6
17.4.2 Type Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–7
17.4.3 Access Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–8
17.4.4 Mechanism Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–9
17.4.5 Explanatory Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–10
17.5 Condition Values Returned Heading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–11
17.5.1 Condition Values Returned . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–12
17.5.2 Condition Values Returned in an I/O Status Block . . . . . . . . . . . . . . . 17–12
17.5.3 Condition Values Returned in a Mailbox . . . . . . . . . . . . . . . . . . . . . . . 17–12
17.5.4 Condition Values Signaled . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17–12

18 Basic Calling Standard Conventions


18.1 Hardware Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–1
18.1.1 Register Usage for OpenVMS VAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–1
18.1.2 Register Usage for OpenVMS Alpha . . . . . . . . . . . . . . . . . . . . . . . . . . 18–2
18.1.2.1 Integer Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–2
18.1.2.2 Floating-Point Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–3
18.2 Stack Usage for Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–3
18.2.1 Stack Procedure Usage for VAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–3
18.2.1.1 Calling Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–5
18.2.1.2 Call Frames on Return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–5
18.2.2 Stack Procedure Usage for Alpha . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–5
18.2.2.1 Fixed-Size Stack Frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–5
18.2.2.2 Variable-Size Stack Frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–6
18.3 Procedure Representation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–8
18.4 Argument List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–9
18.5 Argument Passing Mechanisms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–11
18.5.1 Passing Arguments by Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–13

iii
18.5.2 Passing Arguments by Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–14
18.5.3 Passing Arguments by Descriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–16
18.6 Passing Scalars as Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–18
18.7 Passing Arrays as Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–18
18.8 Passing Strings as Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–18
18.9 Combinations of Descriptor Class and Data Type . . . . . . . . . . . . . . . . . . . 18–19
18.10 Return of the Function Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–22
18.11 Return of the Condition Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–22

19 Calling Run-Time Library Routines


19.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–1
19.2 Call Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–3
19.2.1 Facility Prefix and Routine Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–3
19.2.2 The RTL Call Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–4
19.2.2.1 JSB Call Entries (VAX Only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–6
19.2.3 Returns from an RTL Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–6
19.2.3.1 Facility Return Status and Condition Value Symbols . . . . . . . . . . 19–6
19.3 Calling a Library Procedure in VAX MACRO (VAX Only) . . . . . . . . . . . . . 19–7
19.3.1 VAX MACRO Calling Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–7
19.3.2 VAX MACRO CALLS Instruction Example . . . . . . . . . . . . . . . . . . . . . 19–8
19.3.3 VAX MACRO CALLG Instruction Example . . . . . . . . . . . . . . . . . . . . . 19–8
19.3.4 VAX MACRO JSB Entry Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–9
19.3.5 Return Status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–10
19.3.6 Function Return Values in VAX MACRO . . . . . . . . . . . . . . . . . . . . . . . 19–11
19.4 Calling a Library Routine in BLISS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–11
19.4.1 BLISS Calling Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–12
19.4.2 Accessing a Return Status in BLISS . . . . . . . . . . . . . . . . . . . . . . . . . . 19–12
19.4.3 Calling JSB Entry Points from BLISS . . . . . . . . . . . . . . . . . . . . . . . . . 19–13

20 Calling System Services


20.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–1
20.2 Preserving System Integrity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–2
20.2.1 User Privileges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–2
20.2.2 Resource Quotas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–2
20.2.3 Access Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–2
20.3 System Service Call Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–3
20.4 System Service Completion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–5
20.4.1 Asynchronous and Synchronous System Services . . . . . . . . . . . . . . . . . 20–5
20.4.2 System Service Resource Wait Mode . . . . . . . . . . . . . . . . . . . . . . . . . . 20–6
20.4.3 Condition Values Returned from System Services . . . . . . . . . . . . . . . . 20–7
20.4.4 Testing the Condition Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–8
20.4.5 Special Condition Values Using Symbolic Codes . . . . . . . . . . . . . . . . . 20–8
20.4.6 Testing the Return Condition Value for Assembly Languages . . . . . . . 20–9
20.4.7 System Messages Generated by Condition Values . . . . . . . . . . . . . . . . 20–10
20.5 Program Examples with System Service Calls . . . . . . . . . . . . . . . . . . . . . . 20–11

iv
21 STARLET Structures and Definitions for C Programmers
21.1 SYS$STARLET_C.TLB Equivalency to STARLETSD.TLB . . . . . . . . . . . . . 21–1
21.2 NEW STARLET Definitions for C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21–2

Part II I/O, System and Programming Routines

22 Run-Time Library Input/Output Operations


22.1 Choosing I/O Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–1
22.2 Using SYS$INPUT and SYS$OUTPUT . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–3
22.2.1 Default Input and Output Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–3
22.2.2 Reading and Writing to Alternate Devices and External Files . . . . . . . 22–4
22.3 Working with Simple User I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–4
22.3.1 Default Devices for Simple I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–4
22.3.2 Getting a Line of Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–4
22.3.3 Getting Several Lines of Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–5
22.3.4 Writing Simple Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–6
22.4 Working with Complex User I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–7
22.4.1 Compaq DECwindows Motif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–7
22.4.1.1 DECwindows Server Height or Width Exceeding 32767 (VAX
Only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–8
22.4.1.2 SET DISPLAY Used to Create WSA Pseudo Workstation
Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–8
22.4.2 SMG$ Run-Time Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–9
22.4.3 Pasteboards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–10
22.4.3.1 Erasing a Pasteboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–11
22.4.3.2 Deleting a Pasteboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–11
22.4.3.3 Setting Screen Dimensions and Background Color . . . . . . . . . . . . 22–11
22.4.4 Virtual Displays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–12
22.4.4.1 Creating a Virtual Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–12
22.4.4.2 Pasting Virtual Displays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–13
22.4.4.3 Rearranging Virtual Displays . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–15
22.4.4.4 Removing Virtual Displays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–16
22.4.4.5 Modifying a Virtual Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–17
22.4.4.6 Using Spawned Subprocesses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–18
22.4.5 Viewports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–19
22.4.6 Writing Text to Virtual Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–19
22.4.6.1 Positioning the Cursor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–19
22.4.6.2 Writing Data Character by Character . . . . . . . . . . . . . . . . . . . . . . 22–20
22.4.6.3 Writing Data Line by Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–21
22.4.6.4 Drawing Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–22
22.4.6.5 Deleting Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–23
22.4.7 Using Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–23
22.4.8 Reading Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–24
22.4.8.1 Reading from a Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–24
22.4.8.2 Reading from a Virtual Keyboard . . . . . . . . . . . . . . . . . . . . . . . . . 22–25
22.4.8.3 Reading from the Keypad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–26
22.4.8.4 Reading Composed Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–29
22.4.9 Controlling Screen Updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–31
22.4.10 Maintaining Modularity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–31
22.5 Performing Special Input/Output Actions . . . . . . . . . . . . . . . . . . . . . . . . . 22–33
22.5.1 Using Ctrl/C and Ctrl/Y Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–33
22.5.2 Detecting Unsolicited Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–36

v
22.5.3 Using the Type-Ahead Buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–39
22.5.4 Using Echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–40
22.5.5 Using Timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–41
22.5.6 Converting Lowercase to Uppercase . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–42
22.5.7 Performing Line Editing and Control Actions . . . . . . . . . . . . . . . . . . . 22–42
22.5.8 Using Broadcasts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–43
22.5.8.1 Default Handling of Broadcasts . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–43
22.5.8.2 How to Create Alternate Broadcast Handlers . . . . . . . . . . . . . . . . 22–43

23 System Service Input/Output Operations


23.1 Overview of OpenVMS QIO Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–2
23.2 Quotas, Privileges, and Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–2
23.2.1 Buffered I/O Quota . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–3
23.2.2 Buffered I/O Byte Count Quota . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–3
23.2.3 Direct I/O Quota . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–3
23.2.4 AST Quota . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–3
23.2.5 Physical I/O Privilege . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–3
23.2.6 Logical I/O Privilege . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–4
23.2.7 Mount Privilege . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–4
23.2.8 Share Privilege . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–4
23.2.9 Volume Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–4
23.2.10 Device Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–5
23.2.11 System Privilege . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–5
23.2.12 Bypass Privilege . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–5
23.3 Physical, Logical, and Virtual I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–5
23.3.1 Physical I/O Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–5
23.3.2 Logical I/O Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–6
23.3.3 Virtual I/O Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–6
23.4 I/O Function Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–10
23.4.1 Function Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–10
23.4.2 Function Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–11
23.5 Assigning Channels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–11
23.5.1 Using the Share Privilege with the SYS$ASSIGN and SYS$DASSGN
Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–12
23.6 Queuing I/O Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–12
23.7 Synchronizing Service Completion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–13
23.8 Recommended Method for Testing Asynchronous Completion . . . . . . . . . . 23–18
23.9 Synchronous and Asynchronous Forms of Input/Output Services . . . . . . . 23–19
23.9.1 Reading Operations with SYS$QIOW . . . . . . . . . . . . . . . . . . . . . . . . . 23–19
23.9.2 Reading Operations with SYS$QIO . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–21
23.9.3 Write Operations with SYS$QIOW . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–23
23.10 I/O Completion Status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–23
23.11 Deassigning I/O Channels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–24
23.12 Using Complete Terminal I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–24
23.13 Canceling I/O Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–26
23.14 Logical Names and Physical Device Names . . . . . . . . . . . . . . . . . . . . . . . . 23–27
23.15 Device Name Defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–28
23.16 Obtaining Information About Physical Devices . . . . . . . . . . . . . . . . . . . . . 23–28
23.16.1 Checking the Terminal Device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–29
23.16.2 Terminal Characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–29
23.16.3 Record Terminators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–31
23.16.4 File Terminators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–31
23.17 Device Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–32

vi
23.17.1 Implicit Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–33
23.17.2 Deallocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–33
23.18 Mounting, Dismounting, and Initializing Volumes . . . . . . . . . . . . . . . . . . . 23–34
23.18.1 Mounting a Volume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–34
23.18.1.1 Calling the SYS$MOUNT System Service . . . . . . . . . . . . . . . . . . . 23–34
23.18.1.2 Calling the SYS$DISMOU System Service . . . . . . . . . . . . . . . . . . 23–36
23.18.2 Initializing Volumes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–36
23.18.2.1 Calling the Initialize Volume System Service . . . . . . . . . . . . . . . . . 23–36
23.19 Formatting Output Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–38
23.20 Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–39
23.20.1 Mailbox Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–43
23.20.2 System Mailboxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–43
23.20.3 Mailboxes for Process Termination Messages . . . . . . . . . . . . . . . . . . . . 23–44
23.21 Example of Using I/O Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–45
23.22 Fast I/O and Fast Path Features (Alpha Only) . . . . . . . . . . . . . . . . . . . . . 23–48
23.22.1 Fast I/O (Alpha Only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–48
23.22.1.1 Fast I/O Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–48
23.22.1.2 Buffer Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–49
23.22.2 Fast Path (Alpha Only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–51
23.22.2.1 Fast Path Features and Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . 23–51
23.22.2.2 Additional Information About Fast Path . . . . . . . . . . . . . . . . . . . . 23–52

24 Using Run-Time Library Routines to Access Operating System


Components
24.1 System Service Access Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–1
24.2 Access to the Command Language Interpreter . . . . . . . . . . . . . . . . . . . . . 24–2
24.2.1 Obtaining the Command Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–3
24.2.2 Chaining from One Program to Another . . . . . . . . . . . . . . . . . . . . . . . 24–5
24.2.3 Executing a CLI Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–7
24.2.4 Using Symbols and Logical Names . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–8
24.2.5 Disabling and Enabling Control Characters . . . . . . . . . . . . . . . . . . . . . 24–8
24.2.6 Creating and Connecting to a Subprocess . . . . . . . . . . . . . . . . . . . . . . 24–9
24.3 Access to VAX Machine Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–9
24.3.1 Variable-Length Bit Field Instruction Routines . . . . . . . . . . . . . . . . . . 24–10
24.3.2 Integer and Floating-Point Routines . . . . . . . . . . . . . . . . . . . . . . . . . . 24–12
24.3.3 Queue Access Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–12
24.3.4 Character String Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–14
24.3.5 Miscellaneous Instruction Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–15
24.4 Processwide Resource Allocation Routines . . . . . . . . . . . . . . . . . . . . . . . . . 24–16
24.4.1 Allocating Logical Unit Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–16
24.4.2 Allocating Event Flag Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–17
24.5 Performance Measurement Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–17
24.6 Output Formatting Control Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–20
24.7 Miscellaneous Interface Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–21
24.7.1 Indicating Asynchronous System Trap in Progress . . . . . . . . . . . . . . . 24–21
24.7.2 Create a Directory or Subdirectory . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–22
24.7.3 File Searching Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–22
24.7.4 Inserting an Entry into a Balanced Binary Tree . . . . . . . . . . . . . . . . . 24–29

vii
25 Using Cross-Reference Routines
25.1 How to Use the Cross-Reference Routines . . . . . . . . . . . . . . . . . . . . . . . . . 25–1
25.2 $CRFCTLTABLE Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–2
25.3 $CRFFIELD Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–3
25.4 $CRFFIELDEND Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–4
25.5 Cross-Reference Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–4
25.6 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–6
25.6.1 Defining Control Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–6
25.6.2 Inserting Table Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–8
25.6.3 Formatting Information for Output . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–9
25.7 How to Link to the Cross-Reference Shareable Image . . . . . . . . . . . . . . . . 25–10

26 Shareable Resources
26.1 Sharing Program Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–1
26.1.1 Object Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–2
26.1.1.1 System- and User-Defined Default Object Libraries . . . . . . . . . . . . 26–2
26.1.1.2 How the Linker Searches Libraries . . . . . . . . . . . . . . . . . . . . . . . . 26–2
26.1.1.3 Creating an Object Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–2
26.1.1.4 Managing an Object Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–2
26.1.2 Text and Macro Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–3
26.2 Shareable Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–3
26.3 Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–3
26.3.1 Defining Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–3
26.3.2 Local and Global Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–4
26.3.3 Resolving Global Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–4
26.3.3.1 Explicitly Named Modules and Libraries . . . . . . . . . . . . . . . . . . . . 26–5
26.3.3.2 System Default Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–5
26.3.3.3 User Default Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–5
26.3.3.4 Making a Library Available for Systemwide Use . . . . . . . . . . . . . . 26–5
26.3.3.5 Macro Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–5
26.3.4 Sharing Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–6
26.3.4.1 Installed Common Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–6
26.3.4.2 Using Global Sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–9
26.3.4.3 Synchronizing Access to Global Sections . . . . . . . . . . . . . . . . . . . . 26–13
26.3.4.4 RMS Shared Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26–13

27 System Time Operations


27.1 System Time Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–1
27.1.1 Absolute Time Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–1
27.1.2 Delta Time Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–2
27.2 Time Conversion and Date/Time Manipulation . . . . . . . . . . . . . . . . . . . . . 27–2
27.2.1 Time Conversion Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–2
27.2.1.1 Calculating and Displaying Time with SYS$GETTIM and
LIB$SUBX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–4
27.2.1.2 Obtaining Absolute Time with SYS$ASCTIM and
SYS$BINTIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–6
27.2.1.3 Obtaining Delta Time with SYS$BINTIM . . . . . . . . . . . . . . . . . . . 27–6
27.2.1.4 Obtaining Numeric and ASCII Time with SYS$NUMTIM . . . . . . . 27–7
27.2.2 Date/Time Manipulation Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–7
27.3 Timer Routines Used to Obtain and Set Current Time . . . . . . . . . . . . . . . 27–8
27.3.1 Obtaining Current Time and Date with LIB$DATE_TIME . . . . . . . . . 27–9
27.3.2 Obtaining Current Time and Date with SYS$GETTIM . . . . . . . . . . . . 27–10

viii
27.3.3 Setting the Current Time with SYS$SETIME . . . . . . . . . . . . . . . . . . . 27–11
27.4 Routines Used for Timer Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–13
27.4.1 Setting Timer Requests with SYS$SETIMR . . . . . . . . . . . . . . . . . . . . 27–14
27.4.2 Canceling a Timer Request with SYS$CANTIM . . . . . . . . . . . . . . . . . 27–16
27.4.3 Scheduling Wakeups with SYS$WAKE . . . . . . . . . . . . . . . . . . . . . . . . 27–16
27.4.4 Canceling a Scheduled Wakeup with SYS$CANWAK . . . . . . . . . . . . . . 27–17
27.4.5 Executing a Program at Timed Intervals . . . . . . . . . . . . . . . . . . . . . . . 27–18
27.5 Routines Used for Timer Statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–18
27.6 Date/Time Formatting Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–21
27.6.1 Performing Date/Time Logical Initialization . . . . . . . . . . . . . . . . . . . . 27–21
27.6.2 Selecting a Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–24
27.6.2.1 Formatting Run-Time Mnemonics . . . . . . . . . . . . . . . . . . . . . . . . . 27–24
27.6.2.2 Specifying Formats at Run Time . . . . . . . . . . . . . . . . . . . . . . . . . . 27–26
27.6.2.3 Specifying Input Formats at Run Time . . . . . . . . . . . . . . . . . . . . . 27–26
27.6.2.4 Specifying Output Formats at Run Time . . . . . . . . . . . . . . . . . . . . 27–29
27.6.2.5 Specifying Formats at Compile Time . . . . . . . . . . . . . . . . . . . . . . . 27–31
27.6.2.6 Specifying Input Format Mnemonics at Compile Time . . . . . . . . . 27–32
27.6.2.7 Specifying Output Formats at Compile Time . . . . . . . . . . . . . . . . . 27–33
27.6.3 Converting with the LIB$CONVERT_DATE_STRING Routine . . . . . . 27–33
27.6.4 Retrieving with LIB$GET_DATE_FORMAT Routine . . . . . . . . . . . . . . 27–34
27.6.4.1 Using User-Defined Output Formats . . . . . . . . . . . . . . . . . . . . . . . 27–34
27.7 Coordinated Universal Time Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–36

28 File Operations
28.1 File Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–1
28.1.1 Specifying File Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–2
28.1.2 Using Extended File Specifications (Alpha Only) . . . . . . . . . . . . . . . . . 28–2
28.2 File Access Strategies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–2
28.3 File Protection and Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–3
28.3.1 Read-Only Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–3
28.3.2 Shared Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–3
28.4 File Access and Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–4
28.4.1 Using SYS$CRMPSC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–4
28.4.1.1 Mapping a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–5
28.4.1.2 Using the User-Open Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–10
28.4.1.3 Initializing a Mapped Database . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–11
28.4.1.4 Saving a Mapped File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–11
28.5 Opening and Updating a Sequential File . . . . . . . . . . . . . . . . . . . . . . . . . . 28–12
28.6 User-Open Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–15
28.6.1 Opening a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–15
28.6.1.1 Specifying USEROPEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–15
28.6.1.2 Writing the User-Open Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–16
28.6.1.3 Setting FAB and RAB Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–17

29 Using the Distributed Transaction Manager


29.1 Introduction to DECdtm Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29–1
29.1.1 Sample Atomic Transaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29–1
29.1.2 Transaction Participants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29–2
29.1.3 DECdtm System Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29–2
29.1.4 Default Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29–3
29.2 Calling DECdtm System Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29–3
29.3 Using DECdtm Services: An Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29–3

ix
30 Creating User-Written System Services
30.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30–1
30.2 Writing a Privileged Routine (User-Written System Service) . . . . . . . . . . . 30–3
30.3 Creating a Privileged Shareable Image (VAX Only) . . . . . . . . . . . . . . . . . . 30–4
30.3.1 Creating User-Written Dispatch Routines on VAX Systems . . . . . . . . . 30–4
30.3.2 Creating a PLV on VAX Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30–5
30.3.3 Declaring Privileged Routines as Universal Symbols Using Transfer
Vectors on VAX Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30–9
30.4 Creating a User-Written System Service (Alpha Only) . . . . . . . . . . . . . . . 30–9
30.4.1 Creating a PLV on Alpha Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30–9
30.4.2 Declaring Privileged Routines as Universal Symbols Using Symbol
Vectors on Alpha Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30–13

31 System Security Services


31.1 Overview of the Operating System’s Protection Scheme . . . . . . . . . . . . . . 31–1
31.2 Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–2
31.2.1 Identifier Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–2
31.2.2 General Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–2
31.2.3 System-Defined Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–3
31.2.4 UIC Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–3
31.2.5 Facility Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–4
31.2.6 Identifier Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–5
31.3 Rights Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–8
31.3.1 Initializing a Rights Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–9
31.3.2 Using System Services to Affect a Rights Database . . . . . . . . . . . . . . . 31–10
31.3.2.1 Translating Identifier Values and Identifier Names . . . . . . . . . . . . 31–11
31.3.2.2 Adding Identifiers and Holders to the Rights Database . . . . . . . . . 31–12
31.3.2.3 Determining Holders of Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . 31–13
31.3.2.4 Determining Identifiers Held by a Holder . . . . . . . . . . . . . . . . . . . 31–13
31.3.2.5 Modifying the Identifier Record . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–13
31.3.2.6 Modifying a Holder Record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–14
31.3.2.7 Removing Identifiers and Holders from the Rights Database . . . . . 31–16
31.3.3 Search Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–16
31.3.4 Modifying a Rights List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–19
31.4 Persona (Alpha Only1 ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–19
31.4.1 Impersonation Services (Alpha Only) . . . . . . . . . . . . . . . . . . . . . . . . . . 31–20
31.4.1.1 Using Impersonation System Services . . . . . . . . . . . . . . . . . . . . . . 31–20
31.4.2 Per-Thread Security (Alpha Only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–21
31.4.2.1 Previous Security Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–21
31.4.2.2 Per-Thread Security Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–21
31.4.3 Persona Extensions (Alpha Only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–22
31.5 Managing Object Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–23
31.5.1 Protected Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–23
31.5.2 Object Security Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–24
31.5.2.1 Displaying the Security Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–24
31.5.2.2 Modifying the Security Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–24
31.5.3 Types of Access Control Entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–24
31.5.3.1 Design Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–25
31.5.3.2 Translating ACEs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–25
31.5.3.3 Creating and Maintaining ACEs . . . . . . . . . . . . . . . . . . . . . . . . . . 31–26
31.6 Protected Subsystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–27
31.7 Security Auditing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–28
31.8 Checking Access Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–28

x
31.8.1 Creating a Security Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–29
31.8.2 SYS$CHKPRO System Sevice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–29
31.8.3 SYS$CHECK_ACCESS System Service . . . . . . . . . . . . . . . . . . . . . . . . 31–29
31.9 SYS$CHECK_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–30
31.10 Implementing Site-Specific Security Policies . . . . . . . . . . . . . . . . . . . . . . . 31–30
31.10.1 Creating Loadable Security Services . . . . . . . . . . . . . . . . . . . . . . . . . . 31–30
31.10.1.1 Preparing and Loading a System Service . . . . . . . . . . . . . . . . . . . . 31–31
31.10.1.2 Removing an Executive Loaded Image . . . . . . . . . . . . . . . . . . . . . . 31–32
31.10.2 Installing Filters for Site-Specific Password Policies . . . . . . . . . . . . . . 31–33
31.10.2.1 Creating a Shareable Image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–33
31.10.2.2 Installing a Shareable Image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–33

32 Logical Name and Logical Name Tables


32.1 Logical Name System Services and DCL Commands . . . . . . . . . . . . . . . . . 32–1
32.1.1 Logical Names, Equivalence Names, and Search Lists . . . . . . . . . . . . 32–2
32.1.2 Logical Name Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–3
32.1.2.1 Logical Name Directory Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–3
32.1.2.2 Process, Job, Group, System and Clusterwide Default Logical
Name Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–4
32.1.2.2.1 Process Logical Name Table . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–4
32.1.2.2.2 Job Logical Name Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–5
32.1.2.2.3 Group Logical Name Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–6
32.1.2.2.4 System Logical Name Table . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–6
32.1.2.2.5 Clusterwide Logical Name Table . . . . . . . . . . . . . . . . . . . . . . . 32–6
32.1.3 Logical Name Table Names and Search Lists . . . . . . . . . . . . . . . . . . . 32–7
32.1.4 Specifying the Logical Name Table Search List . . . . . . . . . . . . . . . . . . 32–8
32.2 Creating User-Defined and Clusterwide Logical Name Tables . . . . . . . . . . 32–8
32.2.1 Creating Clusterwide Logical Name Tables . . . . . . . . . . . . . . . . . . . . . 32–9
32.3 Checking Access and Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–10
32.4 Specifying Access Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–10
32.5 Translating Logical Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–11
32.6 Specifying Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–13
32.7 Establishing Logical Name Table Quotas . . . . . . . . . . . . . . . . . . . . . . . . . . 32–15
32.7.1 Directory Table Quotas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–15
32.7.2 Default Logical Name Table Quotas . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–15
32.7.3 Job Logical Name Table Quotas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–15
32.7.4 User-Defined Logical Name Table Quotas . . . . . . . . . . . . . . . . . . . . . . 32–16
32.8 Interprocess Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–16
32.9 Using Logical Name and Equivalence Name Format Conventions . . . . . . . 32–17
32.10 Using Logical Names and Logical Name Table System Services in
Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–18
32.10.1 Using SYS$CRELNM to Create a Logical Name . . . . . . . . . . . . . . . . . 32–18
32.10.2 Using SYS$CRELNT to Create Logical Name Tables . . . . . . . . . . . . . 32–21
32.10.3 Using SYS$DELLNM to Delete Logical Names . . . . . . . . . . . . . . . . . . 32–21
32.10.4 Using SYS$TRNLNM to Translate Logical Names . . . . . . . . . . . . . . . 32–22
32.10.5 Using SYS$CRELNM, SYS$TRNLNM, and SYS$DELLNM in a
Program Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–24

xi
33 Image Initialization
33.1 Initializing an Image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33–1
33.2 Initializing an Argument List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33–5
33.3 Declaring Initialization Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33–6
33.4 Dispatching to Initialization Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33–7
33.5 Initialization Routine Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33–7
33.6 Initialization Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33–7

Part III Appendixes

A Generic Macros for Calling System Services


A.1 Using Macros to Construct Argument Lists . . . . . . . . . . . . . . . . . . . . . . . . A–2
A.1.1 Specifying Arguments with the $name_S Macro and the $name Macro
....................................................... A–2
A.1.2 Conventions for Specifying Arguments to System Services . . . . . . . . . A–4
A.1.3 Defining Symbolic Names for Argument List Offsets: $name and
$nameDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A–4
A.2 Using Macros to Call System Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . A–5
A.2.1 The $name_S Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A–6
A.2.1.1 Example of $name_S Macro Call . . . . . . . . . . . . . . . . . . . . . . . . . . A–6
A.2.2 The $name_G Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A–6
A.2.3 The $name Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A–6
A.2.4 Example of $name and $name_G Macro Calls . . . . . . . . . . . . . . . . . . . A–7

B OpenVMS Data Types


B.1 OpenVMS Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–1
B.2 Ada Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–17
B.3 Application Programming Language (APL) Implementations . . . . . . . . . . B–20
B.4 BASIC Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–22
B.5 BLISS Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–25
B.6 C and C++ Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–28
B.7 COBOL Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–30
B.8 FORTRAN Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–34
B.9 Pascal Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–38
B.10 PL/I Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–42
B.11 VAX MACRO Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–48
B.12 RPG II Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–50
B.13 SCAN Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–52

C Distributed Name Service (VAX Only)


C.1 DECdns Clerk System Service . . . . . . . . . . . . . . . . . . . . . . . . . ......... C–1
C.1.1 Using the DECdns System Service and Run-Time Library
Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C–2
C.1.1.1 Using the SYS$DNS System Service . . . . . . . . . . . . . . . . . . . . . . . C–2
C.1.1.2 Using the Run-Time Library Routines . . . . . . . . . . . . . . . . . . . . . . C–4
C.2 Using the SYS$DNS System Service Call . . . . . . . . . . . . . . . . . . . . . . . . . C–4
C.2.1 Creating Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C–4
C.2.2 Modifying Objects and Their Attributes . . . . . . . . . . . . . . . . . . . . . . . . C–6

xii
C.2.3 Requesting Information from DECdns . . . . . . . . . . . . . . . . . . . . . . . . . C–9
C.2.3.1 Using the Distributed File Service (DFS) . . . . . . . . . . . . . . . . . . . . C–9
C.2.3.2 Reading Attributes from DNS . . . . . . . . . . . . . . . . . . . . . . . . . . . . C–10
C.2.3.3 Enumerating DECdns Names and Attributes . . . . . . . . . . . . . . . . C–13
C.3 Using the DCL Command DEFINE with DECdns Logical Names . . . . . . . C–16

Index

Examples
20–1 Example of SYS$SYNCH System Service in FORTRAN . . . . . . . . . . . 20–6
20–2 System Service Call in Ada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–11
20–3 System Service Call in BASIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–13
20–4 System Service Call in BLISS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–14
20–5 System Service Call in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–15
20–6 System Service Call in COBOL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–16
20–7 System Service Call in FORTRAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–17
20–8 System Service Call in Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–19
20–9 System Service Call in VAX MACRO . . . . . . . . . . . . . . . . . . . . . . . . . . 20–20
22–1 Reading a Line of Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–5
22–2 Reading a Varying Number of Input Records . . . . . . . . . . . . . . . . . . . . 22–5
22–3 Associating a Pasteboard with a Terminal . . . . . . . . . . . . . . . . . . . . . . 22–10
22–4 Creating a Pasteboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–11
22–5 Modifying Screen Dimensions and Background Color . . . . . . . . . . . . . 22–11
22–6 Defining and Pasting a Virtual Display . . . . . . . . . . . . . . . . . . . . . . . . 22–13
22–7 Scrolling Forward Through a Display . . . . . . . . . . . . . . . . . . . . . . . . . 22–21
22–8 Scrolling Backward Through a Display . . . . . . . . . . . . . . . . . . . . . . . . 22–21
22–9 Creating a Statistics Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–22
22–10 Reading Data from a Virtual Keyboard . . . . . . . . . . . . . . . . . . . . . . . . 22–25
22–11 Reading Data from the Keypad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–27
22–12 Redefining Keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–29
22–13 Using Interrupts to Perform I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–35
22–14 Receiving Unsolicited Input from a Virtual Keyboard . . . . . . . . . . . . . 22–37
22–15 Trapping Broadcast Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–44
23–1 Event Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–15
23–2 AST Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–16
23–3 I/O Status Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–17
23–4 Reading Data from the Terminal Synchronously . . . . . . . . . . . . . . . . . 23–20
23–5 Reading Data from the Terminal Asynchronously . . . . . . . . . . . . . . . . 23–21
23–6 Writing Character Data to a Terminal . . . . . . . . . . . . . . . . . . . . . . . . . 23–23
23–7 Using SYS$GETDVIW to Verify the Device Name . . . . . . . . . . . . . . . . 23–29
23–8 Disabling the HOSTSYNC Terminal Characteristic . . . . . . . . . . . . . . . 23–30
26–1 Interprocess Communication Using Global Sections . . . . . . . . . . . . . . 26–9
27–1 Calculating and Displaying the Time . . . . . . . . . . . . . . . . . . . . . . . . . . 27–5
27–2 Setting an Event Flag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–14
27–3 Specifying an AST Service Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–15
27–4 Displaying and Writing Timer Statistics . . . . . . . . . . . . . . . . . . . . . . . 27–19

xiii
28–1 Mapping a Data File to the Common Block on a VAX System . . . . . . . 28–6
28–2 Mapping a Data File to the Common Block on an Alpha System . . . . . 28–8
28–3 Using a User-Open Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–10
28–4 Closing a Mapped File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–12
28–5 Creating a Sequential File of Fixed-Length Records . . . . . . . . . . . . . . 28–13
28–6 Updating a Sequential File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28–14
30–1 Sample Dispatching Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30–5
30–2 Assigning Values to a PLV on a VAX System . . . . . . . . . . . . . . . . . . . . 30–8
30–3 Creating a PLV on Alpha Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30–12
30–4 Declaring Universal Symbols for Privileged Shareable Image on an
Alpha System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. 30–13
A–1 Using Keywords with the $name_S Macro . . . . . . . . . . . . . . . . . . . . .. A–2
A–2 Specifying Arguments in Positional Order with the $name_S
Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. A–2
A–3 Using Keywords with the $name Macro . . . . . . . . . . . . . . . . . . . . . . .. A–3
A–4 Specifying Arguments in Positional Order with the $name Macro . . .. A–3

Figures
18–1 Call Frame Generated by CALLG and CALLS Instructions . . . . . . . . . 18–4
18–2 Fixed-Size Stack Frame Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–6
18–3 Variable-Size Stack Frame Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–8
18–4 Structure of a VAX Argument List . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–9
18–5 Alpha Argument List Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–10
18–6 Argument Information (AI) Register (R25) Format . . . . . . . . . . . . . . . 18–10
18–7 Alpha Procedure Argument-Passing Mechanisms . . . . . . . . . . . . . . . . 18–12
18–8 VAX Procedure Argument-Passing Mechanisms . . . . . . . . . . . . . . . . . . 18–13
18–9 Atomic Data Types and Descriptor Classes . . . . . . . . . . . . . . . . . . . . . 18–20
18–10 String Data Types and Descriptor Classes . . . . . . . . . . . . . . . . . . . . . . 18–21
18–11 Miscellaneous Data Types and Descriptor Classes . . . . . . . . . . . . . . . . 18–21
18–12 Condition Value Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–23
19–1 Calling the Run-Time Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19–2
22–1 Defining and Pasting Virtual Displays . . . . . . . . . . . . . . . . . . . . . . . . . 22–14
22–2 Moving a Virtual Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–15
22–3 Repasting a Virtual Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–16
22–4 Popping a Virtual Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–17
22–5 Statistics Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–22
23–1 Mailbox Protection Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–5
23–2 Physical I/O Access Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–7
23–3 Logical I/O Access Checks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–8
23–4 Physical, Logical, and Virtual I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–9
23–5 I/O Function Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–10
23–6 Function Modifier Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–11
23–7 I/O Status Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–24
23–8 SYS$MOUNT Item Descriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–34
24–1 Format of a Variable-Length Bit Field . . . . . . . . . . . . . . . . . . . . . . . . . 24–11
25–1 Using Cross-Reference Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–2

xiv
25–2 Summary of Symbol Names and Values . . . . . . . . . . . . . . . . . . . . . . .. 25–5
25–3 Summary of Symbol Names, Values, and Name of Referring
Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–5
25–4 Summary Indicating Defining Module . . . . . . . . . . . . . . . . . . . . . . . . . 25–5
25–5 Output Line for LIB$CRF_OUTPUT . . . . . . . . . . . . . . . . . . . . . . . . . . 25–6
27–1 Predefined Output Date Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–23
27–2 Predefined Output Time Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–23
29–1 Participants in a Distributed Transaction . . . . . . . . . . . . . . . . . . . . . . 29–2
30–1 Flow of Control Accessing a Privileged Routine on VAX Systems . . . . . 30–6
30–2 Components of the Privileged Library Vector on VAX Systems . . . . . . 30–7
30–3 Linkage for a Privileged Routine After Image Activation . . . . . . . . . . . 30–10
31–1 ID Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–3
31–2 UIC Identifier Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–4
31–3 Facility-Specific Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–4
31–4 Format of the Identifier Record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–8
31–5 Format of the Holder Record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–9
31–6 Format of the Holder Argument . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–13
31–7 Previous Per-Thread Security Model . . . . . . . . . . . . . . . . . . . . . . . . . . 31–21
31–8 Per-Thread Security Profile Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–22
33–1 Sequence of Events During Image Initialization on VAX Systems . . . . 33–4
33–2 Sequence of Events During Image Initialization on Alpha Systems . . . 33–5

Tables
17–1 Main Headings in the Documentation Format for System Routines . . 17–2
17–2 General Rules of Syntax for Procedure Call Formats . . . . . . . . . . . . . . 17–3
17–3 Standard Data Types and Their Descriptor Field Symbols . . . . . . . . . 17–7
17–4 Descriptor Classes of Passing Mechanisms . . . . . . . . . . . . . . . . . . . . . 17–10
18–1 VAX Register Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–1
18–2 Alpha Integer Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–2
18–3 Alpha Floating-Point Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–3
18–4 Contents of the Argument Information (AI) Register (Alpha only) . . . . 18–11
18–5 String-Passing Descriptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18–18
20–1 OpenVMS System Access Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20–3
20–2 Severity Codes of Condition Value Returned . . . . . . . . . . . . . . . . . . . . 20–7
21–1 Structures Used by _NEW_STARLET Prototypes . . . . . . . . . . . . . . . . 21–4
22–1 SYS$INPUT and SYS$OUTPUT Values . . . . . . . . . . . . . . . . . . . . . . . 22–3
22–2 Setting Video Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22–18
23–1 Read and Write I/O Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–10
23–2 Asynchronous Input/Output Services and Their Synchronous Versions
....................................................... 23–19
23–3 System Services for Translating Logical Names . . . . . . . . . . . . . . . . . . 23–27
23–4 Default Device Names for I/O Services . . . . . . . . . . . . . . . . . . . . . . . . 23–28
23–5 SYSGEN Buffer Object Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . 23–50
24–1 System Service Access Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–2
24–2 CLI Access Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–2
24–3 Variable-Length Bit Field Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–10

xv
24–4 Integer and Floating-Point Routines . . . . . . . . . . . . . . . . . . . . . . . . . . 24–12
24–5 Queue Access Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–13
24–6 Character String Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–14
24–7 Miscellaneous Instruction Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–15
24–8 Processwide Resource Allocation Routines . . . . . . . . . . . . . . . . . . . . . . 24–16
24–9 Performance Measurement Routines . . . . . . . . . . . . . . . . . . . . . . . . . . 24–17
24–10 The Code Argument in LIB$SHOW_TIMER and
LIB$STAT_TIMER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–18
24–11 Routines for Customizing Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–20
24–12 Miscellaneous Interface Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24–21
25–1 Cross-Reference Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25–1
27–1 Time Conversion Routines and System Services . . . . . . . . . . . . . . . . . 27–3
27–2 Date/Time Manipulation Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–8
27–3 Timer RTLs and System Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–8
27–4 Timer System Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–13
27–5 Available Languages for Date/Time Formatting . . . . . . . . . . . . . . . . . . 27–22
27–6 Format Mnemonics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–24
27–7 Input String Punctuation and Defaults . . . . . . . . . . . . . . . . . . . . . . . . 27–28
27–8 Predefined Output Date Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–29
27–9 Predefined Output Time Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–30
27–10 Available Components for Specifying Formats at Compile Time . . . . . 27–31
27–11 Legible Format Mnemonics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–32
27–12 Sample Input Format Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27–34
30–1 Components of the VAX Privileged Library Vector . . . . . . . . . . . . . . . . 30–7
30–2 Components of the Alpha Privileged Library Vector . . . . . . . . . . . . . . . 30–11
31–1 Using System Services to Manipulate Elements of the Rights
Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ..... 31–10
31–2 Returned Records of SYS$IDTOASC, SYS$FIND_HELD, and
SYS$FIND_HOLDER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–17
31–3 Item Code Symbols and Meanings . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31–26
32–1 Logical Name Services and DCL Commands . . . . . . . . . . . . . . . . . . . . 32–2
32–2 Summary of Privileges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32–10
A–1 Generic Argument List Macros of the System Service Interface . . . . . A–1
B–1 OpenVMS Usage Data Type Entries . . . . . . . . . . . . . . . . . . . . . . . . . . B–2
B–2 Ada Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–17
B–3 APL Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–20
B–4 BASIC Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–22
B–5 BLISS Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–25
B–6 C and C++ Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–28
B–7 COBOL Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–31
B–8 FORTRAN Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–34
B–9 Pascal Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–39
B–10 PL/I Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–42
B–11 VAX MACRO Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–48
B–12 RPG II Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–50
B–13 SCAN Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B–52

xvi
Preface

Intended Audience
This manual is intended for system and application programmers. It presumes
that its readers have some familiarity with the OpenVMS programming
environment, derived from the OpenVMS Programming Environment Manual
and OpenVMS high-level language documentation. The OpenVMS Programming
Environment Manual has been archived but is available on the OpenVMS
Documentation CD_ROM.

Document Structure
The printed copy of the OpenVMS Programming Concepts Manual is a two
volume manual. The second volume contains three parts; the three parts are as
follows:
• OpenVMS Programming Interfaces: Calling a System Routine
• I/O, System and Programming Routines
• Appendixes
The chapters in Volume II provide information about the programming features
of the OpenVMS operating system. A list of the chapters and a summary of their
content are as follows:
• Chapter 17, Call Format to OpenVMS Routines, describes the format used
to document system routine calls and explains where to find and how to
interpret information about routine calls.
• Chapter 18, Basic Calling Standard Conventions, describes the concepts and
conventions used by common languages to invoke routines and pass data
between them.
• Chapter 19, Calling Run-Time Library Routines, describes a set of language-
independent routines that establishes a common run-time environment for
user programs.
• Chapter 20, Calling System Services, describes the system services available
to application and system programs for use at run time.
• Chapter 21, STARLET Structures and Definitions for C Programmers,
describes the libraries that contain C header files for routines.
• Chapter 22, Run-Time Library Input/Output Operations, describes the
different I/O programming capabilities provided by the run-time library.
• Chapter 23, System Service Input/Output Operations, describes how to use
system services to perform input and output operations.

xvii
• Chapter 24, Using Run-Time Library Routines to Access Operating System
Components, describes the run-time library (RTL) routines that allow access
to various operating system components.
• Chapter 25, Using Cross-Reference Routines, describes how cross-reference
routines that are contained in a separate, shareable image are capable of
creating a cross-reference analysis of symbols.
• Chapter 26, Shareable Resources, describes the techniques available for
sharing data and program code among programs.
• Chapter 27, System Time Operations, describes the system time format,
and the manipulation of date/time and time conversion. It further describes
how to obtain and set the current date and time, how to set and cancel
timer requests, and how to schedule and cancel wakeups. The Coordinated
Universal Time (UTC) system is also described.
• Chapter 28, File Operations, describes file attributes, strategies to access
files, and file protection techniques.
• Chapter 29, Using the Distributed Transaction Manager, describes the use
of the DECdtm system services to ensure the integrity and consistency of
distributed transactions by implementing a two-phase commit protocol.
• Chapter 30, Creating User-Written System Services, describes how to create
user-written system services with privileged shareable images for both VAX
systems and Alpha systems.
• Chapter 31, System Security Services, describes the system services that
establish protection by using identifiers, rights databases, and access control
entries. This chapter also describes how to modify a rights list as well as
check access protection.
• Chapter 32, Logical Name and Logical Name Tables, describes how to create
and use logical name services, how to use logical and equivalence names, and
how to add and delete entries to a logical name table.
• Chapter 33, Image Initialization, describes how to use the LIB$INITIALIZE
routine to initialize an image.
• Appendix A, Generic Macros for Calling System Services, describes the use
of generic macros to specify argument lists with appropriate symbols and
conventions in the system services interface to MACRO assembles.
• Appendix B, OpenVMS Data Types, describes the data types that provide
compatibility between procedure calls that support many different high-level
languages.
• Appendix C, Distributed Name Service, describes the Digital Distributed
Name Service (DECdns) Clerk by introducing the functions of the DECdns
(SYS$DNS) system service and various run-time library routines.

Related Documents
For a detailed description of each run-time library and system service routine
mentioned in this manual, see the OpenVMS Run-Time Library documentation
and the OpenVMS System Services Reference Manual.

xviii
You can find additional information about calling OpenVMS system services and
Run-Time Library routines in your language processor documentation. You may
also find the following documents useful:
• OpenVMS DCL Dictionary
• OpenVMS User’s Manual
• Guide to OpenVMS File Applications
• OpenVMS Guide to System Security
• DECnet for OpenVMS Networking Manual
• OpenVMS Record Management Services documentation
• OpenVMS Utility Routines Manual
• OpenVMS I/O User’s Reference Manual
For additional information about OpenVMS products and services, access the
following World Wide Web address:
http://www.openvms.compaq.com/

Reader’s Comments
Compaq welcomes your comments on this manual. Please send comments to
either of the following addresses:
Internet [email protected]
Mail Compaq Computer Corporation
OSSG Documentation Group, ZKO3-4/U08
110 Spit Brook Rd.
Nashua, NH 03062-2698

How To Order Additional Documentation


Use the following World Wide Web address to order additional documentation:
http://www.openvms.compaq.com/
If you need help deciding which documentation best meets your needs, call
800-282-6672.

Conventions
The following conventions are used in this manual:
Ctrl/x A sequence such as Ctrl/x indicates that you must hold down
the key labeled Ctrl while you press another key or a pointing
device button.
PF1 x A sequence such as PF1 x indicates that you must first press
and release the key labeled PF1 and then press and release
another key or a pointing device button.
Return In examples, a key name enclosed in a box indicates that
you press a key on the keyboard. (In text, a key name is not
enclosed in a box.)
In the HTML version of this document, this convention appears
as brackets, rather than a box.

xix
... A horizontal ellipsis in examples indicates one of the following
possibilities:
• Additional optional arguments in a statement have been
omitted.
• The preceding item or items can be repeated one or more
times.
• Additional parameters, values, or other information can be
entered.

. A vertical ellipsis indicates the omission of items from a code


. example or command format; the items are omitted because
. they are not important to the topic being discussed.
() In command format descriptions, parentheses indicate that you
must enclose choices in parentheses if you specify more than
one.
[] In command format descriptions, brackets indicate optional
choices. You can choose one or more items or no items.
Do not type the brackets on the command line. However,
you must include the brackets in the syntax for OpenVMS
directory specifications and for a substring specification in an
assignment statement.
| In command format descriptions, vertical bars separate choices
within brackets or braces. Within brackets, the choices are
optional; within braces, at least one choice is required. Do not
type the vertical bars on the command line.
{} In command format descriptions, braces indicate required
choices; you must choose at least one of the items listed. Do
not type the braces on the command line.
bold text This typeface represents the introduction of a new term. It
also represents the name of an argument, an attribute, or a
reason.
italic text Italic text indicates important information, complete titles
of manuals, or variables. Variables include information that
varies in system output (Internal error number), in command
lines (/PRODUCER=name), and in command parameters in
text (where dd represents the predefined code for the device
type).
UPPERCASE TEXT Uppercase text indicates a command, the name of a routine,
the name of a file, or the abbreviation for a system privilege.
Monospace text Monospace text indicates code examples and interactive screen
displays.
In the C programming language, monospace type in text
identifies the following elements: keywords, the names
of independently compiled external functions and files,
syntax summaries, and references to variables or identifiers
introduced in an example.
- A hyphen at the end of a command format description,
command line, or code line indicates that the command or
statement continues on the following line.
numbers All numbers in text are assumed to be decimal unless
otherwise noted. Nondecimal radixes—binary, octal, or
hexadecimal—are explicitly indicated.

xx
Part I
OpenVMS Programming Interfaces: Calling a
System Routine

This part of this second volume describes the basic calling format for OpenVMS
routines and system services. It also describes the STARLET structures and
definitions for C programmers.
17
Call Format to OpenVMS Routines

This chapter describes the format used to document system routine calls and
explains where to find and how to interpret information about routine calls.
Subsequent chapters provide more specific information about calling run-time
library (RTL) routines and system services.

Note
The documentation format described in this chapter is generic; portions
of it are used or not used, as appropriate, in the following OpenVMS
manuals that document system routines:
OpenVMS System Services Reference Manual: A–GETUAI
OpenVMS System Services Reference Manual: GETUTC–Z
OpenVMS Run-Time Library manuals
OpenVMS Utility Routines Manual
OpenVMS Record Management Services Reference Manual

17.1 Overview
This chapter provides additional explanations for the following documentation
categories for routines:
• Format
• Returns
• Arguments
• Condition values returned
However, some main categories in the routine format contain information
requiring no explanation beyond that given in Table 17–1.

Call Format to OpenVMS Routines 17–1


Call Format to OpenVMS Routines
17.1 Overview

Table 17–1 Main Headings in the Documentation Format for System Routines
Main Heading Description
Routine Name Always present. The routine entry point name appears at the
top of the first page. It is usually followed by the English text
name of the routine.
Routine Overview Always present. Appears directly below the routine name and
briefly explains what the routine does.
Format Always present. Follows the routine overview and gives the
routine entry point name and the routine argument list.
Returns Always present. Follows the routine format and explains what
information is returned by the routine.
Arguments Always present. Follows the Returns heading and gives
detailed information about each argument. If a routine takes
no arguments, the word None appears.
Description Optional. Follows the Arguments heading and contains
information about specific actions taken by the routine:
interaction between routine arguments, if any; operation of
the routine within the context of OpenVMS; user privileges
needed to call the routine, if any; system resources used by the
routine; and user quotas that might affect the operation of the
routine.
Note that any restrictions on the use of the routine are always
discussed first in the Description section. For example, any
required user privileges or necessary system resources are
explained first.
For some simple routines, a Description section is not
necessary because the routine overview provides the needed
information.
Condition Values Always present. Follows the Description section and lists the
Returned condition values (typically status or completion codes) that are
returned by the routine.
Example Optional. Follows the Condition Values Returned heading and
contains one or more programming examples that illustrate
how to use the routine, followed by an explanation.
All examples under this heading are complete. They have
been tested and should run when compiled (or assembled)
and linked. Throughout the manuals that document system
routines, examples are provided in as many different
programming languages as possible.

17.2 Format Heading


The following three types of information can be present in the format heading:
• Procedure call format
• Explanatory text
• Jump to Subroutine (JSB) format (VAX only)
On VAX processors, all system routines have a procedure call format, but few
system routines have JSB formats. If a routine has a JSB format, the format
always appears after the routine’s procedure call format.

17–2 Call Format to OpenVMS Routines


Call Format to OpenVMS Routines
17.2 Format Heading

17.2.1 Procedure Call Format


Procedure call formats can appear in many forms. The following four formats
illustrate the meaning of syntactical elements, such as brackets and commas.
General rules of syntax governing how to use procedure call formats are shown in
Table 17–2.

Table 17–2 General Rules of Syntax for Procedure Call Formats


Element Syntax Rule
Entry point names Entry point names are always shown in uppercase characters.
Argument names Argument names are always shown in lowercase characters.
Spaces One or more spaces are used between the entry point name
and the first argument, and between each argument.
Braces ( {} ) Braces surround two or more arguments. You must choose one
of the arguments.
Brackets ( [ ] ) Brackets surround optional arguments. Note that commas
can also be optional (see the comma element). Note that
programming language syntax for optional arguments differs
between languages. Refer to your language user’s guide for
more information.
Commas ( , ) Between arguments, the comma always follows the space.
If the argument is optional, the comma might appear either
inside or outside the brackets, depending on the position of the
argument in the list and on whether surrounding arguments
are optional or required.
Null arguments A null argument is a placeholding argument. It is used for one
of the following reasons: ( 1 ) to hold a place in the argument
list for an argument that has not yet been implemented by
Compaq but might be in the future; or ( 2 ) to mark the position
of an argument that was used in earlier versions of the routine
but is not used in the latest version (upward compatibility
is thereby ensured because arguments that follow the null
argument in the argument list keep their original positions). A
null argument is always given the name nullarg.
In the argument list constructed when a procedure is called,
both null arguments and omitted optional arguments are
represented by argument list entries containing the value
0. The programming language syntax required to produce
argument list entries containing 0 differs from language to
language. See your language user’s guide for language-specific
syntax.

Format 1 This format illustrates the standard representation of optional


arguments and best describes the use of commas as delimiters. Arguments
enclosed within square brackets are optional. In most languages, if an optional
argument other than a trailing optional argument is omitted, you must include a
comma as a delimiter for the omitted argument.
ROUTINE_NAME arg1[, [arg2][, arg3]]
Typically, OpenVMS RMS system routines use this format when a maximum of
three arguments appear in the argument list.

Call Format to OpenVMS Routines 17–3


Call Format to OpenVMS Routines
17.2 Format Heading

Format 2 When the argument list contains three or more optional arguments,
the syntax does not provide enough information. If you omit the optional
arguments arg3 and arg4 and specify the trailing argument arg5, you must use
commas to delimit the positions of the omitted arguments.
ROUTINE_NAME arg1, [arg2], nullarg, [arg3], [arg4], arg5
Typically, system services, utility routines, and run-time library routines contain
call formats with more than three arguments.
Format 3 In the following call format, the trailing four arguments are optional
as a group; that is, you specify either arg2, arg3, arg4, and arg5, or none of
them. Therefore, if you do not specify the optional arguments, you need not use
commas to delimit unoccupied positions.
However, if you specify a required argument or a separate optional argument
after arg5, you must use commas when arg2, arg3, arg4, and arg5 are omitted.
ROUTINE_NAME arg1[, arg2, arg3, arg4, arg5]
Format 4 In the following example, you can specify arg2 and omit arg3.
However, whenever you specify arg3, you must specify arg2.
ROUTINE_NAME arg1[, arg2[, arg3]]

17.2.2 JSB Call Format (VAX only)


The JSB call format indicates that the named routine is called using the VAX JSB
instruction. The routine returns using Return from Subroutine (RSB). You can
use the JSB call format with only the VAX MACRO and VAX BLISS languages.
Explanatory Text
Explanatory text might follow the procedure call format or the JSB call format, or
both. This text is present only when needed to clarify the format. For example,
in the call format, you indicate that arguments are optional by enclosing them
in brackets ( [ ] ). However, brackets alone cannot convey all the important
information that might apply to optional arguments. For example, in some
routines that have many optional arguments, if you select one optional argument,
you must also select another optional argument. In such cases, text following the
format clarifies this.

17.3 Returns Heading


The Returns heading contains a description of any information returned by the
routine to the caller. A routine can return information to the caller in various
ways. The following subsections discuss each possibility and then describe how
this returned information is presented.

17.3.1 Condition Values Returned in a Register


Most routines return a condition value in register R0. This condition value
contains various kinds of information, the most important for the caller (in bits
<3:0>) being the completion status of the operation. You test the condition value
to determine whether the routine completed successfully.
On Alpha processors, a 32-bit condition value is represented in the Alpha register
sign-extended to 64 bits.

17–4 Call Format to OpenVMS Routines


Call Format to OpenVMS Routines
17.3 Returns Heading

If you program in high-level languages for OpenVMS environments, the fact


that status information is returned by means of a condition value and that it is
returned in a hardware register is of little importance because you receive this
status information in the return (or status) variable. The run-time environment
established for the high-level language program allows the status information in
R0 to be moved automatically to the user’s return variable.
Nevertheless, for routines that return a condition value, the Returns heading in
the documentation contains the following information:
OpenVMS usage: cond_value
type: longword (unsigned)
access: write only
mechanism: by value
The OpenVMS usage entry specifies the OpenVMS data type of the information
returned. Because a condition value in any OpenVMS operating system
environment is returned in a specific condition value structure, the OpenVMS
usage entry is cond_value.
The type entry specifies the standard data type of the information returned.
Because the condition value structure is 32 bits, the type heading is longword
(unsigned).
The access entry specifies the way in which the called routine accesses the
object. Because the called routine is returning the condition value, the routine
writes the value into R0, so the access heading is write only.
The mechanism heading specifies the passing mechanism used by the called
routine in returning the condition value. Because the called routine is writing
the condition value directly into R0, the mechanism heading is by value. (If the
called routine had written the address of the condition value into R0, the passing
mechanism would have been by reference.)
Note that if a routine returns a condition value, another main heading in
the documentation format (Condition Values Returned) describes the possible
condition values that the routine can return.

17.3.2 Other Returned Values


If a routine returns actual data, the Returns heading in the documentation
of that routine contains the following information (for example, from a math
routine):
OpenVMS usage: floating_point
type: G_floating
access: write only
mechanism: by value
In this mathematics routine notation, the OpenVMS data type is floating_point
and the standard data type is G_floating point. The meaning of the contents of
the access and mechanism headings is discussed in Sections 17.4.3 and 17.4.4.
The registers used to return values vary with the type of the result and the
specific hardware environment. For more information, see the OpenVMS Calling
Standard.
In addition, under the Returns heading, some text can be provided after the
information about the type, access, and mechanism. This text explains other
relevant information about what the routine is returning.

Call Format to OpenVMS Routines 17–5


Call Format to OpenVMS Routines
17.3 Returns Heading

For example, because the routine is returning actual data in the VAX or Alpha
registers, the registers cannot be used to convey completion status information.
All routines that return actual data in VAX or Alpha registers must signal the
condition value, which contains the completion status. Thus, the text under the
Returns heading points out that the routine signals its completion status.

17.3.3 Condition Values Signaled


Although most routines return condition values, some routines choose to signal
their condition values using the OpenVMS signaling mechanism. Routines can
signal their completion status whether or not they are returning actual data in
the hardware registers, but all routines that return actual data in the hardware
registers must signal their completion status if they are to return this status
information at all.
If a routine signals its completion status, text under the Returns heading explains
this, and the Condition Values Signaled heading in the documentation format
describes the possible condition values that the routine can signal.
Compaq’s system routines never signal condition values indicating success. Only
error condition values are signaled.

17.4 Arguments Heading


Detailed information about each argument is listed in the call format under the
Arguments heading. Arguments are described in the order in which they appear
in the call format. If the routine has no arguments, the word None appears.
The following format is used to describe each argument:
argument-name
OpenVMS usage: OpenVMS data type
type: argument data type
access: argument access
mechanism: argument passing mechanism
A paragraph of structured text describing the arguments follows the argument
format along with additional information, if needed.

17.4.1 OpenVMS Usage Entry


The purpose of the OpenVMS usage entry is to facilitate the coding of source-
language data type declarations in application programs. Ordinarily, the standard
data type, discussed in Section 17.4.2, is sufficient to describe the type of data
passed by an argument. However, within the OpenVMS operating system
environment, many system routines contain arguments whose conceptual nature
or complexity requires additional explanation. For instance, when an argument
passes the name of an event flag, the type entry longword (unsigned) alone
does not indicate the nature of the value. In this instance, an accompanying
OpenVMS usage entry, denoting the OpenVMS data type ef_number, further
explains the actual usage.
See Table B–1 for a list of the possible OpenVMS usage entries and their
definitions. Refer to the appropriate language implementation table in
Appendix B to determine the correct syntax of the type declaration in the
language you are using.
Note that the OpenVMS usage entry is not a traditional data type (such as the
standard data types of byte, word, longword, and so on). It is significant only
within the context of the OpenVMS operating system and is intended solely to
expedite data declarations within application programs.

17–6 Call Format to OpenVMS Routines


Call Format to OpenVMS Routines
17.4 Arguments Heading

17.4.2 Type Entry


In actuality, an argument does not have a data type; rather, the data specified
by an argument has a data type. The argument is merely the vehicle for passing
data to the called routine. Nevertheless, the phrase argument data type is used
to describe the standard data type of the data specified by the argument.
Procedure calls result in the construction of an argument list. (This process is
described in the OpenVMS Calling Standard.) An argument list is a sequence of
entries together with a count of the number of entries.
On VAX systems, an argument list is represented as a vector of longwords, where
the first longword contains the count and each remaining longword contains one
argument.
On Alpha systems, an argument list is represented as quadword entities that
comprise an argument item sequence, partly in hardware registers and
(when there are more than six arguments) partly on the stack. The argument
information (AI) register contains the argument count that specifies the number
of 64-bit argument items.
When arguments are passed by descriptors, these standard data types are defined
with symbolic codes. Table 17–3 lists the standard data types for VAX and Alpha
systems that can appear for the type entry in an argument description, along
with their symbolic code (DTYPE) used in argument descriptors.
For a detailed description of each of the following symbolic codes, see the
OpenVMS Calling Standard.

Table 17–3 Standard Data Types and Their Descriptor Field Symbols
Data Type Symbolic Code
Absolute date and time DSC$K_DTYPE_ADT
Byte integer (signed) DSC$K_DTYPE_B
Bound label value DSC$K_DTYPE_BLV
1
Bound procedure value DSC$K_DTYPE_BPV
Byte (unsigned) DSC$K_DTYPE_BU
COBOL intermediate temporary DSC$K_DTYPE_CIT
D_floating DSC$K_DTYPE_D
D_floating complex DSC$K_DTYPE_DC
Descriptor DSC$K_DTYPE_DSC
F_floating DSC$K_DTYPE_F
F_floating complex DSC$K_DTYPE_FC
G_floating DSC$K_DTYPE_G
G_floating complex DSC$K_DTYPE_GC
H_floating1 DSC$K_DTYPE_H
1
H_floating complex DSC$K_DTYPE_HC
2
S_floating (32-bit IEEE) DSC$K_DTYPE_FS

1 VAX specific.
2 Alpha specific.

(continued on next page)

Call Format to OpenVMS Routines 17–7


Call Format to OpenVMS Routines
17.4 Arguments Heading

Table 17–3 (Cont.) Standard Data Types and Their Descriptor Field Symbols
Data Type Symbolic Code
2
T_floating (64-bit IEEE) DSC$K_DTYPE_FT
X_floating (128-bit IEEE)2 DSC$K_DTYPE_FX
2
S_floating complex DSC$K_DTYPE_FSC
2
T_floating complex DSC$K_DTYPE_FTC
X_floating complex2 DSC$K_DTYPE_FXC
Longword integer (signed) DSC$K_DTYPE_L
Longword (unsigned) DSC$K_DTYPE_LU
Numeric string, left separate sign DSC$K_DTYPE_NL
Numeric string, left overpunched sign DSC$K_DTYPE_NLO
Numeric string, right separate sign DSC$K_DTYPE_NR
Numeric string, right overpunched sign DSC$K_DTYPE_NRO
Numeric string, unsigned DSC$K_DTYPE_NU
Numeric string, zoned sign DSC$K_DTYPE_NZ
Octaword integer (signed) DSC$K_DTYPE_O
Octaword (unsigned) DSC$K_DTYPE_OU
Packed decimal string DSC$K_DTYPE_P
Quadword integer (signed) DSC$K_DTYPE_Q
Quadword (unsigned) DSC$K_DTYPE_QU
Character string DSC$K_DTYPE_T
Aligned bit string DSC$K_DTYPE_V
Varying character string DSC$K_DTYPE_VT
Unaligned bit string DSC$K_DTYPE_VU
Word integer (signed) DSC$K_DTYPE_W
Word (unsigned) DSC$K_DTYPE_WU
Unspecified DSC$K_DTYPE_Z
1
Procedure entry mask DSC$K_DTYPE_ZEM
1
Sequence of instruction DSC$K_DTYPE_ZI
1 VAX specific.
2 Alpha specific.

17.4.3 Access Entry


The access entry describes the way in which the called routine accesses the data
specified by the argument, or access method. The following methods of access
are most common:
• Read only. Data upon which a routine operates, or data needed by the routine
to perform its operation, must be read by the called routine. Such data is
also called input data. When an argument specifies input data, the access
entry is read only.
The term only is present to indicate that the called routine does not both read
and write (that is, modify) the input data. Thus, input data supplied by a
variable is preserved when the called routine completes execution.

17–8 Call Format to OpenVMS Routines


Call Format to OpenVMS Routines
17.4 Arguments Heading

• Write only. Data that the called routine returns to the calling program must
be written into a location where the calling program can access it. Such
data is also called output data. When an argument specifies output data, the
access entry is write only.
In this context, the term only is present to indicate that the called routine
does not read the contents of the location either before or after it writes into
the location.
• Modify. When an argument specifies data that is both read and written by
the called routine, the access entry is modify. In this case, the called routine
reads the input data, which it uses in its operation, and then overwrites the
input data with the results (the output data) of the operation. Thus, when the
called routine completes execution, the input data specified by the argument
is lost.
Following is a complete list of access methods that can appear under the access
entry in an argument description:
• Read only
• Write only
• Modify
• Function call (before return)
• JMP after unwind
• Call after stack unwind
• Call without stack unwind
For more information, see the OpenVMS Calling Standard.

17.4.4 Mechanism Entry


The way in which an argument specifies the actual data to be used by the called
routine is defined in terms of the argument passing mechanism. There are
three basic passing mechanism types:
• By value. When the argument in the argument list contains the actual data
to be used by the routine, the actual data is said to be passed to the routine
by value. In this case, the argument is the actual data.
• By reference. When the argument in the argument list contains the address
of the data to be used by the routine, the data is said to be passed by
reference. In this case, the argument is a pointer to the data.
• By descriptor. When the argument in the argument list contains the address
of a descriptor, the data is said to be passed by descriptor. A descriptor
consists of two or more longwords (depending on the type of descriptor used)
that describe the location, length, and the OpenVMS standard data type of
the data to be used by the called routine. In this case, the argument is a
pointer to a descriptor that points to the actual data.
There are several kinds of descriptors. Each one contains a value, or class,
in the fourth byte of the first longword. The class identifies the type of
descriptor it is. Each class has a symbolic code.

Call Format to OpenVMS Routines 17–9


Call Format to OpenVMS Routines
17.4 Arguments Heading

Table 17–4 lists the types of descriptors and their corresponding code names.
See the OpenVMS Calling Standard for a detailed description of each
descriptor class.

Table 17–4 Descriptor Classes of Passing Mechanisms


Passing Mechanism Descriptor Symbolic Code
By descriptor, fixed-length (scalar) DSC$K_CLASS_S
By descriptor, dynamic string DSC$K_CLASS_D
By descriptor, array DSC$K_CLASS_A
By descriptor, procedure DSC$K_CLASS_P
By descriptor, decimal string DSC$K_CLASS_SD
By descriptor, noncontiguous array DSC$K_CLASS_NCA
By descriptor, varying string DSC$K_CLASS_VS
By descriptor, varying string array DSC$K_CLASS_VSA
By descriptor, unaligned bit string DSC$K_CLASS_UBS
By descriptor, unaligned bit array DSC$K_CLASS_UBA
By descriptor, string with bounds DSC$K_CLASS_SB
By descriptor, unaligned bit string with bounds DSC$K_CLASS_UBSB

17.4.5 Explanatory Text


For each argument, one or more paragraphs of explanatory text follow the
OpenVMS usage, type, access, and mechanism entries. The first paragraph is
highly structured and always contains information in the following sequence:
1. A sentence or a sentence fragment that describes ( 1 ) the nature of the
data specified by the argument, and ( 2 ) the way in which the routine uses
this data. For example, if an argument were supplying a number, which
the routine converts to another data type, the argument description would
contain the following sentence fragment:
Integer to be converted to an F_floating point number
2. A sentence that expresses the relationship between the argument and the
data that it specifies. This relationship is the passing mechanism used to
pass the data and, for a given argument, is expressed in one of the following
ways:
a. If the passing mechanism is by value, the sentence should read as follows:
The attrib argument is a longword that contains
(or is) the bit mask specifying the attributes.
b. If the passing mechanism is by reference, the sentence should read as
follows:
The objtyp argument is the address of a longword
containing a value indicating whether the object is
a file or a device.
c. If the passing mechanism is by descriptor, the sentence should read as
follows:
The devnam argument is the address of a string
descriptor of a logical name denoting a device
name.

17–10 Call Format to OpenVMS Routines


Call Format to OpenVMS Routines
17.4 Arguments Heading

3. Additional explanatory paragraphs that appear for each argument, as needed.


For example, some arguments specify complex data consisting of many
discrete fields, each of which has a particular purpose and use. In such
cases, additional paragraphs provide detailed descriptions of each such field,
symbolic names for the fields, if any, and guidance on their use.

17.5 Condition Values Returned Heading


A condition value is a longword that has the following uses on the OpenVMS VAX
and OpenVMS Alpha systems:
• Indicates the success or failure of a called procedure
• Describes an exception condition when an exception is signaled
• Identifies system messages
• Reports program success or failure to the command level
The OpenVMS Calling Standard explains in detail the uses for the condition
value and depicts its format and contents.
The Condition Values Returned heading describes the condition values that
are returned by the routine when it completes execution without generating an
exception condition. These condition values describe the completion status of the
operation.
If a called routine generates an exception condition during execution, the
exception condition is signaled; the exception condition is then handled by a
condition handler (either user supplied or system supplied). Depending on the
nature of the exception condition and on the condition handler, the called routine
either continues normal execution or terminates abnormally.
If a called routine executes without generating an exception condition, the called
routine returns a condition value in one or two of the following ways:
• Condition Values Returned
• Condition Values Returned in an I/O Status Block
• Condition Values Returned in a Mailbox
• Condition Values Signaled
The method used to return the condition value is indicated under the Condition
Values Returned heading in the documentation of each routine. These methods
are discussed individually in the following subsections.
Under these headings, a two-column list shows the symbolic code for each
condition value the routine can return and an accompanying description. The
description explains whether the condition value indicates success or failure
and, if failure, what user action might have caused the failure and what to do to
correct it. Condition values that indicate success are listed first.
Symbolic codes for condition values are defined by the system. Though the
condition value consists of several fields, each of which can be interpreted
individually for specific information, the entire condition value itself can be
interpreted as an integer, and this integer has an equivalent symbolic code.
The three sections that follow discuss the ways in which the called routine
returns condition values.

Call Format to OpenVMS Routines 17–11


Call Format to OpenVMS Routines
17.5 Condition Values Returned Heading

17.5.1 Condition Values Returned


The possible condition values that the called routine can return in general
register R0 are listed under the Condition Values Returned heading in the
documentation. Most routines return a condition value in this way.
In the documentation of system services that complete asynchronously, both the
Condition Values Returned and Condition Values Returned in the I/O Status
Block headings are used. Under the Condition Values Returned heading, the
condition values returned by the asynchronous service refer to the success or
failure of the system service request—that is, to the status associated with the
correctness of the syntax of the call, in contrast to the final status associated
with the completion of the service operation. For asynchronous system services,
condition values describing the success or failure of the actual service operation—
that is, the final completion status—are listed under the Condition Values
Returned in the I/O Status Block heading.

17.5.2 Condition Values Returned in an I/O Status Block


The possible condition values that the called routine can return in an I/O status
block are listed under the Condition Values Returned in the I/O Status Block
heading.
The routines that return condition values in the I/O status block are the system
services that are completed asynchronously. Each of these asynchronous
system services returns to the caller as soon as the service call is queued.
This allows the continued use of the calling program during the execution of the
service operations. System services that are completed asynchronously all have
arguments that specify an I/O status block. When the system service operation is
completed, a condition value specifying the completion status of the operation is
written in the first word of this I/O status block.
Representing a condition value in a word-length field is possible for system
services because the high-order segment of all system service condition values
is 0. See cond_value in Table B–1 or Section 18.11 for the field detail of the
condition value structure.

17.5.3 Condition Values Returned in a Mailbox


The possible condition values that the called routine can return in a mailbox are
listed under the Condition Values Returned in a Mailbox heading.
Routines such as SYS$SNDOPR that return condition values in a mailbox send
information to another process to perform a task. The receiving process performs
the action and returns the status of the task to the mailbox of the sending
process.

17.5.4 Condition Values Signaled


The possible condition values that the called routine can signal (instead of
returning them in R0) are listed under the Condition Values Signaled heading.
Routines that signal condition values as a way of indicating the completion status
do so because these routines are returning actual data as the value of the routine.
As mentioned, the signaling of condition values occurs whenever a routine
generates an exception condition, regardless of how the routine returns its
completion status under normal circumstances.

17–12 Call Format to OpenVMS Routines


18
Basic Calling Standard Conventions

The OpenVMS Calling Standard defines the concepts and conventions used by
common languages to invoke routines and pass data between them. This chapter
briefly describes the following calling standard conventions:
• Register usage
• Stack usage
• Argument list
• Argument passing
• Returns
Refer to the OpenVMS Calling Standard for more detail on calling conventions
and for standards defining argument data types, descriptor formats, and
procedures for condition handling and stack unwinding.

18.1 Hardware Registers


Registers in the hardware provide the necessary temporary storage for
computation within OpenVMS software procedures. The number of registers
available and their usage vary between the Alpha and VAX systems.

18.1.1 Register Usage for OpenVMS VAX


The calling standard defines several VAX registers and their use, as listed in
Table 18–1.

Table 18–1 VAX Register Usage


Register Use
PC Program counter
SP Stack pointer
FP Current stack frame pointer
AP Argument pointer
R1 Environment value (when necessary)
R0, R1 Function return value registers

By definition, any called routine can use registers R2 through R11 for
computation and the AP register as a temporary register.

Basic Calling Standard Conventions 18–1


Basic Calling Standard Conventions
18.1 Hardware Registers

18.1.2 Register Usage for OpenVMS Alpha


On Alpha systems, there are two groups of 64-bit wide, general-purpose Alpha
hardware registers:
• Integer
• Floating point
The first 32 general-purpose registers support integer processing; the second 32
support floating-point operations.
18.1.2.1 Integer Registers
The calling standard defines the Alpha general-purpose integer registers and
their use, as listed in Table 18–2.

Table 18–2 Alpha Integer Registers


Register Usage
R0 Function value register. A standard call that returns a nonfloating-point
function must return the function result in this register. The register can be
modified by the called procedure without being saved and restored.
R1 Conventional scratch register. In a standard call, this register can be
modified by the called procedure without being saved and restored.
R2–15 Conventional saved registers. If a standard-conforming procedure modifies
one of these registers, the procedure must save and restore it.
R16–21 Argument registers. Up to six nonfloating-point items of the argument list
are passed in these registers and the registers can be modified by the called
procedure without being saved and restored.
R22–24 Conventional scratch registers. The registers can be modified by the called
procedure without being saved and restored.
R25 Argument information (AI) register. The register describes the argument
list (see Section 18.4 for a detailed description) and can be modified by the
called procedure without being saved and restored.
R26 Return address (RA) register. The return address must be passed in this
register and can be modified by the called procedure without being saved
and restored.
R27 Procedure value (PV) register. The procedure value of the procedure being
called is passed in this register and can be modified by the called procedure
without being saved and restored.
R28 Volatile scratch register. The contents of this register are always
unpredictable after any external transfer of control either to or from a
procedure.
R29 Frame pointer (FP). This register defines which procedure is the current
procedure.
R30 Stack pointer (SP). This register contains a pointer to the top (start) of the
current operating stack.
R31 ReadAsZero/Sink (RZ). Hardware defined: binary zero as a source operand,
sink (no effect) as a result operand.

18–2 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.1 Hardware Registers

18.1.2.2 Floating-Point Registers


The calling standard defines the Alpha floating-point registers and their use, as
listed in Table 18–3.

Table 18–3 Alpha Floating-Point Registers


Register Usage
F0 Floating-point function value register. In a standard call that returns a
floating-point result in a register, this register is used to return the real part
of the result. The register can be modified by the called procedure without
being saved and restored.
F1 Floating-point function value register. In a standard call that returns a
complex floating-point result in registers, this register is used to return the
imaginary part of the result. This register can be modified by the called
procedure without being saved and restored.
F2–9 Conventional saved registers. If a standard-conforming procedure modifies
one of these registers, the procedure must save and restore it.
F10–15 Conventional scratch registers. The registers can be modified by the called
procedure without being saved and restored.
F16–21 Argument registers. Up to six floating-point arguments can be passed by
value in these registers. These registers can be modified by the called
procedure without being saved and restored.
F22–30 Conventional scratch registers. The registers can be modified by the called
procedure without being saved and restored.
F31 ReadAsZero/Sink. Hardware defined: binary zero as a source operand, sink
(no effect) as a result operand.

18.2 Stack Usage for Procedures


A stack is a last-in/first-out (LIFO) temporary storage area that the system
allocates for every user process. The system keeps information about each
routine call in the current image on the call stack. Then, each time you call a
routine, the system creates a structure on the stack, defined as the stack frame.
Stack frames and call frames are synonymous. A call frame for each procedure
has a specified format containing pointers and control information necessary in
the transfer of control between procedures of a call chain. Stack frames (call
frames) of standard calling procedures differ between Alpha and VAX systems.

18.2.1 Stack Procedure Usage for VAX


Figure 18–1 shows the format of the stack frame created for the called procedure
by the CALLG or CALLS instruction. The stack frame (pointed to by SP) is in
the context of the current procedure, and call frames (pointed to by FP) are the
preserved stack frames of other active procedures in the call chain. The stack
frame (call frame) for each procedure in the chain contains the following:
• A pointer to the call frame of the previous procedure call, defined as the frame
pointer (FP).
Note that FP points at the condition handler longword at the beginning of
the previous call frame. Unless the procedure has a condition handler, this
longword contains all zeros. See the OpenVMS Calling Standard for more
information on condition handlers.
• The argument pointer (AP) of the previous routine call.

Basic Calling Standard Conventions 18–3


Basic Calling Standard Conventions
18.2 Stack Usage for Procedures

• The stored address (program count) of the point at which the routine was
called. Specifically, this address is the program count from the program
counter (PC) of the instruction following the call to the current routine.
• The contents of other general registers. Based on a register save mask
specified in the control information of the second longword, the system
restores the saved contents of the identified registers to the calling routine
when control returns to it.

Figure 18–1 Call Frame Generated by CALLG and CALLS Instructions

31 0

Condition handler (none=0) :(SP) :(FP)

SPA S 0 Register save mask Processor status word

Argument pointer (AP)

Frame pointer (FP)

Program counter (PC)

Saved register (R2)

Saved register (R11)

ZK−5249A−GE

The contents of the stack located at addresses following the call frame belong to
the calling program; they should not be read or written by the called procedure,
except as specified in the argument list. The contents of the stack located at
addresses lower than the call frame (at FP) belong to interrupt and exception
routines; they are modified continually and unpredictably.
The called procedure allocates local storage by subtracting the required number of
bytes from the stack provided on entry. This local storage is freed automatically
by the RET instruction.

18–4 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.2 Stack Usage for Procedures

18.2.1.1 Calling Sequence


At the option of the calling procedure, the called procedure is invoked using the
CALLG or CALLS instruction, as follows:
CALLG arglst, procedure
CALLS argcnt, procedure
CALLS pushes the argument count argcnt onto the stack as a longword and sets
the argument pointer, AP, to the top of the stack. The complete sequence using
CALLS follows:
push argn
.
.
.
push arg1
CALLS #n, procedure
18.2.1.2 Call Frames on Return
If the called procedure returns control to the calling procedure, control must
return to the instruction immediately following the CALLG or CALLS instruction.
Skip returns and GOTO returns are allowed only during stack unwind operations.
The called procedure returns control to the calling procedure by executing the
return instruction (RET).
Note that when a routine completes execution, the system uses the FP in the call
frame of the current procedure to locate the frame of the previous procedure. The
system then removes the stack frame of the current procedure from the stack.

18.2.2 Stack Procedure Usage for Alpha


On Alpha systems, when a standard procedure is called, the language compiler
creates a stack frame for that procedure. The stack format of a stack frame
procedure consists of a fixed part (the size of which is known at compile time) and
an optional variable part. There are two basic types of stack frames:
• Fixed size
• Variable size
18.2.2.1 Fixed-Size Stack Frame
Figure 18–2 illustrates the format of the stack frame for a procedure with a fixed
amount of stack. The SP register is the stack base pointer for a fixed-size stack.
In this case, R29 (FP) typically contains the address of the procedure descriptor
for the current procedure.
The optional parts of the stack frame are created only as required by the
particular procedure. As shown in Figure 18–2, the field names within brackets
are optional fields. The fixed temporary locations are optional sections of any
stack frame that contain language-specific locations required by the procedure
context of some high-level languages.
The register save area is a set of consecutive quadwords in which registers
that are saved and restored by the current procedure are stored. The register
save area (RSA) begins at the location pointed to by the RSA offset. The contents
of the return address register (R26) are always saved in the first register field
(SAVED_RETURN) of the register save area.

Basic Calling Standard Conventions 18–5


Basic Calling Standard Conventions
18.2 Stack Usage for Procedures

Use of the arguments passed in memory appending the end of the frame is
described in Section 18.4. For more detail concerning the fixed-size stack frame,
see the OpenVMS Calling Standard.

Figure 18–2 Fixed-Size Stack Frame Format

octaword aligned
:0 (from SP)

[Fixed temporary locations]

:RSA_OFFSET
(from SP)

Register save area

[Fixed temporary locations]

[Argument home area]

:SIZE (from SP)

[Arguments passed in memory]

ZK−4650A−GE

18.2.2.2 Variable-Size Stack Frame


Figure 18–3 illustrates the format of the stack frame for procedures with a
varying amount of stack when PDSC$V_BASE_REG_IS_FP is 1. In this case,
R29 (FP) contains the address that points to the base of the stack frame on the
stack. This frame-base quadword location contains the address of the current
procedure’s descriptor.
The optional parts of the stack frame are created as required by the particular
procedure. As shown in Figure 18–3, field names within brackets are optional
fields. The fixed temporary locations are optional sections of any stack frame
that contain language-specific locations required by the procedure context of some
high-level languages.
A compiler can use the stack temporary area pointed to by the SP base register
for fixed local variables, such as constant-sized data items and program state,
as well as for dynamically sized local variables. The stack temporary area may
also be used for dynamically sized items with a limited lifetime, for example, a
dynamically sized function result or string concatenation that cannot be directly

18–6 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.2 Stack Usage for Procedures

stored in a target variable. When a procedure uses this area, the compiler
must keep track of its base and reset SP to the base to reclaim storage used by
temporaries.
The register save area is a set of consecutive quadwords in which registers
saved and restored by the current procedure are stored. The register save area
(RSA) begins at the location pointed to by the offset PDSC$W_RSA_OFFSET. The
contents of the return address register (R26) is always saved in the first register
field (SAVED_RETURN) of the register save area.
Use of the arguments passed in memory appending the end of the frame is
described in Section 18.4. For more detail concerning the variable-size stack
frame, see the OpenVMS Calling Standard.

Basic Calling Standard Conventions 18–7


Basic Calling Standard Conventions
18.2 Stack Usage for Procedures

Figure 18–3 Variable-Size Stack Frame Format

octaword aligned
:0 (from SP)

[Stack temporary area]

:0 (from FP)
Procedure descriptor address

:8 (from FP)

[Fixed temporary locations]

:RSA_OFFSET
(from FP)

Register save area

[Fixed temporary locations]

[Argument home area]

:SIZE (from FP)


[Arguments passed in memory]

ZK−4651A−GE

18.3 Procedure Representation


A procedure value is an address value that represents a procedure.
On Alpha systems, the procedure value in R27 is the address of the procedure
descriptor that describes that procedure. So any OpenVMS Alpha procedure can
be invoked by calling the stored address at offset 8 from the procedure descriptor
(PDSC) starting address (procedure value).
On VAX systems, the procedure value is the address of the procedure entry mask
that begins the actual code sequence of the procedure.

18–8 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.4 Argument List

18.4 Argument List


The calling standard defines a data structure called the argument list. An
argument list is a sequence of locations in memory that represents a routine
parameter list and possibly includes a function value. You use an argument list
to pass information to a routine and receive results.
On VAX systems, the first longword in an argument list (see Figure 18–4) stores
the number of arguments (the argument count, n) as an unsigned integer value.
The maximum argument count is 255. The remaining 24 bits of the first longword
are reserved for use by Compaq and must be 0.
Both integer and floating-point values can be an argument passed in the
argument list. Note that a 64-bit floating-point argument counts as 2 longword
arguments in the list.

Figure 18–4 Structure of a VAX Argument List

31 0
Argument :arglst
Must be 0 count (n)

arg1

arg2

argn

ZK−4648A−GE

On Alpha systems, arguments are quadwords, and the calling program passes
arguments in an argument item sequence. Each quadword in the sequence
specifies a single argument. The argument item sequence is formed using R16–21
or F16–21 (a register for each argument). The argument item sequence can have
a mix of integer and floating-point items that use both register types but must
not repeat the same number. For example, an argument list might use R16,
R17, F18, and R19. If there are more than six arguments, the argument items
overflow to the end of the stack, as shown in Figure 18–5.
The calling procedure must pass to the called procedure information about the
argument list. For high-level languages, this is performed by the language
processor. In the argument information (AI) register (R25), the quadword format
is the structure shown in Figure 18–6. The AI register contains the argument
count in the first byte. Table 18–4 describes the argument information fields in
detail.

Basic Calling Standard Conventions 18–9


Basic Calling Standard Conventions
18.4 Argument List

Figure 18–5 Alpha Argument List Format

Argument Item Sequence

Alpha Registers

R16 (arg1)

R17 (arg2)

R18 (arg3)

R19 (arg4)

End of stack frame


R20 (arg5)

R21 (arg6) arg7

arg8

R25 (AI) Arg Count


argn

Arguments passed in
memory for more than
R30 (SP) six arguments

F16 (arg1)

F17 (arg2)

F18 (arg3)

F19 (arg4)

F20 (arg5)

F21 (arg6)

ZK−5273A−GE

Figure 18–6 Argument Information (AI) Register (R25) Format

64 25 7 0

Must be 0 ARG_REG_INFO

ARG_COUNT
ZK−6510A−GE

18–10 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.4 Argument List

Table 18–4 Contents of the Argument Information (AI) Register (Alpha only)
Field Name Contents
AI$B_ARG_COUNT Unsigned byte <7:0> that specifies the number of 64-bit argument items in the
argument list (known as the argument count).
AI$V_ARG_REG_INFO An 18-bit vector field <25:8> divided into 6 groups of 3 bits that correspond to
the 6 arguments passed in registers. These groups describe how each of the first
six arguments are passed in registers with the first group <10:8> describing the
first argument. The encoding for each group for the argument register usage
follows:

Value Name Meaning


0 AI$K_AR_I64 64-bit or 32-bit sign-extended to 64-bit argument
passed in an integer register or
Argument is not present.
1 AI$K_AR_FF VAX F_floating argument passed in a floating
register.
2 AI$K_AR_FD VAX D_floating argument passed in a floating
register.
3 AI$K_AR_FG VAX G_floating argument passed in a floating
register.
4 AI$K_AR_FS IEEE S_floating argument passed in a floating
register.
5 AI$K_AR_FT IEEE T_floating argument passed in a floating
register.
6, 7 Reserved.

Bits <63:26> Reserved and must be 0.

18.5 Argument Passing Mechanisms


Each high-level language supported by OpenVMS provides a mechanism for
passing arguments to a procedure. The specifics of the mechanism and the
terminology used, however, vary from one language to another. For specific
information, refer to the appropriate high-level language user’s guide.
OpenVMS system routines are external procedures that accept arguments. The
argument list contains the parameters that are passed to the routine. Depending
on the passing mechanisms for these parameters, the forms of the arguments
contained in the argument list vary. As shown in Figures 18–7 and 18–8,
argument entries labeled arg1 through argn are the actual parameters, which
can be any of the following addresses or value:
• An uninterpreted 32-bit value on VAX or 64-bit value on Alpha systems is
passed by value.
• An address of a data value is passed by reference.
• An address of a descriptor that contains a pointer to a data value is passed by
descriptor (for example, a string might be the data value).

Basic Calling Standard Conventions 18–11


Basic Calling Standard Conventions
18.5 Argument Passing Mechanisms

Figure 18–7 Alpha Procedure Argument-Passing Mechanisms

Argument Passed by Value


Argument Item Sequence

R16/F16 (arg1 actual value)

R17/F17 (arg2 actual value)

R18/F18 (arg3 actual value)

argn actual value

Argument Passed by Reference


Argument Item Sequence

R16/F16 arg1 pointer

R17/F17 arg2 pointer


Data

R18/F18 arg3 pointer Actual value

argn pointer

Argument Passed by Descriptor


Argument Item Sequence

R16/F16 arg1 pointer to DSC

R17/F17 arg2 pointer to DSC Descriptor

R18/F18 arg3 pointer to DSC Class D Type Length

Pointer

Data
argn pointer to DSC
D C B A

H G F E

ZK−5248A−GE

OpenVMS programming reference manuals provide a description of each


OpenVMS system routine that indicates how each argument is to be passed.
Phrases such as ‘‘an address’’ and ‘‘address of a character string descriptor’’
identify reference and descriptor arguments, respectively. Terms like ‘‘Boolean
value,’’ ‘‘number,’’ ‘‘value,’’ and ‘‘mask’’ indicate an argument that is passed by
value.

18–12 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.5 Argument Passing Mechanisms

Figure 18–8 VAX Procedure Argument-Passing Mechanisms

Argument Passed by Value


Argument List

n :(AP)

arg1

arg2

Actual value

argn

Argument Passed by Reference

n :(AP)

arg1

arg2

Pointer to
actual value Data

Actual Value

argn

Data (bytes)
Argument Passed by Descriptor
A

n B
:(AP)

arg1 C

arg2 D
Descriptor Length
Pointer to Class D Type Length E
descriptor
Pointer F

argn G

H
Note: arg1, arg2, and argn can be passed by value,
by reference, or by descriptor in any of these examples.

:(AP) = Argument pointer

n = Number of arguments
ZK−1962−GE

18.5.1 Passing Arguments by Value


When your program passes an argument using the by value mechanism, the
argument list entry contains either the actual uninterpreted 32-bit VAX value

Basic Calling Standard Conventions 18–13


Basic Calling Standard Conventions
18.5 Argument Passing Mechanisms

or a 64-bit Alpha value (zero- or sign-extended) of the argument. For example,


to pass the constant 100 by value, the calling program puts 100 directly in the
argument list or sequence. For more information about passing 64-bit Alpha
values, refer to Chapter 11.
All high-level languages (except C) require you to specify the by-value mechanism
explicitly when you call a procedure that accepts an argument by value. For
example, FORTRAN uses the %VAL built-in function, while COBOL uses the BY
VALUE qualifier on the CALL [USING] statement.
A FORTRAN program calls a procedure using the by-value mechanism as follows:
INCLUDE ’($SSDEF)’
CALL LIB$STOP (%VAL(SS$_INTOVF))
A BLISS program calls this procedure as follows:
LIB$SIGNAL (SS$_INTOVF)
The equivalent VAX MACRO code is as follows:
PUSHL #SS$_INTOVF ; Push longword by value
CALLS #1,G^LIB$SIGNAL ; Call LIB$SIGNAL
A C language program calls a procedure using the by-value mechanism as follows:
#include <starlet.h> /* Declare the function*/
.
.
enum cluster0
{
completion, breakdown, beginning
} event;
int status;
event = completion;
.
.
status = sys$setef(event); /* Set event flag */

18.5.2 Passing Arguments by Reference


When your program passes arguments using the by reference mechanism, the
argument list entry contains the address of the location that contains the value
of the argument. For example, if variable x is allocated at location 1000, the
argument list entry will contain 1000, the address of the value of x.
On Alpha processors, the address is sign-extended from 32 bits to 64 bits.
Most languages (but not C) pass scalar data by reference by default. Therefore, if
you simply specify x in the CALL statement or function invocation, the language
automatically passes the value stored at the location allocated to x to the
OpenVMS system routine.
A VAX BLISS program calls a procedure using the by-reference mechanism as
follows:
LIB$FLT_UNDER (%REF(1))

18–14 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.5 Argument Passing Mechanisms

The equivalent VAX MACRO code is as follows:


ONE: .LONG 1 ; Longword value 1
.
.
.
PUSHAL ONE ; Push address of longword
CALLS #1,G^LIB$FLT_UNDER ; Call LIB$FLT_UNDER
A C language program calls a procedure using the by-reference mechanism as
follows:

/* This program shows how to call system service SYS$READEF. */


#include <ssdef.h>
#include <stdio.h>
#include <starlet.h> /* Declare the function */
main(void)
{
/* Longword that receives the status *
* of the event flag cluster */
unsigned cluster_status;
int return_status; /* Status: SYS$READEF */
/* Argument values for SYS$READEF */
enum cluster0
{
completion, breakdown, beginning
} event;
.
.
.
event = completion; /* Event flag in cluster 0 */
/* Obtain status of cluster 0. *
* Pass value of event and *
* address of cluster_status. */
return_status = SYS$READEF(event, &cluster_status);
/* Check for successful call */
if (return_status != SS$WASCLR && return_status != SS$WASSSET)
{
/* Handle the error here. */
.
.
.
}
else
{
/* Check bits of interest in cluster_status here. */
.
.
.
}
}

Basic Calling Standard Conventions 18–15


Basic Calling Standard Conventions
18.5 Argument Passing Mechanisms

18.5.3 Passing Arguments by Descriptor


When a procedure specifies that an argument is passed by descriptor, the
argument list entry must contain the address of a descriptor for the argument.
For more information about OpenVMS Alpha 64-bit descriptors, refer to Chapter
11.
On Alpha processors, the address is sign-extended from 32 bits to 64 bits.
This mechanism is used to pass more complicated data. For both Alpha and VAX
systems, a descriptor includes at least the following fields:

Symbol Description
DSC$W_LENGTH Length of data (or DSC$W_MAXSTRLEN, maximum length, for
varying strings)
DSC$B_DTYPE Data type
DSC$B_CLASS Descriptor class code
DSC$A_POINTER Address at which the data begins

The OpenVMS Calling Standard describes these fields in greater detail.


OpenVMS high-level languages include extensions for passing arguments by
descriptor. When you specify by descriptor in these languages, the compiler
creates the descriptor, defines its fields, and passes the address of the descriptor
to the OpenVMS system routine. In some languages, by descriptor is the default
passing mechanism for certain types of arguments, such as character strings. For
example, the default mechanism for passing strings in BASIC is by descriptor.
100 COMMON STRING GREETING = 30
200 CALL LIB$PUT_SCREEN(GREETING)
The default mechanism for passing strings in COBOL, however, is by reference.
Therefore, when passing a string argument to an OpenVMS system routine from
a COBOL program, you must specify BY DESCRIPTOR for the string argument
in the CALL statement.
CALL LIB$PUT_OUTPUT USING BY DESCRIPTOR GREETING
In VAX MACRO or BLISS, you must define the descriptor’s fields explicitly
and push its address onto the stack. Following is the VAX MACRO code that
corresponds to the previous examples.

MSGDSC: .WORD LEN ; DESCRIPTOR: DSC$W_LENGTH


.BYTE DSC$K_DTYPE_T ; DSC$B_DTYPE
.BYTE DSC$K_CLASS_S ; DSC$B_CLASS
.ADDRESS MSG ; DSC$A_POINTER
MSG: .ASCII/Hello/ ; String itself
LEN = .-MSG ; Define the length of the string
.ENTRY EX1,^M<>
PUSHAQ MSGDSC ; Push address of descriptor
CALLS #1,G^LIB$PUT_OUTPUT ; Output the string
RET
.END EX1

18–16 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.5 Argument Passing Mechanisms

The equivalent BLISS code looks like this:


MODULE BLISS1 (MAIN = BLISS1, ! Example of calling LIB$PUT_OUTPUT
IDENT = ’1-001’,
ADDRESSING_MODE(EXTERNAL = GENERAL)) =
BEGIN
EXTERNAL ROUTINE
LIB$STOP, ! Stop execution via signaling
LIB$PUT_OUTPUT; ! Put a line to SYS$OUTPUT
FORWARD ROUTINE
BLISS1 : NOVALUE;
LIBRARY ’SYS$LIBRARY:STARLET.L32’;
ROUTINE BLISS1 ! Routine
: NOVALUE =
BEGIN
!+
! Allocate the necessary local storage.
!-
LOCAL
STATUS, ! Return status
MSG_DESC : BLOCK [8, BYTE]; ! Message descriptor
BIND
MSG = UPLIT(’HELLO’);
!+
! Initialize the string descriptor.
!-
MSG_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
MSG_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
MSG_DESC [DSC$W_LENGTH] = 5;
MSG_DESC [DSC$A_POINTER] = MSG;
!+
! Put out the string. Test the return status.
! If it is not a success, then signal the RMS error.
!-
STATUS = LIB$PUT_OUTPUT(MSG_DESC);
IF NOT .STATUS THEN LIB$STOP(.STATUS);
END; ! End of routine BLISS1
END ! End of module BLISS1
ELUDOM
A C language program calls a procedure using the by-descriptor mechanism as
follows:
/* This program shows a call to system service SYS$SETPRN. */
#include <ssdef.h>
#include <stdio.h>
/* Define structures for descriptors */
#include <descrip.h>
#include starlet.h /* Declare the function */
int main(void)
{
int ret; /* Define return status of SYS$SETPRN */
struct dsc$descriptor_s name_desc; /* Name the descriptor */
char *name = "NEWPROC"; /* Define new process name */
.
.
.
name_desc.dsc$w_length = strlen(name); /* Length of name without *
* null terminator */

Basic Calling Standard Conventions 18–17


Basic Calling Standard Conventions
18.5 Argument Passing Mechanisms

name_desc.dsc$a_pointer = name; /* Put address of shortened string *


* in descriptor */
name_desc.dsc$b_class = DSC$K_CLASS_S; /* String descriptor class */
name_desc.dsc$b_dtype = DSC$K_DTYPE_T; /* Data type: ASCII string */
.
.
.
ret = sys$setprn(&name_desc);
if (ret != SS$_NORMAL) /* Test return status */
fprintf(stderr, "Failed to set process name\n"),
exit(ret);
.
.
.
}

18.6 Passing Scalars as Arguments


When you are passing an input scalar value to an OpenVMS system routine,
you usually pass it either by reference or by value. You usually pass output
scalar arguments by reference to OpenVMS system routines. An output scalar
argument is the address of a location where some scalar output of the routine will
be stored.

18.7 Passing Arrays as Arguments


Arrays are passed to OpenVMS system routines by reference or by descriptor.
Sometimes the routine knows the length and dimensions of the array to be
received, as in the case of the table passed to LIB$CRC_TABLE. Arrays such as
this are normally passed by reference.
In other cases, the routine actually analyzes and operates on the input array.
The routine does not necessarily know the length or dimensions of such an input
array, so a descriptor is necessary to provide the information the routine needs to
describe the array accurately.

18.8 Passing Strings as Arguments


Strings are passed by descriptor to OpenVMS system routines. Table 18–5 lists
the string-passing descriptors recognized by a system routine.

Table 18–5 String-Passing Descriptors


Descriptor Function Descriptor Class Code Numeric Value
Unspecified DSC$K_CLASS_Z 0
Fixed length (string/scalar) DSC$K_CLASS_S 1
Dynamic DSC$K_CLASS_D 2
Array DSC$K_CLASS_A 4
Scaled decimal DSC$K_CLASS_SD 9
Noncontiguous array DSC$K_CLASS_NCA 10
Varying length DSC$K_CLASS_VS 11

18–18 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.8 Passing Strings as Arguments

An OpenVMS system routine writes strings according to the following types of


semantics:
• Fixed length — Characterized by an address and a constant length
• Varying length — Characterized by an address, a current length, and a
maximum length
• Dynamic — Characterized by a current address and a current length

18.9 Combinations of Descriptor Class and Data Type


Some combinations of descriptor class and data type are not permitted, either
because they are not meaningful or because the calling standard does not
recognize them. Possibly, the same function can be performed with more than
one combination. This section describes the restrictions on the combinations
of descriptor classes and data types. These restrictions help to keep procedure
interfaces simple by allowing a procedure to accept a limited set of argument
formats without sacrificing functional flexibility.
The tables in Figures 18–9, 18–10, and 18–11 show all possible combinations of
descriptor classes and data types. For example, Figure 18–9 shows that your
program can pass an argument to an OpenVMS system routine whose descriptor
class is DSC$K_CLASS_A (array descriptor) and whose data type is unsigned
byte (DSC$K_DTYPE_BU). The calling standard does not permit your program to
pass an argument whose descriptor class is DSC$K_CLASS_D (dynamic string)
and whose data type is unsigned byte.
A descriptor with data type DSC$K_DTYPE_DSC (24) points to a descriptor that
has class DSC$K_CLASS_D (2) and data type DSC$K_DTYPE_T (14). All other
class and data type combinations in the target descriptor are reserved for future
definition in the standard.
The scale factor for DSC$K_CLASS_SD is always a decimal data type. It does
not vary with the data type of the data described by the descriptor.
For DSC$K_CLASS_UBS and DSC$K_CLASS_UBA, the length field specifies the
length of the data field in bits. For example, if the data type is unsigned word
(DSC$K_DTYPE_WU), DSC$W_LENGTH equals 16.

Basic Calling Standard Conventions 18–19


Basic Calling Standard Conventions
18.9 Combinations of Descriptor Class and Data Type

Figure 18–9 Atomic Data Types and Descriptor Classes

DSC$K_CLASS
_S _D _V _A _P _SD _NCA _VS _VSA _UBS _UBA _BFA
Data Type Value =1 =2 =3 =4 =5 =9 = 10 = 11 = 12 = 13 = 14 = 191
DSC$K_DTYPE_Z = 0 Yes − − Yes − − Yes − − Yes Yes −
DSC$K_DTYPE_BU = 2 Yes − − Yes Yes − Yes − − Yes Yes −
DSC$K_DTYPE_WU = 3 Yes − − Yes − − Yes − − Yes Yes −
DSC$K_DTYPE_LU = 4 Yes − − Yes − − Yes − − Yes Yes −
DSC$K_DTYPE_QU = 5 Yes − − Yes − − Yes − − − − −
DSC$K_DTYPE_OU = 25 Yes − − Yes − − Yes − − − − −
DSC$K_DTYPE_B = 6 Yes − − Yes Yes Yes Yes − − Yes Yes −
DSC$K_DTYPE_W = 7 Yes − − Yes Yes Yes Yes − − Yes Yes Yes
DSC$K_DTYPE_L = 8 Yes − − Yes Yes Yes Yes − − Yes Yes Yes
DSC$K_DTYPE_Q = 9 Yes − − Yes − Yes Yes − − − − −
DSC$K_DTYPE_O = 26 Yes − − Yes − Yes Yes − − − − −
DSC$K_DTYPE_F = 10 Yes − − Yes Yes Yes Yes − − Yes Yes Yes
DSC$K_DTYPE_D = 11 Yes − − Yes Yes Yes Yes − − − − Yes
DSC$K_DTYPE_G = 27 Yes − − Yes Yes Yes Yes − − − − −
DSC$K_DTYPE_H = 28 Yes − − Yes Yes Yes Yes − − − − −
DSC$K_DTYPE_FC = 12 Yes − − Yes Yes − Yes − − − − −
DSC$K_DTYPE_DC = 13 Yes − − Yes Yes − Yes − − − − −
DSC$K_DTYPE_GC = 29 Yes − − Yes Yes − Yes − − − − −
DSC$K_DTYPE_HC = 30 − − − − − − − − − − − −
DSC$K_DTYPE_FS = 52 Yes − − Yes Yes Yes Yes − − Yes Yes Yes
DSC$K_DTYPE_FT = 53 Yes − − Yes Yes Yes Yes − − − − −
DSC$K_DTYPE_FSC = 54 Yes − − Yes Yes − Yes − − − − −
DSC$K_DTYPE_FTC = 55 Yes − − Yes Yes − Yes − − − − −
DSC$K_DTYPE_FX = 57 Yes − − Yes Yes − Yes − − − − −
DSC$K_DTYPE_FXC = 58 Yes − − Yes Yes − Yes − − − − −

Yes The calling standard allows this combination of class and data type.

− The calling standard forbids the use of this combination of class and data type.
Higher−level languages and their run−time support must conform to this restriction.

= VAX specific
= Alpha specific

ZK−4267−GE

18–20 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.9 Combinations of Descriptor Class and Data Type

Figure 18–10 String Data Types and Descriptor Classes

DSC$K_CLASS
_S _D _V _A _P _SD _NCA _VS _VSA _UBS _UBA _BFA
Data Type Value =1 =2 =3 =4 =5 =9 = 10 = 11 = 12 = 13 = 14 = 191
DSC$K_DTYPE_V = 1 Yes − − Yes − − Yes − − Yes Yes −
DSC$K_DTYPE_T = 14 Yes Yes − Yes Yes Yes Yes Yes Yes Yes Yes Yes
DSC$K_DTYPE_NU = 15 Yes − − − − Yes Yes − − − − −
DSC$K_DTYPE_NL = 16 Yes − − − − Yes Yes − − − − −
DSC$K_DTYPE_NLO = 17 Yes − − − − Yes Yes − − − − −
DSC$K_DTYPE_NR = 18 Yes − − − − Yes Yes − − − − −
DSC$K_DTYPE_NLR = 19 Yes − − − − Yes Yes − − − − −
DSC$K_DTYPE_NZ = 20 Yes − − − − Yes Yes − − − − −
DSC$K_DTYPE_P = 21 Yes − − − − Yes Yes − − − − −
DSC$K_DTYPE_VT = 37 − − − − − − − Yes Yes − − −
DSC$K_DTYPE_VU = 34 * * * * * * * * * * * *

Yes The calling standard allows this combination of class and data type.

* No valid interpretation exists for this combination.

− The calling standard forbids the use of this combination of class and data type.
Higher−level languages and their run−time support must conform to this restriction.

ZK−4266−GE

Figure 18–11 Miscellaneous Data Types and Descriptor Classes

DSC$K_CLASS
_S _D _V _A _P _SD _NCA _VS _VSA _UBS _UBA _BFA
Data Type Value =1 =2 =3 =4 =5 =9 = 10 = 11 = 12 = 13 = 14 = 191
DSC$K_DTYPE_ZI = 22 Yes − − − − * − − − − − −
DSC$K_DTYPE_ZEM = 23 Yes − − − − * − − − − − −
DSC$K_DTYPE_DSC = 3 − − − Yes − * Yes − − − − −
DSC$K_DTYPE_BPV = 32 Yes − − − − * Yes − − − − −
DSC$K_DTYPE_BLV = 33 Yes − − − − * Yes − − − − −

Yes The calling standard allows this combination of class and data type.

* No valid interpretation exists for this combination.

− The calling standard forbids the use of this combination of class and data type.
Higher−level languages and their run−time support must conform to this restriction.

ZK−4265−GE

Basic Calling Standard Conventions 18–21


Basic Calling Standard Conventions
18.10 Return of the Function Value

18.10 Return of the Function Value


A function is a routine that returns a single value to the calling routine. The
function value represents the value of the expression in the return statement.
As specified by the calling standard, a function value may be returned as an
actual value in R0.
On VAX systems, if the actual function value returned is greater than 32 bits,
then both R0 and R1 should be used.
On Alpha systems, if the actual function returned is a floating-point value, the
floating-point value is returned either in F0 or in both F0 and F1.
A standard function must return its function value by one of the following
mechanisms:
• Immediate value
• Reference
• Descriptor
These mechanisms are the standard return convention because they support
the language-independent data types. For information about condition values
returned in R0, see Section 18.11.

18.11 Return of the Condition Value


An OpenVMS system routine can indicate success or failure to the calling
program by returning a condition value. In addition, an error condition to the
calling program can return as a condition value in R0 or by error signaling.
A condition value in R0, also called a return status or completion code, is
either a success (bit 0 = 1) value or an error condition (bit 0 = 0) value. In an
error condition value, the low-order 3 bits specify the severity of the error (see
Figure 18–12). Bits <27:16> contain the facility number, and bits <15:3> indicate
the particular condition. Bits <31:28> are the control field. When the called
procedure returns a condition value, the calling program can test R0 and choose
a recovery path. A general guideline to follow when testing for success or failure
is that all success codes have odd values and all error codes have even values.

18–22 Basic Calling Standard Conventions


Basic Calling Standard Conventions
18.11 Return of the Condition Value

Figure 18–12 Condition Value Format

31 28 27 3 2 0

Control Condition identification Severity

2 1 0

*S

27 16 15 3

Facility number Message number

*S = Success
ZK−1795−GE

When the completion code is signaled, the calling program must establish
a handler to get control and take appropriate action. (See the OpenVMS
Programming Concepts Manual or the OpenVMS Calling Standard for a
description of signaling and condition handling and for more information about
the condition value.)

Basic Calling Standard Conventions 18–23


19
Calling Run-Time Library Routines

The OpenVMS Run-Time Library is a set of language-independent routines that


establish a common run-time environment for user programs. The procedures
ensure correct operation of complex language features and help enforce consistent
operations on data across languages.
The OpenVMS Calling Standard describes the mechanisms used by OpenVMS
languages for invoking routines and passing data between them. In effect, this
standard describes the interface between your program and the run-time library
routines that your program calls. This chapter describes the basic methods for
coding calls to run-time library routines from an OpenVMS common language.

19.1 Overview
When you call a run-time library routine from your program, you must furnish
whatever arguments the routine requires. When the routine completes execution,
in most cases it returns control to your program. If the routine returns a status
code, your program should check the value of the code to determine whether or
not the routine completed successfully. If the return status indicates an error,
you may want to change the flow of execution of your program to handle the error
before returning control to your program.
When you log in, the operating system creates a process that exists until you log
out. When you run a program, the system activates an executable image in your
process. This image consists of a set of user procedures.
From the run-time library’s point of view, user procedures are procedures that
exist outside the run-time library and that can call run-time library routines.
When you write a program that calls a run-time library routine, the run-time
library views your program as a user procedure. User procedures also can call
other user procedures that are either supplied by Compaq or written by you.
Because an OpenVMS native-mode language compiler program exists outside
the run-time library, compiler-generated programs that call any run-time library
routine are also defined as a set of user procedures.
The main program, or main procedure, is the first user procedure that the
system calls after calling a number of initialization procedures. A user program
consists of the main program and all of the other user procedures that it calls.
Figure 19–1 shows the calling relationships among a main program, other user
procedures, library routines, and the operating system. In this figure, Call
indicates that the calling procedures requested some information or action;
Return indicates that the called procedure returned the information to the calling
procedure or performed the action.

Calling Run-Time Library Routines 19–1


Calling Run-Time Library Routines
19.1 Overview

Figure 19–1 Calling the Run-Time Library

Main Program User Operating


(User Procedure) Procedure System

Call

Return

Library
Procedure

RTL Call Call

Return Return

Service Call

Return

ZK−4262−GE

Although library routines can always call either other library routines or the
operating system, they can call user procedures only in the following cases:
• When a user procedure establishes its own condition handler. For example,
LIB$SIGNAL operates by searching for and calling user procedures that have
been established as condition handlers (see the OpenVMS RTL Library (LIB$)
Manual for more information).
• When a user procedure passes to a routine the address of another procedure
that the library will call later. For example, when your program calls
LIB$SHOW_TIMER, you can pass the address of an action routine that
LIB$SHOW_TIMER will call to process timing statistics.

19–2 Calling Run-Time Library Routines


Calling Run-Time Library Routines
19.2 Call Instructions

19.2 Call Instructions


Each run-time library routine requires a specific calling sequence. This calling
sequence indicates the elements that you must include when calling the routine,
and the order of those elements. The form of a calling sequence first specifies
the type of call being made. A library routine can be invoked either by a CALL
instruction or possibly by a JSB instruction (for VAX systems only) as follows:
• CALL — Call procedure from a high-level language
• CALLS — Call procedure with stack argument list instruction (VAX MACRO)
• CALLG — Call procedure with general argument list instruction
(VAX MACRO)
• JSB — Jump to subroutine instruction (for VAX systems only)
• JSR — Jump to subroutine instruction (MACRO-64)
On VAX systems, the following restrictions apply to the different types of calls:
• High-level languages do not differentiate between CALLS and CALLG. They
use a CALL statement or a function reference to invoke a run-time library
routine.
• VAX MACRO does not differentiate between functions and subroutines in its
CALLS and CALLG instructions.
• Only VAX MACRO and BLISS programs on VAX systems can explicitly access
the JSB entry points that are provided for some routines in the run-time
library. You cannot write a program to access the JSB entry points directly
from a high-level language.

19.2.1 Facility Prefix and Routine Name


Each routine is identified by a unique entry point name consisting of the facility
prefix (for example, MTH$) and the procedure name (for example, MTH$SIN).
Run-time library entry points follow the OpenVMS conventions for naming global
symbols. A global entry point takes the following general form:
fac$symbol
The elements that make up this format represent the following:
fac A 2- or 3-character facility name
symbol A 1- to 27-character symbol
The facility names are maintained in a systemwide Compaq registry. A unique,
12-bit facility number is assigned to each facility name for use in (1) condition
value symbols, and (2) condition values in procedure return status codes, signaled
conditions, and messages. The high-order bit of this number is 0 for facilities
assigned by Compaq and 1 for those assigned by Application Project Services
(APS) and customers. For further information, refer to the OpenVMS Calling
Standard.
The run-time library facility names are as follows:
CVT$ Convert routines
DTK$ DECtalk routines
LIB$ Library routines

Calling Run-Time Library Routines 19–3


Calling Run-Time Library Routines
19.2 Call Instructions

MTH$ Mathematics routines


OTS$ General-purpose routines
PPL$ Parallel processing routines
SMG$ Screen management routines
STR$ String-handling routines

19.2.2 The RTL Call Entry


Arguments passed to a routine must be listed in your call entry in the order
shown in the format section of the routine description. Each argument has four
characteristics: OpenVMS usage, data type, access type, and passing mechanism.
These characteristics are described in Chapter 17.
Some arguments are optional. Optional arguments are indicated by brackets
in the routine descriptions. When your program invokes a run-time library
routine using a CALL entry point, you can omit optional arguments at the end
of the argument list. If the optional argument is not the last argument in the
list, you must either pass a zero by value or use a comma to indicate the place
of the omitted argument. Some languages, such as C, require that you pass
zero by value for trailing optional arguments. See your language processor
documentation for further information.
On VAX systems, the calling program passes an argument list of longwords to a
called routine; each longword in the argument list specifies a single argument.
Note that a 64-bit floating-point argument would count as 2 longword arguments
in the list.
On Alpha systems, the calling program passes arguments in an argument item
sequence; each quadword in the sequence specifies a single argument item. Note
that the argument item sequence is formed using R16–21 or F16–21 (a register
for each argument). The argument item sequence can have a mix of integer and
floating-point items that use both register types but must not repeat the same
number.
In the Alpha and VAX environments, the called routine interprets each argument
using one of three standard passing mechanisms: by value, by reference, or by
descriptor. For more information on arguments, see Sections 18.4 and 18.5.
Optional arguments apply only to the CALL entry points. For example, the call
format for a procedure with two optional arguments is as follows:
LIB$GET_INPUT get-str [,prompt-str] [,out-len]
A FORTRAN program could include any one of the following calls to this
procedure:
INTEGER*4 STAT
.
.
.
STAT = LIB$GET_INPUT (GET_STR,PROMPT,LENGTH)
STAT = LIB$GET_INPUT (GET_STR,PROMPT)
STAT = LIB$GET_INPUT (GET_STR,PROMPT,)
STAT = LIB$GET_INPUT (GET_STR,,LENGTH)
STAT = LIB$GET_INPUT (GET_STR)
STAT = LIB$GET_INPUT (GET_STR,)

19–4 Calling Run-Time Library Routines


Calling Run-Time Library Routines
19.2 Call Instructions

STAT = LIB$GET_INPUT (GET_STR,%VAL(0))


The following examples illustrate the standard mechanism for calling an external
procedure, subroutine, or function in most high-level languages.
BASIC
CALL LIB$MOVTC(SRC, FILL, TABLE, DEST)
STATUS = LIB$GET_INPUT(STRING, ’NAME:’)
BLISS
LOCAL
MSG_DESC : BLOCK [8,BYTE];
MSG_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
MSG_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
MSG_DESC [DSC$W_LENGTH] = 5;
MSG_DESC [DSC$A_POINTER] = MSG;
STATUS = LIB$PUT_OUTPUT(MSG_DESC);
C
#include <lib$routines.h>
#include <descrip.h>
$DESCRIPTOR(name, "Name:");
struct dsc$descriptor_s string:
.
.
.
status = lib$get_input(&string, &name);
COBOL
CALL LIB$MOVTC USING BY DESCRIPTOR
SRC,
FILL,
TABLE,
DEST,
GIVING RET-STATUS.
FORTRAN
CALL LIB$MOVTC(SRC, FILL, TABLE, DEST)
STATUS = LIB$GET_INPUT(STRING, ’NAME:’)
Pascal
RET_STATUS := LIB$MOVTC (SRC, FILL, TABLE, DEST);
PL/I
CALL LIB$MOVTC(SRC, FILL, TABLE, DEST);
STATUS = LIB$GET_INPUT(STRING, ’NAME:’);
VAX MACRO
In VAX MACRO, a calling sequence takes one of three forms, as illustrated by the
following examples:
CALLS #2,G^LIB$GET_INPUT
CALLG ARGLIST, G^LIB$GET_VM
JSB G^MTH$SIN_R4
As these examples show, high-level languages use different forms of the call
statement. Each language’s user guide gives specific information about calling
the run-time library from that language.

Calling Run-Time Library Routines 19–5


Calling Run-Time Library Routines
19.2 Call Instructions

19.2.2.1 JSB Call Entries (VAX Only)


On VAX systems, JSB entry point names follow the naming conventions explained
in Section 19.2.1, except that they include a suffix indicating the number of the
highest register accessed or modified. This suffix helps ensure that the calling
program and the called routine agree on the number of registers that the called
routine is going to change.
The following example illustrates the VAX MACRO code that invokes the library
routine MTH$SIN_R4 by means of a JSB instruction. As indicated in the JSB
entry point name, this routine uses R0 through R4.
JSB G^MTH$SIN_R4 ;F_floating sine uses R0 through R4
JSB entry points are available only to VAX MACRO and VAX BLISS programs.
No VAX high-level language provides a mechanism for accessing JSB entry points.

19.2.3 Returns from an RTL Routine


On VAX systems, some run-time library routines return a function value.
Typically on a VAX system, the return is in the form of a 32-bit value in register
R0 or a 64-bit value in registers R0 and R1. In high-level languages, statuses
or function return values in R0 appear as the function result. When a routine
returns a function value in R0, it cannot also use R1 to return a status code.
Therefore, such a procedure signals errors rather than returning a status. For
more information, refer to the OpenVMS Calling Standard or the description of
LIB$SIGNAL in the OpenVMS RTL Library (LIB$) Manual.
On Alpha systems, a standard function returns its function value in R0, F0, or F0
and F1. A function value of less than 64 bits returned by immediate value in R0
is zero-extended or sign-extended to a full quadword as required by the data type.
Note that a floating function value is returned by immediate value in F0 or in F0
and F1.
19.2.3.1 Facility Return Status and Condition Value Symbols
Library return status and condition value symbols have the following general
form:
fac$_abcmnoxyz
The elements that make up this format represent the following:
fac The 2- or 3-letter facility symbol
abc The first 3 letters of the first word of the associated message
mno The first 3 letters of the next word
xyz The first 3 letters of the third word, if any
Articles and prepositions are not considered significant words in this format. If a
significant word is only two letters long, an underscore is used to fill out the third
space. Some examples follow. Note that, in most facilities, the normal or success
symbol is an exception to the convention described here.
SS$_NORMAL Routine successfully completed
LIB$_INSVIRMEM Insufficient virtual memory
MTH$_FLOOVEMAT Floating overflow in mathematics library procedure
OTS$_FATINTERR Fatal internal error in a language-independent
support procedure

19–6 Calling Run-Time Library Routines


Calling Run-Time Library Routines
19.2 Call Instructions

LIB$_SCRBUFOVF Screen buffer overflow

19.3 Calling a Library Procedure in VAX MACRO (VAX Only)


This section describes how to code MACRO calls to library routines using a
CALLS, CALLG, or JSB instruction for VAX systems. The routine descriptions
that appear later in this manual describe the entry points for each routine. You
can use either a CALLS or a CALLG instruction to invoke a procedure with a
CALL entry point. You must use a JSB instruction to invoke a procedure with a
JSB entry point. All MACRO calls are explicitly defined.

19.3.1 VAX MACRO Calling Sequence


All run-time library routines have a CALL entry point. Some routines also have
a JSB entry point. In MACRO, you invoke a CALL entry point with a CALLS or
CALLG instruction. To access a JSB entry point, use a JSB instruction.
Arguments are passed to CALLS and CALLG entry points by a pointer to the
argument list. The only difference between the CALLS and CALLG instructions
is as follows:
• For CALLS, the calling procedure pushes the argument list onto the stack (in
reverse order) before performing the call. The list is automatically removed
from the stack upon return.
• For CALLG, the calling program specifies the address of the argument list,
which can be anywhere in memory. This list remains in memory upon return.
Both of these instructions have the same effect on the called procedure.
JSB instructions execute faster than CALL instructions. They do not set up a
new stack frame, do not change the enabling of hardware traps or faults, and
do not preserve the contents of any registers before modifying them. For these
reasons, you must be careful when invoking a JSB entry point in order to prevent
the loss of information stored by the calling program.
Whichever type of call you use, the actual reference to the procedure entry point
should use general-mode addressing (G^). This ensures that the linker and the
image activator are able to locate the module within the shareable image.
In most cases, you have to tell a library routine where to find input values and
store output values. You must select a data type for each argument when you
code your program. Most routines accept and return 32-bit arguments.
For input arguments of byte, word, or longword values, you can supply a constant
value, a variable name, or an expression in the run-time library routine call. If
you supply a variable name for the argument, the data type of the variable must
be as large as or larger than the data types that the called procedure requires.
For example, if the called procedure expects a byte in the range 0 to 100, you can
use a variable data type of a byte, word, or longword with a value between 0 and
100.
For each output argument, you must declare a variable of exactly the length
required to avoid extraneous data. For example, if the called procedure returns a
byte value to a word-length variable, the leftmost 8 bits of the variable <15:8> are
not overwritten on output. Conversely, if a procedure returns a longword value to
a word-length variable, it modifies variables in the next higher word.

Calling Run-Time Library Routines 19–7


Calling Run-Time Library Routines
19.3 Calling a Library Procedure in VAX MACRO (VAX Only)

19.3.2 VAX MACRO CALLS Instruction Example


Before executing a CALLS instruction, you must push the necessary arguments
on the stack. Arguments are pushed in reverse order; the last argument listed in
the calling sequence is pushed first. The following example shows how a MACRO
program calls the procedure that allocates virtual memory in the program region
for LIB$GET_VM.
.PSECT DATA PIC,USR,CON,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC
MEM: .LONG 0 ; Longword to hold address of
; allocated memory
LEN: .LONG 700 ; Number of bytes to allocate
.PSECT CODE PIC,USR,CON,REL,GBL,SHR,EXE,RD,NOWRT,NOVEC
.ENTRY PROG, ^M<>
PUSHAL MEM ; Push address of longword
; to receive address of block
PUSHAL LEN ; Push address of longword
; containing number of bytes
; desired
CALLS #2, G^LIB$GET_VM ; Allocate memory
BLBC R0, 1$ ; Branch if memory not available
RET
1$: PUSHL R0 ; Signal the error
CALLS #1, G^LIB$SIGNAL
RET
.END PROG
Because the stack grows toward location 0, arguments are pushed onto the stack
in reverse order from the order shown in the general format for the routine.
Thus, the base-address argument, here called START, is pushed first, and then
the number-bytes argument, called LEN. Upon return from LIB$GET_VM, the
calling program tests the return status (ret-status), which is returned in R0 and
branches to an appropriate error routine if an error occurred.

19.3.3 VAX MACRO CALLG Instruction Example


When you use the CALLG instruction, the arguments are set up in any location,
and the call includes a reference to the argument list. The following example of a
CALLG instruction is equivalent to the preceding CALLS example.
ARGLST:
.LONG 2 ; Argument list count
.ADDRESS LEN ; Address of longword containing
; the number of bytes to allocate.
.ADDRESS START ; Address of longword to receive
; the starting address of the
; virtual memory allocated.
LEN: .LONG 20 ; Number of bytes to allocate
START: .BLKL 1 ; Starting address of the virtual
; memory.

CALLG ARGLIST, G^LIB$GET_VM ; Get virtual memory


BLBC R0, ERROR ; Check for error
BRB 10$

19–8 Calling Run-Time Library Routines


Calling Run-Time Library Routines
19.3 Calling a Library Procedure in VAX MACRO (VAX Only)

19.3.4 VAX MACRO JSB Entry Points


A procedure’s JSB entry point name indicates the highest numbered register that
the procedure modifies. Thus, a procedure with a suffix Rn modifies registers
R0 through Rn. (You should always assume that R0 and R1 are modified.) The
calling program loads the arguments in the registers before the JSB instruction
is executed.
A calling program must use a JSB instruction to invoke a run-time library routine
by means of its JSB entry point. You pass arguments to a JSB entry point by
placing them in registers in the following manner:
NUM: .FLOAT 0.7853981 ; Constant P1/4
MOVF NUM, R0 ; Set up input argument
JSB G^MTH$SIN_R4 ; Call F_floating sine procedure
; Return with value in R0
In this example, R4 in the entry point name indicates that MTH$SIN_R4 changes
the contents of registers R0 through R4. The routine does not reference or change
the contents of registers R5 through R11.
The entry mask of a calling procedure should specify all the registers to be saved
if the procedure invokes a JSB routine. This step is necessary because a JSB
procedure does not have an entry mask and thus has no way to specify registers
to be saved or restored.
For example, consider program A calling procedure B by means of a CALL entry
point.
• Procedure B modifies the contents of R2 through R6, so the contents of these
registers are preserved at the time of the call.
• Procedure B then invokes procedure C by means of a JSB entry point.
• Procedure C modifies registers R0 through R7.
• When control returns to procedure B, R7 has been modified, but when
procedure B passes control back to procedure A, it restores only R2 through
R6. Thus, the contents of R7 are unpredictable, and program A does not
execute as expected. Procedure B should be rewritten so that R2 through R7
are saved in procedure B’s entry mask.
A similar problem occurs if the stack is unwound, because unwinding the stack
restores the contents of registers for each stack frame as it removes the previous
frame. Because a JSB entry point does not create a stack frame, the contents
of the registers before the JSB instruction will not be restored unless they were
saved in the entry mask of the calling program. You do this by naming the
registers to be saved in the calling program’s entry mask, so a stack unwind
correctly restores all registers from the stack. In the following example, the
function Y=PROC(A,B) returns the value Y, where Y = SIN(A)*SIN(B):
.ENTRY PROC, ^M <R2, R3, R4, R5> ; Save R2:R5
MOVF @4(AP), R0 ; R0 = A
JSB G^MTH$SIN_R4 ; R0 = SIN(A)
MOVF R0 , R5 ; Copy result to register
; not modified by MTH$SIN
MOVF @8(AP) , R0 ; R0 = B
JSB G^MTH$SIN_R4 ; R0 = SIN(B)
MULF R5 , R0 ; R0 = SIN(A)SIN(B)
RET ; Return

Calling Run-Time Library Routines 19–9


Calling Run-Time Library Routines
19.3 Calling a Library Procedure in VAX MACRO (VAX Only)

19.3.5 Return Status


Your VAX MACRO program can test for errors by examining segments of the
32-bit status code returned by a run-time library routine.
To test for errors, check for a zero in bit 0 using a Branch on Low Bit Set (BLBS)
or Branch on Low Bit Clear (BLBC) instruction.
To test for a particular condition value, compare the 32 bits of the return status
with the appropriate return status symbol using a Compare Long (CMPL)
instruction or the run-time library routine LIB$MATCH_COND.
There are three ways to define a symbol for the condition value returned by
a run-time library routine so that you can compare the value in R0 with a
particular error code:
• Using the .EXTRN symbol directive. This causes the assembler to generate
an external symbol declaration.
• Using the $facDEF macro call. Calling the $LIBDEF macro, for example,
causes the assembler to define all LIB$ condition values.
• By default. The assembler automatically declares the condition value as an
external symbol that is defined as a global symbol in the run-time library.
The following example asks for the user’s name. It then calls the run-time library
routine LIB$GET_INPUT to read the user’s response from the terminal. If the
string returned is longer than 30 characters (the space allocated to receive the
name), LIB$GET_INPUT returns in R0 the condition value equivalent to the
error LIB$_INPSTRTRU, ’input string truncated.’ This value is defined as a
global symbol by default. The example then checks for the specific error by
comparing LIB$_INPSTRTRU with the contents of R0. If LIB$_INPSTRTRU is
the error returned, the program considers that the routine executed successfully.
If any other error occurs, the program handles it as a true error.
$SSDEF ; Define SS$ symbols
$DSCDEF ; Define DSC$ symbols
.PSECT $DATA
PROMPT_D: ; Descriptor for prompt
.WORD PROMPT_LEN ; Length field
.BYTE DSC$K_DTYPE_T ; Type field is text
.BYTE DSC$K_CLASS_S ; Class field is string
.ADDRESS PROMPT ; Address
PROMPT: .ASCII /NAME: / ; String descriptor
PROMPT_LEN = . - PROMPT ; Calculate length of
; string
STR_LEN = 30 ; Use 30-byte string
STRING_D: ; Input string descriptor
.WORD STR_LEN ; Length field
.BYTE DSC$K_DTYPE_T ; Type field in text
.BYTE DSC$K_CLASS_S ; Class field is string
.ADDRESS STR_AREA ; Address
STR_AREA: .BLKB STR_LEN ; Area to receive string
.PSECT $CODE
.ENTRY START , ^M<>
PUSHAQ PROMPT_D ; Push address of prompt
; descriptor
PUSHAQ STRING_D ; Push address of string
; descriptor

19–10 Calling Run-Time Library Routines


Calling Run-Time Library Routines
19.3 Calling a Library Procedure in VAX MACRO (VAX Only)

CALLS #2 , G^LIB$GET_INPUT ; Get input string


BLBS R0 , 10$ ; Check for success
CMPL R0 , #LIB$_INPSTRTRU ; Error: Was it
; truncated string?
BEQL 10$ ; No, more serious error
PUSHL R0
CALLS #1 , G^LIB$SIGNAL
10$: MOVL #SS$_NORMAL , R0 ; Success, or name too
; long
RET
.END START

19.3.6 Function Return Values in VAX MACRO


Function values are generally returned in R0 (32-bit values) or R0 and R1 (64-bit
values). A MACRO program can access a function value by referencing R0 or R0
and R1 directly. For functions that return a string, the address of the string or
the address of its descriptor is returned in R0. If a function needs to return a
value larger than 64 bits, it must return the value by using an output argument.
Note the following exceptions to these rules:
• JSB entry points in the MTH$ facility return H_floating values in R0 through
R3.
• One routine, MTH$SINCOS, returns two function values: the sine and the
cosine of an angle. Depending on the data type of the function values, the
function values are returned in the following registers:
F_floating R0 and R1
D_floating R0 through R3
G_floating R0 through R3
H_floating R0 through R7
As in the case of output arguments, a variable declared to receive the function
values must be the same length as the value.

19.4 Calling a Library Routine in BLISS


This section describes how to code BLISS calls to library routines. A called
routine can return only one of the following:
• No value.
• A function value (typically, an integer or floating point number). For example,
MTH$SIN returns its result as an F_floating value in R0 on VAX systems or
F0 on Alpha systems.
On Alpha processors, BLISS cannot access floating point registers.
• A return status (typically, a 32-bit condition value) indicating that the routine
has either executed successfully or failed. For example, LIB$GET_INPUT
returns a return status in R0. If the routine executes successfully, it returns
SS$_NORMAL; if not, it returns one of several possible error condition values.
BLISS treats the return status like any other value.

Calling Run-Time Library Routines 19–11


Calling Run-Time Library Routines
19.4 Calling a Library Routine in BLISS

19.4.1 BLISS Calling Sequence


Scalar arguments are usually passed to run-time library routines by reference.
Thus, when a BLISS program passes a variable, the variable appears with no
preceding period in the procedure-call actual argument list. A constant value can
be easily passed by using the %REF built-in function.
The following example shows how a BLISS program calls LIB$PUT_OUTPUT.
This routine writes a record at the user’s terminal.
MODULE SHOWTIME(IDENT=’1-1’ %TITLE’Print time’, MAIN=TIMEOUT)=
BEGIN
LIBRARY ’SYS$LIBRARY:STARLET’; ! Defines system services, etc.
MACRO
DESC[]=%CHARCOUNT(%REMAINING), ! VAX string descriptor
UPLIT BYTE(%REMAINING) %; ! definition
BIND
FMTDESC=UPLIT( DESC(’At the tone, the time will be ’,
%CHAR(7), ’!%T’ ));
EXTERNAL ROUTINE
LIB$PUT_OUTPUT: ADDRESSING_MODE(GENERAL);
ROUTINE TIMEOUT
=
BEGIN
LOCAL
TIMEBUF: VECTOR[2], ! 64-bit system time
MSGBUF: VECTOR[80,BYTE], ! Output message buffer
MSGDESC: BLOCK[8,BYTE], ! Descriptor for message buffer
RSLT: WORD; ! Length of result string

!+
! Initialize the fields of the string descriptor.
!-
MSGDESC[DSC$B_CLASS]=DSC$K_CLASS_S;
MSGDESC[DSC$B_DTYPE]=DSC$K_DTYPE_T;
MSGDESC[DSC$W_LENGTH]=80;
MSGDESC[DSC$A_POINTER]=MSGBUF[0]
$GETTIM(TIMADR=TIMEBUF); ! Get time as 64-bit integer
$FAOL(CTRSTR=FMTDESC, ! Format descriptor
OUTLEN=RSLT, ! Output length (only a word!)
OUTBUF=MSGDESC, ! Output buffer desc.
PRMLST= %REF(TIMEBUF)); ! Address of 64-bit
! time block
MSGDESC [DSC$W_LENGTH] = .RSLT; ! Modify output desc.
RETURN (LIB$PUT_OUTPUT(MSGDESC); ! Return status
END;
END
ELUDOM

19.4.2 Accessing a Return Status in BLISS


BLISS accesses a function return value or condition value returned in R0 as
follows:
STATUS = LIB$PUT_OUTPUT(MSG_DESC);
IF NOT .STATUS THEN LIB$STOP(.STATUS);

19–12 Calling Run-Time Library Routines


Calling Run-Time Library Routines
19.4 Calling a Library Routine in BLISS

19.4.3 Calling JSB Entry Points from BLISS


Many of the library mathematics routines have JSB entry points. You can
invoke these routines efficiently from a BLISS procedure using LINKAGE and
EXTERNAL ROUTINE declarations, as in the following example:
MODULE JSB_LINK (MAIN = MATH_JSB, ! Example of using JSB linkage
IDENT = ’1-001’,
ADDRESSING_MODE(EXTERNAL = GENERAL)) =
BEGIN
LINKAGE
LINK_MATH_R4 = JSB (REGISTER = 0; ! input reg
REGISTER = 0): ! output reg
NOPRESERVE (0,1,2,3,4)
NOTUSED (5,6,7,8,9,10,11);
EXTERNAL ROUTINE
MTH$SIND_R4 : LINK_MATH_R4;
FORWARD ROUTINE
MATH_JSB;
LIBRARY ’SYS$LIBRARY:STARLET.L32’;
ROUTINE MATH_JSB = ! Routine
BEGIN
LOCAL
INPUT_VALUE : INITIAL (%E’30.0’),
SIN_VALUE;
!+
! Get the sine of single floating 30 degrees. The input, 30 degrees,
! is passed in R0, and the answer, is returned in R0. Registers
! 0 to 4 are modified by MTH$SIND_R4.
!-
MTH$SIND_R4 (.INPUT_VALUE ; SIN_VALUE);
RETURN SS$_NORMAL;
END; ! End of routine
END ! End of module JSB_LINK
ELUDOM

Calling Run-Time Library Routines 19–13


20
Calling System Services

The OpenVMS operating system kernel has many services that are made
available to application and system programs for use at run time. These system
services are procedures that the OpenVMS operating system uses to control
resources available to processes; to provide for communication among processes;
and to perform basic operating system functions, such as the coordination of
input/output operations. The OpenVMS Programming Concepts Manual defines
these functions further.
This chapter describes the basic methods and conventions for coding calls to
system services from OpenVMS high-level languages or from an assembly
language.
For more information about using the system services that support 64-bit
addressing and to see example programs that demonstrate the use of these
services, refer to Chapter 11.

20.1 Overview
System services are called by using the conventions of the OpenVMS Calling
Standard. The programming languages that generate VAX or Alpha native mode
instructions provide mechanisms for specifying the procedure calls.
When you call a system service from your program, you must furnish whatever
arguments the routine requires. When the system service procedure completes
execution, in most cases it returns control to your program. If the service returns
a status code, your program should check the value of the code to determine
whether or not the service completed successfully. If the return status indicates
an error, you may want to change the flow of execution of your program to handle
the error before returning control to your program.
When you write a program that calls a system service in the OpenVMS operating
system, the operating system views your program as a user procedure. User
procedures also can call other user procedures that are either supplied by
Compaq or written by you. Because an OpenVMS native-mode language compiler
program exists outside the operating system, compiler generated programs calling
any system service are also defined as a set of user procedures.
If you program in a high-level language, refer to Chapter 21 for information about
the SYS$LIBRARY:SYS$LIB_C.TLB file, which is an OpenVMS Alpha library of
C header files.
For VAX MACRO, system service macros generate argument lists and CALL
instructions to call system services. These macros are located in the system
library (see SYS$LIBRARY:STARLET.MLB). When you assemble a source
program, this library is searched automatically for unresolved references. (See
Appendix A for further details.) Similar macros are available for VAX BLISS and
are located in SYS$LIBRARY:STARLET.REQ.

Calling System Services 20–1


Calling System Services
20.2 Preserving System Integrity

20.2 Preserving System Integrity


As described in the OpenVMS Programming Concepts Manual and the OpenVMS
System Services Reference Manual, many system services are available and
suitable for application programs, but the use of some of these powerful services
must be restricted to protect the performance of the system and the integrity of
user processes.
For example, because the creation of permanent mailboxes uses system dynamic
memory, the unrestricted use of permanent mailboxes could decrease the amount
of memory available to other users. Therefore, the ability to create permanent
mailboxes is controlled: a user must be specifically assigned the privilege to
use the Create Mailbox (SYS$CREMBX) system service to create a permanent
mailbox.
The various controls and restrictions applied to system service usage are
described in this chapter. The Description section of each system service in the
OpenVMS System Services Reference Manual lists any privileges and quotas
necessary to use the service.

20.2.1 User Privileges


The system manager, who maintains the user authorization file for the
system, grants privileges for access to the protected system services. The user
authorization file contains, in addition to profile information about each user, a
list of specific user privileges and resource quotas.
When you log in to the system, the privileges and quotas assigned to you are
associated with the process created on your behalf. These privileges and quotas
are applied to every image the process executes.
When an image issues a call to a system service that is protected by privilege, the
privilege list is checked. If you have the specific privilege required, the image is
allowed to execute the system service; otherwise, a condition value indicating an
error is returned.
For a list of privileges, see the description of the Create Process ($CREPRC)
system service in the OpenVMS System Services Reference Manual.

20.2.2 Resource Quotas


Many system services require certain system resources for execution. These
resources include system dynamic memory and process quotas for I/O operations.
When a system service that uses a resource controlled by a quota is called, the
process’s quota for that resource is checked. If the process has exceeded its quota,
or if it has no quota allotment, an error condition value may be returned.

20.2.3 Access Modes


A process can execute at any one of four access modes: user, supervisor, executive,
or kernel. The access modes determine a process’s ability to access pages of
virtual memory. Each page has a protection code associated with it, specifying
the type of access—read, write, or no access—allowed for each mode.
For the most part, user-written programs execute in user mode; system programs
executing at the user’s request (system services, for example) may execute at one
of the other three, more privileged access modes.

20–2 Calling System Services


Calling System Services
20.2 Preserving System Integrity

In some system service calls, the access mode of the caller is checked. For
example, when a process tries to cancel timer requests, it can cancel only those
requests that were issued from the same or less privileged access modes. For
example, a process executing in user mode cannot cancel a timer request made
from supervisor, executive, or kernel mode.
Note that many system services use access modes to protect system resources,
and thus employ a special convention for interpreting access mode arguments.
You can specify an access mode using a numeric value or a symbolic name.
Table 20–1 shows the access modes and their numeric values, symbolic names,
and privilege ranks.

Table 20–1 OpenVMS System Access Modes


Access Numeric Symbolic Privilege
Mode Value Name Rank
Kernel 0 PSL$C_KERNEL Highest
Executive 1 PSL$C_EXEC
Supervisor 2 PSL$C_SUPER
User 3 PSL$C_USER Lowest

The symbolic names are defined by the symbolic definition macro SYS$PSLDEF.
System services that permit an access mode argument allow callers to specify
only an access mode of equal or lesser privilege than the access mode from which
the service was called. If the specified access mode is more privileged than the
access mode from which the service was called, the less privileged access mode is
always used.
To determine the mode to use, the operating system compares the specified access
mode with the access mode from which the service was called. Because this
operation results in an access mode with a higher numeric value (when the access
mode of the caller is different from the specified access mode), the access mode is
said to be maximized.
Because much of the code you write executes in user mode, you can omit the
access mode argument. The argument value defaults to 0 (kernel mode), and
when this value is compared with the value of the current execution mode
(3, user mode), the higher value ( 3 ) is used.

20.3 System Service Call Entry


The Format section of each system service description in the OpenVMS System
Services Reference Manual indicates the positional dependencies and keyword
names of each argument, as shown in the following format:
$SERVICE arga ,argb ,argc ,argd
This format indicates that the macro name of the service is $SERVICE and that
it requires four arguments, ordered as shown and with keyword names arga,
argb, argc, and argd.
Arguments passed to a service must be listed in your call entry in the order
shown in the Format section of the service description. Each argument has four
characteristics: OpenVMS usage, data type, access type, and passing mechanism.
These characteristics are described in Chapter 17.

Calling System Services 20–3


Calling System Services
20.3 System Service Call Entry

The OpenVMS Alpha SYS$LIBRARY:SYS$LIB_C.TLB file contains C function


prototypes for system services. These prototypes are documented in OpenVMS
System Services Reference Manual: A–GETUAI and and OpenVMS System
Services Reference Manual: GETUTC–Z. For each prototype, the manuals provide
the correct syntax (which shows the arguments the function accepts in the order
in which it expects them), a description of each argument, and the type of data
returned by the function.
Some arguments are optional. Optional arguments are indicated by brackets in
the service descriptions. When your program invokes a system service by using a
CALL entry point, you can omit optional arguments at the end of the argument
list. If the optional argument is not the last argument in the list, you must
either pass a zero by value or use a comma to indicate the place of the omitted
argument. Some languages, such as C, require that you pass a zero by value for
all trailing optional arguments. See your language processor documentation for
further information.
In the call statement of a high-level language program, you must prefix the macro
function service name with SYS (the system service facility prefix). For example,
the call statement in a C program procedure that calls the SYS$GETDVI system
service with four arguments is as follows:
return_status = sys$getdvi( event_flagnum, channel, &devnam, &item_list,0,0,0);
Note that in C, you must not omit the optional trailing arguments and should
pass a zero by value for these unused parameters. See your language processor
documentation for further information.
The OpenVMS System Services Reference Manual provides a description of each
service that indicates how each argument is to be passed. Phrases such as ‘‘an
address’’ and ‘‘address of a character string descriptor’’ identify reference and
descriptor arguments, respectively. Terms like ‘‘Boolean value,’’ ‘‘number,’’ ‘‘value,’’
or ‘‘mask’’ indicate an argument that is passed by value.
In the Alpha and VAX environments, the called routine interprets each argument
using one of three standard passing mechanisms: by value, by reference, or by
descriptor.
On VAX systems, the calling program passes an argument list of longwords to a
called service; each longword in the argument list specifies a single argument.
On Alpha systems, the calling program passes arguments in an argument item
sequence; each quadword in the sequence specifies a single argument item. Note
that the argument item sequence is formed using R16–R21 or F16–F21 (a register
for each argument).
For more detailed information on arguments lists and passing mechanisms, see
Sections 18.4 and 18.5.
Some services also require service-specific data structures that either indicate
functions to be performed or hold information to be returned. The OpenVMS
System Services Reference Manual includes descriptions of these service-specific
data structures. You can use this information and information from your
programming language manuals to define such service-specific item lists.

20–4 Calling System Services


Calling System Services
20.4 System Service Completion

20.4 System Service Completion


When a system service completes, control is returned to your program. You
can specify how and when control is returned to your program by choosing
synchronous or asynchronous forms of system services and by enabling process
execution modes.
The following sections describe:
• When synchronous system services return control to your program
• When asynchronous system services return control to your program
• How you can synchronize the completion of asynchronous system services
• How control is returned to your program when special process execution
modes are enabled

20.4.1 Asynchronous and Synchronous System Services


You can execute a number of system services either asynchronously or
synchronously (such as, SYS$GETJPI and SYS$GETJPIW or SYS$ENQ and
SYS$ENQW). The W at the end of the system service name indicates the
synchronous version of the system service.
The asynchronous version of a system service queues a request and returns
control to your program. You can perform operations while the system service
executes; however, you should not attempt to access information returned by the
service until you check for the system service completion.
Typically, you pass to an asynchronous system service an event flag and an I/O
status block or a lock status block. When the system service completes, it sets the
event flag and places the final status of the request in the status block. You use
the SYS$SYNCH system service to ensure that the system service has completed.
You pass SYS$SYNCH the event flag and the status block that you passed to the
asynchronous system service; SYS$SYNCH waits for the event flag to be set, then
ensures that the system service (rather than some other program) sets the event
flag by checking the status block. If the status block is still zero, SYS$SYNCH
waits until the status block is filled.
The synchronous version of a system service acts exactly as if you had used the
asynchronous version followed immediately by a call to SYS$SYNCH. If you omit
the efn argument, the service uses event flag number 0 whether you use the
synchronous or asynchronous version of a system service.
Example 20–1 illustrates the use of the SYS$SYNCH system service to check the
completion status of the asynchronous service SYS$GETJPI.

Calling System Services 20–5


Calling System Services
20.4 System Service Completion

Example 20–1 Example of SYS$SYNCH System Service in FORTRAN


! Data structure for SYS$GETJPI
.
.
.
INTEGER*4 STATUS,
2 FLAG,
2 PID_VALUE
! I/O status block
INTEGER*2 JPISTATUS,
2 LEN
INTEGER*4 ZERO /0/
COMMON /IO_BLOCK/ JPISTATUS,
2 LEN,
2 ZERO
.
.
.
! Call SYS$GETJPI and wait for information
STATUS = LIB$GET_EF (FLAG)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
STATUS = SYS$GETJPI (%VAL(FLAG),
2 PID_VALUE,
2 ,
2 NAME_BUF_LEN,
2 JPISTATUS,
2 ,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
.
.
.
STATUS = SYS$SYNCH (%VAL(FLAG),
2 JPISTATUS)
IF (.NOT. JPISTATUS) THEN
CALL LIB$SIGNAL (%VAL(JPISTATUS))
END IF
END

20.4.2 System Service Resource Wait Mode


Normally, when a system service is called and a required resource is not available,
the process is placed in a wait state until the resource becomes available. Then
the service completes execution. This mode is called resource wait mode.
In a real-time environment, however, it may not be practical or desirable for a
program to wait. In these cases, you can choose to disable resource wait mode
so that when a required resource is unavailable, control returns immediately to
the calling program with an error condition value. You can disable (and reenable)
resource wait mode with the Set Resource Wait Mode (SYS$SETRWM) system
service.
If resource wait mode is disabled, it remains disabled until it is explicitly
reenabled or until your process is deleted. For example, if your program has
disabled resource wait mode and has exited to the DCL prompt, subsequent
programs or utilities invoked by this process continue to run with resource wait
mode disabled and might not perform properly because they are not prepared to
handle a failure to obtain a resource. In this case, you should reenable the wait
mode before your program exits to the DCL prompt.

20–6 Calling System Services


Calling System Services
20.4 System Service Completion

How a program responds to the unavailability of a resource depends primarily


on the application and the particular service being called. In some instances, the
program may be able to continue execution and retry the service call later. In
other instances, it may be necessary for the program to wait for the resource and
the system service to complete.

20.4.3 Condition Values Returned from System Services


When a service returns control to your program, it places a return status value in
the general register R0. The value in the low-order word indicates either that the
service completed successfully or that some specific error prevented the service
from performing some or all of its functions. After each call to a system service,
you must check whether it completed successfully. You can also test for specific
errors in the condition value.
Depending on your specific needs, you can test just the low-order bit, the low-
order 3 bits, or the entire condition value, as follows:
• The low-order bit indicates successful (1) or unsuccessful (0) completion of the
service.
• The low-order 3 bits, taken together, represent the severity of the error.
Table 20–2 lists the possible severity code values returned.
For VAX MACRO, the symbolic definition macro SYS$STSDEF defines the
symbolic names. For the C programming language, the SSDEF.H file defines
the symbolic names.
• The remaining bits (bits 3 through 31) classify the particular return condition
and the operating system component that issued the condition value. For
system service return status values, the high-order word (bits 16 through 31)
contains zeros.

Table 20–2 Severity Codes of Condition Value Returned


Value Meaning Symbolic Name
0 Warning STS$K_WARNING
1 Success STS$K_SUCCESS
2 Error STS$K_ERROR
3 Informational STS$K_INFO
4 Severe or fatal error STS$K_SEVERR
5–7 Reserved

Each numeric condition value has a unique symbolic name in the following
format:
SS$_code
where code is a mnemonic describing the return condition.
For example, the following symbol usually indicates a successful return:
SS$_NORMAL
An example of an error return condition value is as follows:
SS$_ACCVIO

Calling System Services 20–7


Calling System Services
20.4 System Service Completion

This condition value indicates that an access violation occurred because a service
could not read an input field or write an output field.
The symbolic definitions for condition values are included in the default system
library SYS$LIBRARY:STARLET.OLB. You can obtain a listing of these symbolic
codes at assembly time by invoking the system macro SYS$SSDEF. To check
return conditions, use the symbolic names for system condition values.
The OpenVMS operating system does not automatically handle system service
failure or warning conditions; you must test for them and handle them yourself.
This contrasts with the operating system’s handling of exception conditions
detected by the hardware or software; the system handles these exceptions
by default, although you can intervene in or override the default handling by
declaring a condition handler.

20.4.4 Testing the Condition Value


Each language provides some mechanism for testing the return status. Often
you need only check the low-order bit, such as by a test for TRUE (success or
informational return) or FALSE (error or warning return). Condition values that
are returned by system services can provide information and whether the service
completed successfully. The condition value that usually indicates success is
SS$_NORMAL, but others are defined. For example, the condition value SS$_
BUFFEROVF, which is returned when a character string returned by a service
is longer than the buffer provided to receive it, is a success code. This condition
value, however, gives the program additional information.
Warning returns and some error returns indicate that the service performed
some, but not all, of the requested function.
The possible condition values that each service can return are described with
the individual service descriptions in the OpenVMS System Services Reference
Manual. When you write calls to system services, read the descriptions of the
return condition values to determine whether you want the program to check for
particular return conditions.
To check the entire value for a specific return condition, each language provides
a way for your program to determine the values associated with specific
symbolically defined codes. You should always use these symbolic names when
you write tests for specific conditions.
For information about how to test for these codes, see the user’s guide for your
programming language.

20.4.5 Special Condition Values Using Symbolic Codes


Individual services have symbolic codes for special return conditions, argument
list offsets, identifiers, and flags associated with these services. For example,
the Create Process (SYS$CREPRC) system service (which is used to create a
subprocess or a detached process) has symbolic codes associated with the various
privileges and quotas you can grant to the created process.
The SYS$LIBRARY:SYS$LIB_C.TLB file contains the C header files for
OpenVMS Alpha C data structures and definitions. For more information
about SYS$LIBRARY:SYS$LIB_C.TLB, refer to Chapter 21.
The default system macro library, STARLET.MLB, contains the macro definitions
for most system symbols. When you assemble a source program that calls any of
these macros, the assembler automatically searches STARLET.MLB for the macro
definitions. Each symbol name has a numeric value.

20–8 Calling System Services


Calling System Services
20.4 System Service Completion

If your language has a method of obtaining values for these symbols, this method
is explained in the user’s guide.
If your language does not have such a method, you can do the following:
1. Write a short VAX MACRO program containing the desired macros.
2. Assemble or compile the program and generate a listing. Using the listing,
find the desired symbols and their hexadecimal values.
3. Define each symbol with its value within your source program.
For example, to use the Get Job/Process Information ($GETJPI) system service
to find out the accumulated CPU time (in 10-millisecond ticks) for a specified
process, you must obtain the value associated with the item identifier JPI$_
CPUTIM. You can do this in the following way:
1. Create the following three-line VAX MACRO program (named JPIDEF.MAR
here; you can choose any name you want):
.TITLE JPIDEF "Obtain values for $JPIDEF"
$JPIDEF GLOBAL ; These MUST be UPPERCASE
.END
2. Assemble and link the program to create the file JPIDEF.MAP as follows:
$ MACRO JPIDEF
$ LINK/NOEXE/MAP/FULL JPIDEF
%LINK-W-USRTFR, image NL:[].EXE; has no user transfer address
The file JPIDEF.MAP contains the symbols defined by $JPIDEF listed both
alphabetically and numerically.
To compile the program to create the JPIDEF.MAP, enter the following:
$ MACRO/MIGRATION JPIDEF
$ LINK/NOEXE/MAP/FULL JPIDEF
%LINK-W-USRTFR, image NL:[].EXE; has no user transfer address
3. Find the value of JPI$_CPUTIM and define the symbol in your program.

20.4.6 Testing the Return Condition Value for Assembly Languages


To check for successful completion after a system service call, the program can
test the low-order bit of R0 and branch to an error-checking routine if this bit is
not set, as follows:
BLBC R0,errlabel ; Error if low bit clear
Programs should not test for success by comparing the return status to SS$_
NORMAL. A future release of OpenVMS may add new, alternate success codes to
an existing service, causing programs that test for SS$_NORMAL to fail.
The error-checking routine may check for specific values or for specific severity
levels. For example, the following VAX MACRO instruction checks for an illegal
event flag number error condition:
CMPL #SS$_ILLEFC,R0 ; Is event flag number illegal?
Note that return condition values are always longword values; however, all
system services always return the same value in the high-order word of all
condition values returned in R0.

Calling System Services 20–9


Calling System Services
20.4 System Service Completion

20.4.7 System Messages Generated by Condition Values


When you execute a program with the DCL command RUN, the command
interpreter uses the contents of R0 to issue a descriptive message if the program
completes with an unsuccessful status.
The following VAX MACRO code fragment shows a simple error-checking
procedure in a main program:
$READEF_S -
EFN=#64, -
STATE=TEST
BSBW ERROR
.
.
.
ERROR: BLBC R0,10$ ; Check register 0
RSB ; Success, return
10$: RET ; Exit with R0 status
After a system service call, the BSBW instruction branches to the subroutine
ERROR. The subroutine checks the low-order bit in register 0 and, if the bit is
clear, branches to a RET instruction that causes the program to exit with the
status of R0 preserved. Otherwise, the subroutine issues an RSB instruction to
return to the main program.
If the event flag cluster requested in this call to $READEF is not currently
available to the process, the program exits and the command interpreter displays
the following message:
%SYSTEM-F-UNASEFC, unassociated event flag cluster
The keyword UNASEFC in the message corresponds to the condition value
SS$_UNASEFC.
The following three severe errors generated by the calls, not the services, can be
returned from calls to system services:

Error Meaning
SS$_ACCVIO The argument list cannot be read by the caller (using the
$name_G macro), and the service is not called.
This meaning of SS$_ACCVIO is different from its meaning
for individual services. When SS$_ACCVIO is returned from
individual services, the service is called, but one or more
arguments to the service cannot be read or written by the
caller.
SS$_INSFARG Not enough arguments were supplied to the service.
SS$_ILLSER An illegal system service was called.

20–10 Calling System Services


Calling System Services
20.5 Program Examples with System Service Calls

20.5 Program Examples with System Service Calls


This section provides code examples that illustrate the use of a system service
call in the following programming languages:
Ada — Example 20–2
BASIC — Example 20–3
BLISS — Example 20–4
C — Example 20–5
COBOL — Example 20–6
FORTRAN — Example 20–7
Pascal — Example 20–8
VAX MACRO — Example 20–9

Example 20–2 System Service Call in Ada

with SYSTEM, TEXT_IO, STARLET, CONDITION_HANDLING; !


procedure ORION is
-- Declare variables to hold equivalence name and length
--
EQUIV_NAME: STRING (1..255); "
pragma VOLATILE (EQUIV_NAME);
NAME_LENGTH: SYSTEM.UNSIGNED_WORD;
pragma VOLATILE (NAME_LENGTH);
-- Declare itemlist and fill in entries.
--
ITEM_LIST: STARLET.ITEM_LIST_3_TYPE (1..2) := #
(1 =>
(ITEM_CODE => STARLET.LNM_STRING, $
BUF_LEN => EQUIV_NAME’LENGTH,
BUF_ADDRESS => EQUIV_NAME’ADDRESS,
RET_ADDRESS => NAME_LENGTH’ADDRESS),
2 =>
(ITEM_CODE => 0,
BUF_LEN => 0,
BUF_ADDRESS => SYSTEM.ADDRESS_ZERO,
RET_ADDRESS => SYSTEM.ADDRESS_ZERO));
STATUS: CONDITION_HANDLING.COND_VALUE_TYPE; %
begin
-- Translate the logical name
--
STARLET.TRNLNM ( &
STATUS => STATUS,
TABNAM => "LNM$FILE_DEV",
LOGNAM => "CYGNUS",
ITMLST => ITEM_LIST);
-- Display name if success, else signal error
--
if not CONDITION_HANDLING.SUCCESS (STATUS) then ’
CONDITION_HANDLING.SIGNAL (STATUS);
else
TEXT_IO.PUT ("CYGNUS translates to """);
TEXT_IO.PUT (EQUIV_NAME (1..INTEGER(NAME_LENGTH)));
TEXT_IO.PUT_LINE ("""");
end if;
end ORION;

Calling System Services 20–11


Calling System Services
20.5 Program Examples with System Service Calls

Ada Notes
! The with clause names the predefined packages of declarations used in this
program. SYSTEM and TEXT_IO are standard Ada packages; STARLET
defines the OpenVMS system service routines, data types, and constants; and
CONDITION_HANDLING defines error-handling facilities.
" Enough space is allocated to EQUIV_NAME to hold the longest possible
logical name. NAME_LENGTH will receive the actual length of the
translated logical name. The VOLATILE pragma is required for variables
that will be modified by means other than an assignment statement or being
an output parameter to a routine call.
# ITEM_LIST_3_TYPE is a predeclared type in package STARLET that defines
the OpenVMS three-longword item list structure.
$ The dollar-sign character is not valid in Ada identifiers; package STARLET
defines the fac$ names by removing the dollar sign.
% COND_VALUE_TYPE is a predeclared type in package CONDITION_
HANDLING that is used for return status values.
& System services are defined in package STARLET using names that omit the
prefix SYS$. The passing mechanisms are specified in the routine declaration
in STARLET, so they need not be specified here.
’ In this example, any failure status from the SYS$TRNLNM service is
signaled as an error. Other means of error recovery are possible; see your
Ada language documentation for more details.

20–12 Calling System Services


Calling System Services
20.5 Program Examples with System Service Calls

Example 20–3 System Service Call in BASIC

10 SUB ORION ! ! Subprogram ORION


OPTION TYPE=EXPLICIT ! Require declaration of all
! symbols
EXTERNAL LONG FUNCTION SYS$TRNLNM ! Declare the system service
EXTERNAL WORD CONSTANT LNM$_STRING ! The request code that
! we will use
DECLARE WORD NAMLEN, " ! Word to receive length
LONG SYS_STATUS ! Longword to receive status
COMMON (BUF) STRING NAME_STRING = 255 #
RECORD ITEM_LIST ! Define item
! descriptor structure
WORD BUFFER_LENGTH ! The buffer length
WORD ITEM ! The request code
LONG BUFFER_ADDRESS ! The buffer address
LONG RETURN_LENGTH_ADDRESS ! The address of the return len
! word
LONG TERMINATOR ! The terminator
END RECORD ITEM_LIST ! End of structure definition
DECLARE ITEM_LIST ITEMS ! Declare an item list
ITEMS::BUFFER_LENGTH = 255% ! Initialize the item list
ITEMS::ITEM = LNM$_STRING
ITEMS::BUFFER_ADDRESS = LOC( NAME_STRING )
ITEMS::RETURN_LENGTH_ADDRESS = LOC( NAMLEN )
ITEMS::TERMINATOR = 0
$
SYS_STATUS = SYS$TRNLNM( , ’LNM$FILE_DEV’, ’CYGNUS’,, ITEMS) %
IF (SYS_STATUS AND 1%) = 0% &
THEN
! Error path
ELSE
! Success path
END IF
END SUB

BASIC Notes
! The SUB statement defines the routine and its entry mask.
" The DECLARE WORD NAMLEN declaration reserves a 16-bit word for the
output value.
# The COMMON (BUF) STRING NAME_STRING = 255 declaration allocates
255 bytes for the output data in a static area. The compiler builds the
descriptor.
$ The SYS$ form invokes the system service as a function.
Enclose the arguments in parentheses and specify them in positional order
only. Specify a comma for each optional argument that you omit (including
trailing arguments).
% The input character string is specified directly in the system service call; the
compiler builds the descriptor.
& The IF statement performs a test on the low-order bit of the return status.
This form is recommended for all status returns.

Calling System Services 20–13


Calling System Services
20.5 Program Examples with System Service Calls

Example 20–4 System Service Call in BLISS


MODULE ORION=
BEGIN
EXTERNAL ROUTINE
ERROR_PROC: NOVALUE; ! Error processing routine
LIBRARY ’SYS$LIBRARY:STARLET.L32’; ! Library containing OpenVMS
! macros (including $TRNLNM).
! This declaration
! is required.
GLOBAL ROUTINE ORION: NOVALUE=
BEGIN
OWN
NAMBUF : VECTOR[255, BYTE], ! Output buffer
NAMLEN : WORD, ! Translated string length
ITEMS : BLOCK[16,BYTE]
INITIAL(WORD(255, ! Output buffer length
LNM$_STRING), ! Item code
NAMBUF, ! Output buffer
NAMLEN, ! Address of word for
! translated
! string length
0); ! List terminator
LOCAL ! Return status from
STATUS; ! system service
STATUS = $TRNLNM(TABNAM = %ASCID’LNM$FILE_DEV’,
LOGNAME = %ASCID’CYGNUS’,
ITMLST = ITEMS); !
IF NOT .STATUS THEN ERROR_PROC(.STATUS); "
END;

BLISS Notes
! The macro is invoked by its service name, without a suffix.
Enclose the arguments in parentheses and specify them by keyword.
(Keyword names correspond to the names of the arguments shown in
lowercase in the system service format descriptions in the OpenVMS System
Services Reference Manual.)
" The return status, which is assigned to the variable STATUS, is tested for
TRUE or FALSE. FALSE (low bit = 0) indicates failure or warning.

20–14 Calling System Services


Calling System Services
20.5 Program Examples with System Service Calls

Example 20–5 System Service Call in C

#include <starlet.h> !
#include <lib$routines.h>
#include <ssdef.h>
#include <lnmdef.h>
#include <descrip.h>
#include <stdio.h>
typedef struct { "
unsigned short buffer_length;
unsigned short item_code;
char *buffer_addr;
short *return_len_addr;
unsigned terminator;
} item_list_t;

main ()
{ #
$DESCRIPTOR(table_name, "LNM$FILE_DEV");
$DESCRIPTOR(log_name, "CYGNUS");
char translated_name[255];
int status;
short return_length;
item_list_t item_list;
item_list.buffer_length = sizeof(translated_name); $
item_list.item_code = LNM$_STRING;
item_list.buffer_addr = translated_name;
item_list.return_len_addr = &return_length;
item_list.terminator = 0;
status = sys$trnlnm(0, &table_name, &log_name, 0, &item_list); %
if (!(status & 1)) &
lib$signal(status);
else
printf("The logical name %s is equivalent to %*s\n",
log_name.dsc$a_pointer,
return_length,
translated_name);
}

C Notes
! The C language header file starlet.h defines OpenVMS system services
entry points. The file lib$routines.h declares the LIB$ Run-Time Library
routines.
" The structure of an item list entry is defined.
# The $DESCRIPTOR macro declares and initializes a character string
descriptor. Here, two descriptors are created for use with the sys$trnlnm
system service.
$ The function sizeof is used to obtain the size of the string. The returned
length will be stored as a short integer in return_length.
% The sys$trnlnm routine is defined in starlet.h.
& The IF statement performs a logical test following the function reference to
determine whether the service completed successfully. If an error or warning
occurs during the service call, the error is signaled.

Calling System Services 20–15


Calling System Services
20.5 Program Examples with System Service Calls

Example 20–6 System Service Call in COBOL


IDENTIFICATION DIVISION.
PROGRAM-ID. ORION. !
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 TABNAM PIC X(11) VALUE "LNM$FILE_DEV".
01 CYGDES PIC X(6) VALUE "CYGNUS".
01 NAMDES PIC X(255) VALUE SPACES. "
01 NAMLEN PIC S9(4) COMP.
01 ITMLIS.
02 BUFLEN PIC S9(4) COMP VALUE 225.
02 ITMCOD PIC S9(4) COMP VALUE 2. #
02 BUFADR POINTER VALUE REFERENCE NAMDES.
02 RETLEN POINTER VALUE REFERENCE NAMLEN.
02 FILLER PIC S9(5) COMP VALUE 0.
01 RESULT PIC S9(9) COMP. $
PROCEDURE DIVISION.
START-ORION.
CALL "SYS$TRNLNM" %
USING OMITTED
BY DESCRIPTOR TABNAM
BY DESCRIPTOR CYGDES &
OMITTED
BY REFERENCE ITMLIS
GIVING RESULT.
IF RESULT IS FAILURE ’
GO TO ERROR-CHECK.
DISPLAY "NAMDES: ", NAMDES(1:NAMLEN).
GO TO THE-END.
ERROR-CHECK.
DISPLAY "Returned Error: ", RESULT CONVERSION.
THE-END.
STOP RUN.

COBOL Notes
! The PROGRAM-ID paragraph identifies the program by specifying the
program name, which is the global symbol associated with the entry point.
The compiler builds the entry mask.
" Enough bytes are allocated for the alphanumeric output data. The compiler
generates a descriptor when you specify USING BY DESCRIPTOR in the
CALL statement.
# The value of the symbolic code LNM$STRING is 2. Section 20.4.5 explains
how to obtain values for symbolic codes.
$ This definition reserves a signed longword with COMP (binary) usage to
receive the output value.
% The service is called by the SYS$ form of the service name, and the name is
enclosed in quotation marks.
Specify arguments in positional order only, with the USING statement. You
cannot omit arguments; if you are accepting the default for an argument, you
must pass the default value explicitly (OMITTED in this example).
You can specify explicitly how each argument is being passed: by descriptor,
by reference (that is, by address), or by value. You can also implicitly
specify how an argument is being passed: through the default mechanism

20–16 Calling System Services


Calling System Services
20.5 Program Examples with System Service Calls

(by reference), or through association with the last specified mechanism (thus,
the last two arguments in the example are implicitly passed by value).
& The input string is defined as alphanumeric (ASCII) data. The compiler
generates a descriptor when you specify USING BY DESCRIPTOR in the
CALL statement.
’ The IF statement tests RESULT for a failure status. In this case, control is
passed to the routine ERROR-CHECK.

Example 20–7 System Service Call in FORTRAN


SUBROUTINE ORION
IMPLICIT NONE ! Require declaration of all symbols
INCLUDE ’($SYSSRVNAM)’ ! Declare system service names !
INCLUDE ’($LNMDEF)’ ! Declare $TRNLNM item codes
INCLUDE ’(LIB$ROUTINES)’ ! Declare LIB$ routines
STRUCTURE /ITEM_LIST_3_TYPE/ ! Structure of item list "
INTEGER*2 BUFLEN ! Item buffer length
INTEGER*2 ITMCOD ! Item code
INTEGER*4 BUFADR ! Item buffer address
INTEGER*4 RETADR ! Item return length address
END STRUCTURE
RECORD /ITEM_LIST_3_TYPE/ ITEMLIST(2) ! Declare itemlist
CHARACTER*255 EQUIV_NAME ! For returned equivalence name
INTEGER*2 NAMLEN ! For returned name length
VOLATILE EQUIV_NAME,NAMLEN #
INTEGER*4 STATUS ! For returned service status $
! Fill in itemlist
!
ITEMLIST(1).ITMCOD = LNM$_STRING
ITEMLIST(1).BUFLEN = LEN(EQUIV_NAME) %
ITEMLIST(1).BUFADR = %LOC(EQUIV_NAME)
ITEMLIST(1).RETADR = %LOC(NAMLEN)
ITEMLIST(2).ITMCOD = 0 ! For terminator
ITEMLIST(2).BUFLEN = 0
! Call SYS$TRNLM
!
STATUS = SYS$TRNLNM (, ! ATTR omitted &
1 ’LNM$FILE_DEV’, ! TABNAM
2 ’CYGNUS’, ! LOGNAM
3 , ! ACMODE omitted
4 ITEMLIST) ! ITMLST
! Check return status, display translation if successful
!
IF (.NOT. STATUS) THEN ’
CALL LIB$SIGNAL(%VAL(STATUS))
ELSE
WRITE (*,*) ’CYGNUS translates to: "’,
1 EQUIV_NAME(1:NAMLEN), ’"’
END IF
END

FORTRAN Notes
! The module $SYSSRVNAM in the FORTRAN system default library
FORSYSDEF.TLB contains INTEGER and EXTERNAL declarations for each
of the system services, so you need not explicitly provide these declarations in
your program. Module $LNMDEF defines constants and data structures used

Calling System Services 20–17


Calling System Services
20.5 Program Examples with System Service Calls

when calling the logical name services, and module LIB$ROUTINES contains
declarations for the LIB$ Run-Time Library routines.
" The structure of an OpenVMS 3-longword item list is declared and then used
to define the record variable ITEM_LIST. The second element will be used for
the terminator.
# The VOLATILE declaration is required for variables that are modified by
means other than a direct assignment or as an argument in a routine call.
$ Return status variables should always be declared as longword integers.
% The LEN intrinsic function returns the allocated length of EQUIV_NAME.
The %LOC built-in function returns the address of its argument.
& By default, FORTRAN passes arguments by reference, except for strings
which are passed by CLASS_S descriptor. Arguments are omitted in
FORTRAN by leaving the comma as a placeholder. All arguments must
be specified or explicitly omitted.
’ A condition value can be tested for success or failure by a true/false test. For
more information on testing return statuses, see the OpenVMS FORTRAN
documentation.

20–18 Calling System Services


Calling System Services
20.5 Program Examples with System Service Calls

Example 20–8 System Service Call in Pascal

[INHERIT(’SYS$LIBRARY:STARLET’, !
’SYS$LIBRARY:PASCAL$LIB_ROUTINES’)]
PROGRAM ORION (OUTPUT);
TYPE
Item_List_Cell = RECORD CASE INTEGER OF "
1:( { Normal Cell }
Buffer_Length : [WORD] 0..65535;
Item_Code : [WORD] 0..65535;
Buffer_Addr : UNSIGNED;
Return_Addr : UNSIGNED
);
2:( { Terminator }
Terminator : UNSIGNED
);
END;
Item_List_Template(Count:INTEGER) = ARRAY [1..Count] OF Item_List_Cell;
VAR
Item_List : Item_List_Template(2);
Translated_Name : [VOLATILE] VARYING [255] OF CHAR; #
Status : INTEGER;
BEGIN
{ Specify the buffer to return the translation } $
Item_List[1].Buffer_Length := SIZE(Translated_Name.Body);
Item_List[1].Item_Code := LNM$_String;
Item_List[1].Buffer_Addr := IADDRESS(Translated_Name.Body);
Item_List[1].Return_Addr := IADDRESS(Translated_Name.Length);
{ Terminate the item list }
Item_List[2].Terminator := 0;
{ Translate the CYGNUS logical name }
Status := $trnlnm(Tabnam := ’LNM$FILE_DEV’, Lognam := ’CYGNUS’, %
Itmlst := Item_List);
IF NOT ODD(Status) &
THEN
LIB$SIGNAL(Status)
ELSE
WRITELN(’CYGNUS is equivalent to ’,Translated_Name);
END.

Pascal Notes
! The Pascal environment file STARLET.PEN defines OpenVMS system
services, data structures and constants. PASCAL$LIB_ROUTINES declares
the LIB$ Run-Time Library routines.
" The structure of an item list entry is defined using a variant record type.
# The VARYING OF CHAR type is a variable-length character string with two
components: a word-integer length and a character string body, which in this
example is 255 bytes long. The VOLATILE attribute is required for variables
that are modified by means other than a direct assignment or as an argument
in a routine call.
$ The functions SIZE and IADDRESS obtain the allocated size of the string
body and the address of the string body and length. The returned length will
be stored into the length field of the varying string Translated_Name, so that
it will appear to be the correct size.

Calling System Services 20–19


Calling System Services
20.5 Program Examples with System Service Calls

% The definition of the SYS$TRNLNM routine in STARLET.PEN contains


specifications of the passing mechanism to be used for each argument; thus, it
is not necessary to specify the mechanism here.
& The IF statement performs a logical test following the function reference to
see if the service completed successfully. If an error or warning occurs during
the service call, the error is signaled.

Example 20–9 System Service Call in VAX MACRO

CYGDES: .ASCID /CYGNUS/ ! ; Descriptor for CYGNUS string


TBLDES: .ASCID /LNM$FILE_DEV/ " ; Logical name table
NAMBUF: .BLKB 255 # ; Output buffer
NAMLEN: .BLKW 1 $ ; Word to receive length
ITEMS: .WORD 255 ; Output buffer length
.WORD LNM$STRING ; Item code
.ADDRESS - ; Output buffer
NAMBUF
.ADDRESS - ; Return length
NAMLEN
.LONG 0 ; List terminator
.
.
.
.ENTRY ORION,0 % ; Routine entry point & mask
$TRNLNM_S - &
TABNAM=TBLDES, -
LOGNAM=CYGDES, -
ITMLST=ITEMS
BLBC R0,ERROR ’ ; Check for error
.
.
.
.END

VAX MACRO Notes


! The input character string descriptor argument is defined using the .ASCID
directive.
" The name of the table to search is defined using the .ASCID directive.
# Enough bytes to hold the output data are allocated for an output character
string argument.
$ The MACRO directive .BLKW reserves a word to hold the output length.
% A routine name and entry mask show the beginning of executable code in a
routine or subroutine.
& A macro name that has the suffix _S or _G calls the service.
You can specify arguments either by keyword (as in this example) or by
positional order. (Keyword names correspond to the names of the arguments
shown in lowercase in the system service format descriptions in the OpenVMS
System Services Reference Manual.) If you omit any optional arguments
(if you accept the defaults), you can omit them completely if you specify
arguments by keyword. If you specify arguments by positional order, however,
you must specify the comma for each missing argument.
Use the number sign ( # ) to indicate a literal value for an argument.

20–20 Calling System Services


Calling System Services
20.5 Program Examples with System Service Calls

’ The BLBC instruction causes a branch to a subroutine named ERROR (not


shown) if the low bit of the condition value returned from the service is clear
(low bit clear = failure or warning). You can use a BSBW instruction to
branch unconditionally to a routine that checks the return status.

Calling System Services 20–21


21
STARLET Structures and Definitions for C
Programmers

This chapter describes the libraries that contain C header files for routines
supplied by the OpenVMS Alpha operating system.

21.1 SYS$STARLET_C.TLB Equivalency to STARLETSD.TLB


The SYS$STARLET_C.TLB file, which was introduced in OpenVMS Alpha
Version 1.0, contains all the .H files that provide STARLET functionality
equivalent to STARLETSD.TLB. The file SYS$STARLET_C.TLB, together
with DECC$RTLDEF.TLB that ships with the Compaq C Compiler,
replaces VAXCDEF.TLB that previously shipped with the VAX C Compiler.
DECC$RTLDEF.TLB contains all the .H files that support the compiler and RTL,
such as STDIO.H.
If you are running an application from a release prior to OpenVMS Alpha Version
1.0, the following differences may require source changes:
• RMS structures
Previously, the RMS structures FAB, NAM, RAB, XABALL, and so forth,
were defined in the appropriate .H files as ‘‘struct RAB {...’’, for example. The
.H files supplied in OpenVMS Alpha Version 1.0 define them as ‘‘struct rabdef
{...’’. To compensate for this difference, lines of the form ‘‘#define RAB rabdef’’
have been added. However, there is one situation where a source change is
required because of this change. If you have a private structure that contains
a pointer to one of these structures and your private structure is defined
(but not used) before the RMS structure has been defined, you will receive
compile-time errors similar to the following:
%CC-E-PASNOTMEM, In this statement, "rab$b_rac" is not a member of "rab".
This error can be avoided by reordering your source file so that the RMS
structure is defined before the private structure. Typically, this involves
moving around ‘‘#include’’ statements.
• LIB (privileged interface) structures
Historically, three structures from LIB (NFBDEF.H, FATDEF.H, and
FCHDEF.H) have been made available as .H files. These files were
shipped as .H files in OpenVMS Alpha Version 1.0 and 1.5 (not in the
new SYS$STARLET_C.TLB). As of OpenVMS Alpha Version 1.0, the file
SYS$LIB_C.TLB, containing all LIB structures and definitions, has been
added. These three .H files are now part of that .TLB and are no longer
shipped separately. Source changes may be required, because no attempt has
been made to preserve any existing anomalies in these files. The structures
and definitions from LIB are for privileged interfaces only and are therefore
subject to change.

STARLET Structures and Definitions for C Programmers 21–1


STARLET Structures and Definitions for C Programmers
21.1 SYS$STARLET_C.TLB Equivalency to STARLETSD.TLB

• Use of ‘‘variant_struct’’ and ‘‘variant_union’’


In the new .H files, ‘‘variant_struct’’ and ‘‘variant_union’’ are always used;
whereas previously some structures used ‘‘struct’’ and ‘‘union’’. Therefore,
the intermediate structure names cannot be specified when referencing fields
within data structures.
For example, the following statement:
AlignFaultItem.PC[0] = DataPtr->afr$r_pc_data_overlay.afr$q_fault_pc[0];
becomes:
AlignFaultItem.PC[0] = DataPtr->afr$q_fault_pc[0];
• Member alignment
Each of the .H files in SYS$STARLET_C.TLB saves and restores the state of
‘‘#pragma member_alignment’’.
• Conventions
The .H files in SYS$STARLET_C.TLB adhere to some conventions that
were only partly followed in VAXCDEF.TLB. All constants (#defines) have
uppercase names. All identifiers (routines, structure members, and so forth)
have lowercase names. Where there is a difference from VAXCDEF.TLB, the
old symbol name is also included for compatibility, but users are encouraged
to follow the new conventions.
• Use of Librarian utility to access the .H files
During installation of OpenVMS Alpha Version 1.0, the contents of
SYS$STARLET_C.TLB are not extracted into the separate .H files. The
Compaq C Compiler accesses these files from within SYS$STARLET_C.TLB,
regardless of the format of the #include statement. If you want to inspect
an individual .H file, you can use the Librarian utility, as in the following
example:
$ LIBRARY /EXTRACT=AFRDEF /OUTPUT=AFRDEF.H SYS$LIBRARY:SYS$STARLET_C.TLB
• Additional .H files included in SYS$STARLET_C.TLB
In addition to the .H files derived from STARLET sources, SYS$STARLET_
C.TLB includes .H files that provide support for POSIX Threads Library, such
as CMA.H.

21.2 NEW STARLET Definitions for C


As of OpenVMS Alpha Version 7.0, SYS$LIBRARY:SYS$STARLET_C.TLB (or
STARLET) provides C function prototypes for system services, as well as new
and enhanced data structure definitions. The new definitions are more consistent
with the OpenVMS C language coding conventions and definitions (typedefs) used
in SYS$LIBRARY:SYS$LIB_C.TLB.
To maintain source compatibility for existing users of STARLET.H, the ‘‘old
style’’ function declarations and definitions are still provided by default. To take
advantage of the new system service function prototypes and type definitions, you
must explicitly enable them.

21–2 STARLET Structures and Definitions for C Programmers


STARLET Structures and Definitions for C Programmers
21.2 NEW STARLET Definitions for C

You can define the _ _NEW_STARLET symbol with a Compaq C command line
qualifier or include the definition directly in your source program. For example:
• Define the _NEW_STARLET symbol with the Compaq C command line
qualifier as follows:
/DEFINE=(__NEW_STARLET=1)
or
• Define the _NEW_STARLET symbol in your C source program before
including the SYS$STARLET_C.TLB header files:
#define __NEW_STARLET 1
#include <starlet.h>
#include <vadef.h>
To see the currently available system service function prototypes in STARLET.H,
you can use the Librarian utility as shown in the following example:
$ LIBRARY/OUTPUT=STARLET.H SYS$LIBRARY:SYS$STARLET_C.TLB/EXTRACT=STARLET
The following example shows a new system service function prototype as it is
defined in STARLET.H:
#pragma __required_pointer_size __long
int sys$expreg_64(
struct _generic_64 *region_id_64,
unsigned __int64 length_64,
unsigned int acmode,
unsigned int flags,
void *(*(return_va_64)),
unsigned __int64 *return_length_64);
#pragma __required_pointer_size __short
For more information about Compaq C pointer size pragmas, see the DEC C
User’s Guide for OpenVMS Systems.
The following source code example shows the sys$expreg_64 function prototype
referenced in a program.

#define __NEW_STARLET 1 /* Enable "New Starlet" features */


#include <starlet.h> /* Declare prototypes for system services */
#include <gen64def.h> /* Define GENERIC_64 type */
#include <vadef.h> /* Define VA$ constants */
#include <ints.h> /* Define 64-bit integer types */
#include <far_pointers.h> /* Define 64-bit pointer types */
{
int status; /* Ubiquitous VMS status value */
GENERIC_64 region = { VA$C_P2 }; /* Expand in "default" P2 region */
VOID_PQ p2_va; /* Returned VA in P2 space */
uint64 length; /* Allocated size in bytes */
extern uint64 page_size; /* Page size in bytes */
status = sys$expreg_64( &region, request_size, 0, 0, &p2_va, &length );
...
}

STARLET Structures and Definitions for C Programmers 21–3


STARLET Structures and Definitions for C Programmers
21.2 NEW STARLET Definitions for C

Table 21–1 lists the data structures that are used by the new function protypes.

Table 21–1 Structures Used by _NEW_STARLET Prototypes


Common Prefix for
Structure Used by Defined by Structure Member
Prototype Header File Names Description
struct _cluevthndl cluevtdef.h cluevthndl$ Cluster event handle
struct _fabdef fabdef.h fab$ File access block
struct _generic_64 gen64def.h gen64$ Generic quadword structure
struct _ieee ieeedef.h ieee$ IEEE Floating point control
structure
1
struct _ile2 iledef.h ile2$ Item list entry 2
1
struct _ile3 iledef.h ile3$ Item list entry 3
struct _iosa iosadef.h iosa$ I/O status area
struct _iosb iosbdef.h iosb$ I/O status block
struct _lksb lksbdef.h lksb$ Lock status block
struct _rabdef rabdef.h rab$ RMS record access block
struct _secid seciddef.h secid$ Global section identifier
struct _va_range va_rangedef.h va_range$ 32-bit virtual address range
1 Useof this structure type is not required by the function prototypes in starlet.h. This structure type is provided as a
convenience and can be used where it is appropriate.

21–4 STARLET Structures and Definitions for C Programmers


Part II
I/O, System and Programming Routines

This part of this second volume describes the I/O operations, and the system and
programming routines used by run-time libraries and system services.
22
Run-Time Library Input/Output Operations

This chapter describes the different I/O programming capabilities provided by the
run-time library and illustrates these capabilities with examples of common I/O
tasks. This chapter contains the following sections:
Section 22.1 describes the input and output operations within a program.
Section 22.2 describes using SYS$INPUT and SYS$OUTPUT.
Section 22.3 describes using LIB$GET_INPUT and LIB$PUT_OUTPUT for
simple user I/O.
Section 22.4 describes using the SMG$ run-time library routines for managing
the appearance of terminal screens.
Section 22.5 describes using screen management input routines and the SYS$QIO
and SYS$QIOW system services to perform special actions.

22.1 Choosing I/O Techniques


The operating system and its compilers provide the following methods for
completing input and output operations within a program:
• DEC Text Processing Utility
• DECforms software
• Program language I/O statements
• OpenVMS Record Management Services (RMS) and Run-Time Library (RTL)
routines
• SYS$QIO and SYS$QIOW system services
• Non-Compaq-supplied device drivers to control the I/O to the device itself
The DEC Text Processing Utility (DECTPU) is a text processor that can be used
to create text editing interfaces. DECTPU has the following features:
• High-level procedure language with several data types, relational operators,
error interception, looping, case language statements, and built-in procedures
• Compiler for the DECTPU procedure language
• Interpreter for the DECTPU procedure language
• Extensible Versatile Editor (EVE) editing interface which, in addition to the
EVE keypad, provides EDT, VT100, WPS, and numeric keypad emulation
In addition, DECTPU offers the following special features:
• Multiple buffers
• Multiple windows
• Multiple subprocesses

Run-Time Library Input/Output Operations 22–1


Run-Time Library Input/Output Operations
22.1 Choosing I/O Techniques

• Text processing in batch mode


• Insert or overstrike text entry
• Free or bound cursor motion
• Learn sequences
• Pattern matching
• Key definition
The method you select for I/O operations depends on the task you want to
accomplish, ease of use, speed, and level of control you want.
The Compaq DECforms for OpenVMS software is a forms management product
for transaction processing. DECforms integrates text and graphics into forms
and menus that application programs use as an interface to users. DECforms
software offers application developers software development tools and a run-time
environment for implementing interfaces.
DECforms software integrates with the Application Control and Management
System (ACMS), a transaction process (TP) monitor that works with other
Compaq commercial applications to provide complete customizable development
and run-time environments for TP applications. An asynchronous call interface to
ACMS allows a single DECforms run-time process to control multiple terminals
simultaneously in a multithreaded way, resulting in an efficient use of memory.
By using the ACMS Remote Access Option, DECforms software can be distributed
to remote CPUs. This technique allows the host CPU to offload forms processing
and distribute it as closely as possible to the end user.
In contrast to OpenVMS RMS, RTLs, SYS$QIOs, and device driver I/O, program
language I/O statements have the slowest speed and lowest level of control, but
they are the easiest to use and are highly portable.
OpenVMS RMS and RTL routines can perform most I/O operations for a high-
level or assembly language program. For information about OpenVMS RMS, see
the OpenVMS Record Management Services Reference Manual.
System services can complete any I/O operation and can access devices not
supported within OpenVMS RMS. See Chapter 23 for a description of using I/O
system services.
Writing a device driver provides the most control over I/O operations, but can
be more complex to implement. For information about device drivers for VAX
systems, see the OpenVMS VAX Device Support Manual. The OpenVMS VAX
Device Support Manual has been archived but is available on the OpenVMS
Documentation CD–ROM.
Several types of I/O operations can be performed within a program, including the
following:
• RTL routines allow you either to read simple input from a user or send simple
output to a user. One RTL routine allows you to specify a string to prompt
for input from the current input device, defined by SYS$INPUT. Another RTL
routine allows you to write a string to the current output device, defined by
SYS$OUTPUT. See Section 22.2 and Section 22.3 for more information.

22–2 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.1 Choosing I/O Techniques

• RTL routines allow you either to read complex input from a user or to
send complex output to a user. By providing an extensive number of screen
management (SMG$) routines, the RTL allows you either to read multiple
lines of input from users or to send complex output to users. The SMG$
routines also allow you to create and modify complicated displays that accept
input and produce output. See Section 22.4 for more information.
• RTL routines allow you to use programming language I/O statements to send
data to and receive data from files. Program language I/O statements call
OpenVMS RMS routines to complete most file I/O. You can also use OpenVMS
RMS directly in your programs for accomplishing file I/O. See Chapter 28 for
more information.
• The SYS$QIO and SYS$QIOW system services allow you to send data to
and from devices with the most flexibility and control. You can use system
services to access devices not supported by your programming language or by
OpenVMS RMS.
You can perform other special I/O actions, such as using interrupts,
controlling echo, handling unsolicited input, using the type-ahead buffer,
using case conversion, and sending sytem broadcast messges, by using
SMG$ routines or, for example, by using SYS$BRKTHRU system service to
broadcast messages. See Section 22.5 for more information.

22.2 Using SYS$INPUT and SYS$OUTPUT


Typically, you set up your program so that the user is the invoker. The user starts
the program either by entering a DCL command associated with the program or
by using the RUN command.

22.2.1 Default Input and Output Devices


The user’s input and output devices are defined by the logical names SYS$INPUT
and SYS$OUTPUT, which are initially set to the values listed in Table 22–1.

Table 22–1 SYS$INPUT and SYS$OUTPUT Values


Logical Name User Mode Equivalence Device or File
SYS$INPUT Interactive Terminal at which the user is logged in
Batch job Data lines following the invocation of the
program
Command procedure Data lines following the invocation of the
program
SYS$OUTPUT Interactive Terminal at which the user is logged in
Batch job Batch log file
Command procedure Terminal at which the user is logged in

Generally, use of SYS$INPUT and SYS$OUTPUT as the primary input and


output devices is recommended. A user of the program can redefine SYS$INPUT
and SYS$OUTPUT to redirect input and output as desired. For example, the
interactive user might redefine SYS$OUTPUT as a file name to save output in a
file rather than display it on the terminal.

Run-Time Library Input/Output Operations 22–3


Run-Time Library Input/Output Operations
22.2 Using SYS$INPUT and SYS$OUTPUT

22.2.2 Reading and Writing to Alternate Devices and External Files


Alternatively, you can design your program to read input from and write output
to a file or a device other than the user’s terminal. Files may be useful for writing
large amounts of data, for writing data that the user might want to save, and for
writing data that can be reused as input. If you use files or devices other than
SYS$INPUT and SYS$OUTPUT, you should provide the names of the files or
devices (best form is to use logical names) and any conventions for their use. You
can specify such information by having the program write it to the terminal, by
creating a help file, or by providing user documentation.

22.3 Working with Simple User I/O


Usually, you can request information from or provide information to the user with
little regard for formatting. For such simple I/O, use either LIB$GET_INPUT
and LIB$PUT_OUTPUT or the I/O statements for your programming language.
To provide complex screen displays for input or output, use the screen
management facility described in Section 22.4.

22.3.1 Default Devices for Simple I/O


The LIB$GET_INPUT and LIB$PUT_OUTPUT routines read from SYS$INPUT
and write to SYS$OUTPUT, respectively. The logical names SYS$INPUT and
SYS$OUTPUT are implicit to the routines, because you need only call the
routine to access the I/O unit (device or file) associated with SYS$INPUT and
SYS$OUTPUT. You cannot use these routines to access an I/O unit other than
the one associated with SYS$INPUT or SYS$OUTPUT.

22.3.2 Getting a Line of Input


A read operation transfers one record from the input unit to a variable or
variables of your choice. At a terminal, the user ends a record by pressing a
terminator. The terminators are the ASCII characters NUL through US (0
through 31) except for LF, VT, FF, TAB, and BS. The usual terminator is CR
(carriage return), which is generated by pressing the Return key.
If you are reading character data, LIB$GET_INPUT is a simple way of prompting
for and reading the data. If you are reading noncharacter data, programming
language I/O statements are preferable since they allow you to translate the data
to a format of your choice.
For example, Fortran offers the ACCEPT statement, which reads data from
SYS$INPUT, and the READ statement, which reads data from an I/O unit of your
choice.
Make sure the variables that you specify can hold the largest number of
characters the user of your program might enter, unless you want to truncate the
input deliberately. Overflowing the input variable using LIB$GET_INPUT causes
the fatal error LIB$_INPSTRTRU (defined in $LIBDEF); overflowing the input
variable using language I/O statements may not cause an error but does truncate
your data.
LIB$GET_INPUT places the characters read in a variable of your choice. You
must define the variable type as a character. Optionally, LIB$GET_INPUT places
the number of characters read in another variable of your choice. For input at a
terminal, LIB$GET_INPUT optionally writes a prompt before reading the input.
The prompt is suppressed automatically for an operation not taking place at a
terminal.

22–4 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.3 Working with Simple User I/O

Example 22–1 uses LIB$GET_INPUT to read a line of input.

Example 22–1 Reading a Line of Data


INTEGER*4 STATUS,
2 LIB$GET_INPUT
INTEGER*2 INPUT_SIZE
CHARACTER*512 INPUT
STATUS = LIB$GET_INPUT (INPUT, ! Input value
2 ’Input value: ’, ! Prompt (optional)
2 INPUT_SIZE) ! Input size (optional)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

22.3.3 Getting Several Lines of Input


The usual technique for obtaining a variable number of input records—either
values for which you are prompting or data records from a file—is to read and
process records until the end-of-file. End-of-file means one of the following:
• Terminal—The user has pressed Ctrl/Z. To ensure that the convention is
followed, you might first write a message telling the user to press Ctrl/Z to
terminate the input sequence.
• Command procedure—The end of a sequence of data lines has been reached.
That is, a sequence of data lines ends at the next DCL command (a line in
the procedure beginning with a dollar sign [$]) or at the end of the command
procedure file.
• File—The end of an actual file has been reached.
Process the records in a loop (one record per iteration) and terminate the loop
on end-of-file. LIB$GET_INPUT returns the error RMS$_EOF (defined in
$RMSDEF) when end-of-file occurs.
Example 22–2 uses a Fortran READ statement in a loop to read a sequence of
integers from SYS$INPUT.

Example 22–2 Reading a Varying Number of Input Records


! Return status and error codes
INTEGER STATUS,
2 IOSTAT,
3 STATUS_OK,
4 IOSTAT_OK
PARAMETER (STATUS_OK = 1,
2 IO_OK = 0)
INCLUDE ’($FORDEF)’
! Data record read on each iteration
INTEGER INPUT_NUMBER
! Accumulated data records
INTEGER STORAGE_COUNT,
2 STORAGE_MAX
PARAMETER (STORAGE_MAX = 255)
INTEGER STORAGE_NUMBER (STORAGE_MAX)

(continued on next page)

Run-Time Library Input/Output Operations 22–5


Run-Time Library Input/Output Operations
22.3 Working with Simple User I/O

Example 22–2 (Cont.) Reading a Varying Number of Input Records


! Write instructions to interactive user
TYPE *,
2 ’Enter values below. Press CTRL/Z when done.’
! Get first input value
WRITE (UNIT=*,
2 FMT=’(A,$)’) ’ Input value: ’
READ (UNIT=*,
2 IOSTAT=IOSTAT,
2 FMT=’(BN,I)’) INPUT_NUMBER
IF (IOSTAT .EQ. IO_OK) THEN
STATUS = STATUS_OK
ELSE
CALL ERRSNS (,,,,STATUS)
END IF
! Process each input value until end-of-file
DO WHILE ((STATUS .NE. FOR$_ENDDURREA) .AND.
(STORAGE_COUNT .LT. STORAGE_MAX))
! Keep repeating on conversion error
DO WHILE (STATUS .EQ. FOR$_INPCONERR)
WRITE (UNIT=*,
2 FMT=’(A,$)’) ’ Try again: ’
READ (UNIT=*,
2 IOSTAT=IOSTAT,
2 FMT=’(BN,I)’) INPUT_NUMBER
IF (IOSTAT .EQ. IO_OK) THEN
STATUS = STATUS_OK
ELSE
CALL ERRSNS (,,,,STATUS)
END IF
END DO
! Continue if end-of-file not entered
IF (STATUS .NE. FOR$_ENDDURREA) THEN
! Status check on last read
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Store input numbers in input array
STORAGE_COUNT = STORAGE_COUNT + 1
STORAGE_NUMBER (STORAGE_COUNT) = INPUT_NUMBER
! Get next input value
WRITE (UNIT=*,
2 FMT=’(A,$)’) ’ Input value: ’
READ (UNIT=*,
2 IOSTAT=IOSTAT,
2 FMT=’(BN,I)’) INPUT_NUMBER
IF (IOSTAT .EQ. IO_OK) THEN
STATUS = STATUS_OK
ELSE
CALL ERRSNS (,,,,STATUS)
END IF
END IF
END DO

22.3.4 Writing Simple Output


You can use LIB$PUT_OUTPUT to write character data. If you are writing
noncharacter data, programming language I/O statements are preferable because
they allow you to translate the data to a format of your choice.

22–6 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.3 Working with Simple User I/O

LIB$PUT_OUTPUT writes one record of output to SYS$OUTPUT. Typically,


you should avoid writing records that exceed the device width. The width of
a terminal is 80 or 132 characters, depending on the setting of the physical
characteristics of the device. The width of a line printer is 132 characters. If your
output record exceeds the width of the device, the excess characters are either
truncated or wrapped to the next line, depending on the setting of the physical
characteristics.
You must define a value (a variable, constant, or expression) to be written. The
value must be expressed in characters. You should specify the exact number of
characters being written and not include the trailing portion of a variable.
The following example writes a character expression to SYS$OUTPUT:
INTEGER*4 STATUS,
2 LIB$PUT_OUTPUT
CHARACTER*40 ANSWER
INTEGER*4 ANSWER_SIZE
.
.
.
STATUS = LIB$PUT_OUTPUT (’Answer: ’ // ANSWER (1:ANSWER_SIZE))
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

22.4 Working with Complex User I/O


The following sections present Compaq DECwindows Motif for OpenVMS
(DECwindows Motif), and the SMG$ run-time library routines that enable
complex screen display I/O.

22.4.1 Compaq DECwindows Motif


The Compaq DECwindows Motif environment provides a consistent user
interface for developing software applications. It also includes an extensive
set of programming libraries and tools. The following Compaq DECwindows
Motif software allows you to build a graphical user interface:
• Toolkit composed on graphical user interface objects, such as widgets and
gadgets. Widgets provide advanced programming capabilities that permit you
to create graphic applications easily; gadgets, similar to widgets, require less
memory to create labels, buttons, and separators.
• Language to describe visual aspects of objects, such as menus, labels, and
forms, and to specify changes resulting from user interaction.
• OSF/Motif Window Manager to allow you to customize the interface.
Compaq DECwindows Motif environment also makes available the
LinkWorks services for creating, managing, and traversing informational
links between different application-specific data. Along with the LinkWorks
Manager application, LinkWorks services help organize information into
a hyperinformation environment. LinkWorks Developer’s Tools provide
a development environment for creating, modifying, and maintaining
hyperapplications.

Run-Time Library Input/Output Operations 22–7


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

22.4.1.1 DECwindows Server Height or Width Exceeding 32767 (VAX Only)


On OpenVMS VAX systems, when an X application sends the display server
a width or height greater than 32767, the application may terminate with a
BadValue error similar to the following:
X error event received from server: BadValue (integer parameter out of
range for operation)
Major opcode of failed request: 61 (X_ClearArea)
Value in failed request: 0xffff****
Serial number of failed request: ###
Current serial number in output stream: ###
The following calls can cause this problem:
CopyArea( )
CreateWindow ( )
PutImage( )
GetImage( )
CopyPlane( )
ClearArea( )
This is due to the width and height being defined as a signed word by the display
server when it should be defined as an unsigned word (CARD16) that allows for
values up to 65536.
To modify the default operation, perform the following steps:
1. Set the logical name DECW$CARD16_VALIDATE to TRUE as follows:

$DEFINE/TABLE=DECW$SERVER0_TABLE DECW$CARD16_VALIDATE TRUE


2. Exit the session and log back in.
Exiting the session causes the display server to reset using the new value
of the logical name DECW$CARD16_VALIDATE. The server will now accept
values that are greater than 32767 without generating an error.
To make this a permanent change, add the command from step 1 to the file
SYS$MANAGER:DECW$PRIVATE_SERVER_SETUP.COM.
22.4.1.2 SET DISPLAY Used to Create WSA Pseudo Workstation Devices
When creating WSA pseudo workstation devices using the SET DISPLAY
command, be careful not to create WSA devices that are never destroyed. For
example, this DCL command procedure is wrong:

$LOOP:
$ SET DISPLAY/CREATE/NODE=remote
$ RUN SYS$SYSTEM:DECW$CLOCK
$ IF $STATUS THEN GOTO DONE
$ WAIT 0:0:5
$ GOTO LOOP
$DONE:
If the clock cannot be started for some reason, one WSA device will be created for
each failed attempt. These WSA devices will use up non-paged dynamic memory,
and eventually the process will exceed its BYTLM quota and enter a resource
wait state (if resource waiting is enabled, as it is by default).

22–8 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

A better version of this command procedure is the following:

$ SET DISPLAY/CREATE/NODE=remote
$LOOP:
$ RUN SYS$SYSTEM:DECW$CLOCK
$ IF $STATUS THEN GOTO DONE
$ WAIT 0:0:5
$ GOTO LOOP
$DONE:
$ SET DISPLAY/DELETE ’F$TRNLNM("DECW$DISPLAY")’
The SET DISPLAY/DELETE command deletes the WSA device that was created
at the beginning of the command procedure; the logical name DECW$DISPLAY
contains the name of the WSA device that was created.
For information about using OpenVMS Compaq DECwindows Motif, see
the Overview of DECwindows Motif for OpenVMS Documentation and the
DECwindows Motif Guide to Application Programming.

22.4.2 SMG$ Run-Time Routines


The SMG$ run-time library routines provide a simple, device-independent
interface for managing the appearance of the terminal screen. The SMG$
routines are primarily for use with video terminals; however, they can be used
with files or hardcopy terminals.
To use the screen management facility for output, do the following:
1. Create a pasteboard—A pasteboard is a logical, two-dimensional area on
which you place virtual displays. Use the SMG$CREATE_PASTEBOARD
routine to create a pasteboard, and associate it with a physical device. When
you refer to the pasteboard, SMG performs the necessary I/O operation to the
device.
2. Create a virtual display—A virtual display is a logical, two-dimensional area
in which you place the information to be displayed. Use the SMG$CREATE_
VIRTUAL_DISPLAY routine to create a virtual display.
3. Paste virtual displays to the pasteboard—To make a virtual display visible,
map (or paste) it to the pasteboard using the SMG$PASTE_VIRTUAL_
DISPLAY routine. You can reference a virtual display regardless of whether
that display is currently pasted to a pasteboard.
4. Create a viewport for a virtual display—A viewport is a rectangular viewing
area that can be moved around on a buffer to view different pieces of the
buffer. The viewport is associated with a virtual display.

Run-Time Library Input/Output Operations 22–9


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–3 associates a pasteboard with the terminal, creates a virtual display
the size of the terminal screen, and pastes the display to the pasteboard. When
text is written to the virtual display, the text appears on the terminal screen.

Example 22–3 Associating a Pasteboard with a Terminal


.
.
.
! Screen management control structures
INTEGER*4 PBID, ! Pasteboard ID
2 VDID, ! Virtual display ID
2 ROWS, ! Rows on screen
2 COLS ! Columns on screen
! Status variable and routines called as functions
INTEGER*4 STATUS,
2 SMG$CREATE_PASTEBOARD,
2 SMG$CREATE_VIRTUAL_DISPLAY,
2 SMG$PASTE_VIRTUAL_DISPLAY
! Set up SYS$OUTPUT for screen management
! and get the number of rows and columns on the screen
STATUS = SMG$CREATE_PASTEBOARD (PBID, ! Return value
2 ’SYS$OUTPUT’,
2 ROWS, ! Return value
2 COLUMNS) ! Return value
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Create virtual display that pastes to the full screen size
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (ROWS,
2 COLUMNS,
2 VDID) ! Return value
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Paste virtual display to pasteboard
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (VDID,
2 PBID,
2 1, ! Starting at row 1 and
2 1) ! column 1 of the screen
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.

To use the SMG$ routines for input, you associate a virtual keyboard with a
physical device or file using the SMG$CREATE_VIRTUAL_KEYBOARD routine.
The SMG$ input routines can be used alone or with the output routines. This
section assumes that you are using the input routines with the output routines.
Section 22.5 describes how to use the input routines without the output routines.
The screen management facility keeps an internal representation of the screen
contents; therefore, it is important that you do not mix SMG$ routines with
other forms of terminal I/O. The following subsections contain guidelines for
using most of the SMG$ routines; for more details, see the OpenVMS RTL Screen
Management (SMG$) Manual.

22.4.3 Pasteboards
Use the SMG$CREATE_PASTEBOARD routine to create a pasteboard and
associate it with a physical device. SMG$CREATE_PASTEBOARD returns
a unique pasteboard identification number; use that number to refer to the
pasteboard in subsequent calls to SMG$ routines. After associating a pasteboard
with a device, your program references only the pasteboard. The screen

22–10 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

management facility performs all necessary operations between the pasteboard


and the physical device. Example 22–4 creates a pasteboard.

Example 22–4 Creating a Pasteboard


STATUS = SMG$CREATE_PASTEBOARD (PBID, ROWS, COLUMNS)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

22.4.3.1 Erasing a Pasteboard


When you create a pasteboard, the screen management facility clears the screen
by default. To clear the screen yourself, invoke the SMG$ERASE_PASTEBOARD
routine. Any virtual displays associated with the pasteboard are removed from
the screen, but their contents in memory are not affected. The following example
erases the screen:
STATUS = SMG$ERASE_PASTEBOARD (PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
22.4.3.2 Deleting a Pasteboard
Invoking the SMG$DELETE_PASTEBOARD routine deletes a pasteboard,
making the screen unavailable for further pasting. The optional second argument
of the SMG$DELETE_PASTEBOARD routine allows you to indicate whether the
routine clears the screen (the default) or leaves it as is. The following example
deletes a pasteboard and clears the screen:
STATUS = SMG$DELETE_PASTEBOARD (PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
By default, the screen is erased when you create a pasteboard. Generally, you
should erase the screen at the end of a session.
22.4.3.3 Setting Screen Dimensions and Background Color
The SMG$CHANGE_PBD_CHARACTERISTICS routine sets the dimensions of
the screen and its background color. You can also use this routine to retrieve
dimensions and background color. To get more detailed information about the
physical device, use the SMG$GET_PASTEBOARD_ATTRIBUTES routine.
Example 22–5 changes the screen width to 132 and the background to white,
then restores the original width and background before exiting.

Example 22–5 Modifying Screen Dimensions and Background Color


.
.
.
INTEGER*4 WIDTH,
2 COLOR
INCLUDE ’($SMGDEF)’

(continued on next page)

Run-Time Library Input/Output Operations 22–11


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–5 (Cont.) Modifying Screen Dimensions and Background Color


! Get current width and background color
STATUS = SMG$CHANGE_PBD_CHARACTERISTICS (PBID,,
2 WIDTH,,,,
2 COLOR)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Change width and background color
STATUS = SMG$CHANGE_PBD_CHARACTERISTICS (PBID,
2 132,,,,
2 SMG$C_COLOR_WHITE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
! Restore width and background color
STATUS = SMG$CHANGE_PBD_CHARACTERISTICS (PBID,
2 WIDTH,,,,
2 COLOR)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

22.4.4 Virtual Displays


You write to virtual displays, which are logically configured as rectangles, by
using the SMG$ routines. The dimensions of a virtual display are designated
vertically as rows and horizontally as columns. A position in a virtual display is
designated by naming a row and a column. Row and column numbers begin at 1.
22.4.4.1 Creating a Virtual Display
Use the SMG$CREATE_VIRTUAL_DISPLAY routine to create a virtual
display. SMG$CREATE_VIRTUAL_DISPLAY returns a unique virtual display
identification number; use that number to refer to the virtual display.
Optionally, you can use the fifth argument of SMG$CREATE_VIRTUAL_
DISPLAY to specify one or more of the following video attributes: blinking,
bolding, reversing background, and underlining. All characters written to that
display will have the specified attribute unless you indicate otherwise when
writing text to the display. The following example makes everything written to
the display HEADER_VDID appear bold by default:
INCLUDE ’($SMGDEF)’
.
.
.
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (1, ! Rows
2 80, ! Columns
2 HEADER_VDID,,
2 SMG$M_BOLD)
You can border a virtual display by specifying the fourth argument when you
invoke SMG$CREATE_VIRTUAL_DISPLAY. You can label the border with the
routine SMG$LABEL_BORDER. If you use a border, you must leave room for it:
a border requires two rows and two columns more than the size of the display.
The following example places a labeled border around the STATS_VDID display.
As pasted, the border occupies rows 2 and 13 and columns 1 and 57.

22–12 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

STATUS = SMG$CREATE_VIRTUAL_DISPLAY (10, ! Rows


2 55, ! Columns
2 STATS_VDID,
2 SMG$M_BORDER)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$LABEL_BORDER (STATS_VDID,
2 ’statistics’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (STATS_VDID,
2 PBID,
2 3, ! Row
2 2) ! Column
22.4.4.2 Pasting Virtual Displays
To make a virtual display visible, paste it to a pasteboard using the
SMG$PASTE_VIRTUAL_DISPLAY routine. You position the virtual display
by specifying which row and column of the pasteboard should contain the upper
left corner of the display. Example 22–6 defines two virtual displays and pastes
them to one pasteboard.

Example 22–6 Defining and Pasting a Virtual Display


.
.
.
INCLUDE ’($SMGDEF)’
INTEGER*4 PBID,
2 HEADER_VDID,
2 STATS_VDID
INTEGER*4 STATUS,
2 SMG$CREATE_PASTEBOARD,
2 SMG$CREATE_VIRTUAL_DISPLAY,
2 SMG$PASTE_VIRTUAL_DISPLAY
! Create pasteboard for SYS$OUTPUT
STATUS = SMG$CREATE_PASTEBOARD (PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Header pastes to first rows of screen
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (3, ! Rows
2 78, ! Columns
2 HEADER_VDID, ! Name
2 SMG$M_BORDER) ! Border
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (HEADER_VDID,
2 PBID,
2 2, ! Row
2 2) ! Column
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

(continued on next page)

Run-Time Library Input/Output Operations 22–13


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–6 (Cont.) Defining and Pasting a Virtual Display


! Statistics area pastes to rows 5 through 15,
! columns 2 through 56
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (10, ! Rows
2 55, ! Columns
2 STATS_VDID, ! Name
2 SMG$M_BORDER) ! Border
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (STATS_VDID,
2 PBID,
2 5, ! Row
2 2) ! Column
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.

Figure 22–1 shows the screen that results from Example 22–6.

Figure 22–1 Defining and Pasting Virtual Displays

ZK−2044−GE

You can paste a single display to any number of pasteboards. Any time you
change the display, all pasteboards containing the display are automatically
updated.
A pasteboard can hold any number of virtual displays. You can paste virtual
displays over one another to any depth, occluding the displays underneath. The
displays underneath are only occluded to the extent that they are covered; that
is, the parts not occluded remain visible on the screen. (In Figure 22–2, displays
1 and 2 are partially occluded.) When you unpaste a virtual display that occludes
another virtual display, the occluded part of the display underneath becomes
visible again.
You can find out whether a display is occluded by using the SMG$CHECK_FOR_
OCCLUSION routine. The following example pastes a two-row summary display
over the last two rows of the statistics display, if the statistics display is not
already occluded. If the statistics display is occluded, the example assumes that
it is occluded by the summary display and unpastes the summary display, making
the last two rows of the statistics display visible again.

22–14 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

STATUS = SMG$CHECK_FOR_OCCLUSION (STATS_VDID,


2 PBID,
2 OCCLUDE_STATE)
! OCCLUDE_STATE must be defined as INTEGER*4
IF (OCCLUDE_STATE) THEN
STATUS = SMG$UNPASTE_VIRTUAL_DISPLAY (SUM_VDID,
2 PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
ELSE
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (SUM_VDID,
2 PBID,
2 11,
2 2)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
END IF
22.4.4.3 Rearranging Virtual Displays
Pasted displays can be rearranged by moving or repasting.
• Moving—To move a display, use the SMG$MOVE_VIRTUAL_DISPLAY
routine. The following example moves display 2. Figure 22–2 shows the
screen before and after the statement executes.
STATUS = SMG$MOVE_VIRTUAL_DISPLAY (VDID,
2 PBID,
2 5,
2 10)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))

Figure 22–2 Moving a Virtual Display

Before Moving Display 2 After Moving Display 2

11 1
aaaaaaaaa aaaaaaaaa
aaaaaaaaa aaaaaaaaa
2
aaaaaaaaa aaaaaaaaa 2
aaaaaaaaa
bbbbbbbb bbbbbbbb
aaaaaaaaa
aaaaaaaaa
bbbbbbbb bbbbbbbb
aaaaaaaaa
bbbbbbbb 3 3
bbbbbbbb
bbbbbbbbccccccccc ccccccccc
bbbbbbbb
bbbbbbbbccccccccc ccccccccc
bbbbbbbb
ccccccccc ccccccccc
ccccccccc ccccccccc
ccccccccc ccccccccc

ZK−2045−GE

• Repasting—To repaste a display, use the SMG$REPASTE_VIRTUAL_


DISPLAY routine. The following example repastes display 2. Figure 22–3
shows the screen before and after the statement executes.
STATUS = SMG$REPASTE_VIRTUAL_DISPLAY (VDID,
2 PBID,
2 4,
2 4)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))

Run-Time Library Input/Output Operations 22–15


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Figure 22–3 Repasting a Virtual Display

Before Repasting Display 2 After Repasting Display 2

11 1
aaaaaaaaa aaaaaaaaa
aaaaaaaaa aaaaaaaaa
2
aaaaaaaaa aaaaaaaaa 2
aaaaaaaaa
bbbbbbbb bbbbbbbb
aaaaaaaaa
bbbbbbbb
aaaaaaaaa bbbbbbbb
aaaaaaaaa
bbbbbbbb 3 3
bbbbbbbb
bbbbbbbbccccccccc bbbbbbbb cc
bbbbbbbbccccccccc bbbbbbbb cc
ccccccccc cc
ccccccccc ccccccccc
ccccccccc ccccccccc

ZK−2046−GE

You can obtain the pasting order of the virtual displays using SMG$LIST_
PASTING_ORDER. This routine returns the identifiers of all the virtual displays
pasted to a specified pasteboard.
22.4.4.4 Removing Virtual Displays
You can remove a virtual display from a pasteboard in a number of different
ways:
• Erase a virtual display—Invoking SMG$UNPASTE_VIRTUAL_DISPLAY
erases a virtual display from the screen but retains its contents in memory.
The following example erases the statistics display:
STATUS = SMG$UNPASTE_VIRTUAL_DISPLAY (STATS_VDID,
2 PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
• Delete a virtual display—Invoking SMG$DELETE_VIRTUAL_DISPLAY
removes a virtual display from the screen and removes its contents from
memory. The following example deletes the statistics display:
STATUS = SMG$DELETE_VIRTUAL_DISPLAY (STATS_VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
• Delete several virtual displays—Invoking SMG$POP_VIRTUAL_DISPLAY
removes a specified virtual display and any virtual displays pasted after that
display from the screen and removes the contents of those displays from
memory. The following example ‘‘pops’’ display 2. Figure 22–4 shows the
screen before and after popping. (Note that display 3 is deleted because it
was pasted after display 2, and not because it is occluding display 2.)
STATUS = SMG$POP_VIRTUAL_DISPLAY (STATS_VDID,
2 PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

22–16 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Figure 22–4 Popping a Virtual Display

Before Popping Display 2 After Popping Display 2

11 1
aaaaaaaaa aaaaaaaaa
aaaaaaaaa aaaaaaaaa
2
aaaaaaaaa aaaaaaaaa
aaaaaaaaa
bbbbbbbb aaaaaaaaa
bbbbbbbb
aaaaaaaaa aaaaaaaaa
bbbbbbbb 3
bbbbbbbbccccccccc
bbbbbbbbccccccccc
ccccccccc
ccccccccc
ccccccccc

ZK−2047−GE

22.4.4.5 Modifying a Virtual Display


The screen management facility provides several routines for modifying the
characteristics of an existing virtual display:
• SMG$CHANGE_VIRTUAL_DISPLAY—Changes the size, video attributes, or
border of a display
• SMG$CHANGE_RENDITION—Changes the video attributes of a portion of a
display
• SMG$MOVE_TEXT—Moves text from one virtual display to another
The following example uses SMG$CHANGE_VIRTUAL_DISPLAY to change the
size of the WHOOPS display to five rows and seven columns and to turn off all of
the display’s default video attributes. If you decrease the size of a display that is
on the screen, any characters in the excess area are removed from the screen.
STATUS = SMG$CHANGE_VIRTUAL_DISPLAY (WHOOPS_VDID,
2 5, ! Rows
2 7,, ! Columns
2 0) ! Video attributes off
The following example uses SMG$CHANGE_RENDITION to direct attention to
the first 20 columns of the statistics display by setting the reverse video attribute
to the complement of the display’s default setting for that attribute:
STATUS = SMG$CHANGE_RENDITION (STATS_VDID,
2 1, ! Row
2 1, ! Column
2 10, ! Number of rows
2 20, ! Number of columns
2 , ! Video-set argument
2 SMG$M_REVERSE) ! Video-comp argument
2

Run-Time Library Input/Output Operations 22–17


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

SMG$CHANGE_RENDITION uses three sets of video attributes to determine the


attributes to apply to the specified portion of the display: ( 1 ) the display’s default
video attributes, ( 2 ) the attributes specified by the rendition-set argument of
SMG$CHANGE_RENDITION, and ( 3 ) the attributes specified by the rendition-
complement argument of SMG$CHANGE_RENDITION. Table 22–2 shows the
result of each possible combination.

Table 22–2 Setting Video Attributes


rendition-set rendition-complement Result
off off Uses display default
on off Sets attribute
off on Uses the complement of display
default
on on Clears attribute

In the preceding example, the reverse video attribute is set in the rendition-
complement argument but not in the rendition-set argument, thus specifying
that SMG$CHANGE_RENDITION use the complement of the display’s default
setting to ensure that the selected portion of the display is easily seen.
Note that the resulting attributes are based on the display’s default attributes,
not its current attributes. If you use SMG$ routines that explicitly set video
attributes, the current attributes of the display may not match its default
attributes.
22.4.4.6 Using Spawned Subprocesses
You can create a spawned subprocess directly with an SMG$ routine to
allow execution of a DCL command from an application. Only one spawned
subprocess is allowed per virtual display. Use the following routines to work with
subprocesses:
• SMG$CREATE_SUBPROCESS—Creates a DCL spawned subprocess and
associates it with a virtual display.
• SMG$EXECUTE_COMMAND—Allows execution of a specified command in
the created spawned subprocess by using mailboxes. Some restrictions apply
to specifying the following commands:
SPAWN, GOTO, or LOGOUT cannot be used and will result in
unpredictable results.
Single-character commands such as Ctrl/C have no effect. You can
signal an end-of-file (that is, press Ctrl/Z) command by setting the flags
argument.
A dollar sign ($) must be specified as the first character of any DCL
command.
• SMG$DELETE_SUBPROCESS—Deletes the subprocess created by
SMG$CREATE_SUBPROCESS.

22–18 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

22.4.5 Viewports
Viewports allow you to view different pieces of a virtual display by moving a
rectangular area around on the virtual display. Only one viewport is allowed for
each virtual display. Once you have associated a viewport with a virtual display,
the only part of the virtual display that is viewable is contained in the viewport.
The SMG$ routines for working with viewports include the following:
• SMG$CREATE_VIEWPORT—Creates a viewport and associates it with
a virtual display. You must create the virtual display first. To view the
viewport, you must paste the virtual display first with SMG$PASTE_
VIRTUAL_DISPLAY.
• SMG$SCROLL_VIEWPORT—Scrolls the viewport within the virtual display.
If you try to move the viewport outside of the virtual display, the viewport is
truncated to stay within the virtual display. This routine allows you to specify
the direction and extent of the scroll.
• SMG$CHANGE_VIEWPORT—Moves the viewport to a new starting location
and changes the size of the viewport.
• SMG$DELETE_VIEWPORT—Deletes the viewport and dissociates it from the
virtual display. The viewport is automatically unpasted. The virtual display
associated with the viewport remains intact. You can unpaste a viewport
without deleting it by using SMG$UNPASTE_VIRTUAL_DISPLAY.

22.4.6 Writing Text to Virtual Display


The SMG$ output routines allow you to write text to displays and to delete or
modify the existing text of a display. Remember that changes to a virtual display
are visible only if the virtual display is pasted to a pasteboard.
22.4.6.1 Positioning the Cursor
Each virtual display has its own logical cursor position. You can control the
position of the cursor in a virtual display with the following routines:
• SMG$HOME_CURSOR—Moves the cursor to a corner of the virtual display.
The default corner is the upper left corner, that is, row 1, column 1 of the
display.
• SMG$SET_CURSOR_ABS—Moves the cursor to a specified row and column.
• SMG$SET_CURSOR_REL—Moves the cursor to offsets from the current
cursor position. A negative value means up (rows) or left (columns). A value
of 0 means no movement.
In addition, many routines permit you to specify a starting location other than
the current cursor position for the operation.
The SMG$RETURN_CURSOR_POS routine returns the row and column of the
current cursor position within a virtual display. You do not have to write special
code to track the cursor position.
Typically, the physical cursor is at the logical cursor position of the most recently
written-to display. If necessary, you can use the SMG$SET_PHYSICAL_CURSOR
routine to set the physical cursor location.

Run-Time Library Input/Output Operations 22–19


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

22.4.6.2 Writing Data Character by Character


If you are writing character by character (see Section 22.4.6.3 for line-oriented
output), you can use three routines:
• SMG$DRAW_CHAR—Puts one line-drawing character on the screen at a
specified position. It does not change the cursor position.
• SMG$PUT_CHARS—Puts one or more characters on the screen at a specified
position, with the option of one video attribute.
• SMG$PUT_CHARS_MULTI—Puts several characters on the screen at a
specified position, with multiple video attributes.
These routines are simple and precise. They place exactly the specified characters
on the screen, starting at a specified position in a virtual display. Anything
currently in the positions written-to is overwritten; no other positions on the
screen are affected. Convert numeric data to character data with language I/O
statements before invoking SMG$PUT_CHARS.
The following example converts an integer to a character string and places it at a
designated position in a virtual display:
CHARACTER*4 HOUSE_NO_STRING
INTEGER*4 HOUSE_NO,
2 LINE_NO,
2 STATS_VDID
.
.
.
WRITE (UNIT=HOUSE_NO_STRING,
2 FMT=’(I4)’) HOUSE_NO
STATUS = SMG$PUT_CHARS (STATS_VDID,
2 HOUSE_NO_STRING,
2 LINE_NO, ! Row
2 1) ! Column
Note that the converted integer is right-justified from column 4 because the
format specification is I4 and the full character string is written. To left-justify
a converted number, you must locate the first nonblank character and write a
substring starting with that character and ending with the last character.
Inserting and Overwriting Text
To insert characters rather than overwrite the current contents of the screen, use
the routine SMG$INSERT_CHARS. Existing characters at the location written to
are shifted to the right. Characters pushed out of the display are truncated; no
wrapping occurs and the cursor remains at the end of the last character inserted.
Specifying Double-Size Characters
In addition to the preceding routines, you can use SMG$PUT_CHARS_WIDE to
write characters to the screen in double width or SMG$PUT_CHARS_HIGHWIDE
to write characters to the screen in double height and double width. When you
use these routines, you must allot two spaces for each double-width character on
the line and two lines for each line of double-height characters. You cannot mix
single-and double-size characters on a line.
All the character routines provide rendition-set and rendition-complement
arguments, which allow you to specify special video attributes for the characters
being written. SMG$PUT_CHARS_MULTI allows you to specify more than one
video attribute at a time. The explanation of the SMG$CHANGE_RENDITION
routine in Section 22.4.4.5 discusses how to use rendition-set and rendition-
complement arguments.

22–20 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

22.4.6.3 Writing Data Line by Line


The SMG$PUT_LINE and SMG$PUT_LINE_MULTI routines write lines to
virtual displays one line after another. If the display area is full, it is scrolled.
You do not have to keep track of which line you are on. All routines permit you to
scroll forward (up); SMG$PUT_LINE and SMG$PUT_LINE_MULTI permit you
to scroll backward (down) as well. SMG$PUT_LINE permits spacing other than
single spacing.
Example 22–7 writes lines from a buffer to a display area. The output is scrolled
forward if the buffer contains more lines than the display area.

Example 22–7 Scrolling Forward Through a Display


INTEGER*4 BUFF_COUNT,
2 BUFF_SIZE (4096)
CHARACTER*512 BUFF (4096)
.
.
.
DO I = 1, BUFF_COUNT
STATUS = SMG$PUT_LINE (VDID,
2 BUFF (I) (1:BUFF_SIZE (I)))
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
END DO
Example 22–8 scrolls the output backward.

Example 22–8 Scrolling Backward Through a Display


DO I = BUFF_COUNT, 1, -1
STATUS = SMG$PUT_LINE (VDID,
2 BUFF (I) (1:BUFF_SIZE (I)),
2 SMG$M_DOWN)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
END DO

Cursor Movement and Scrolling


To maintain precise control over cursor movement and scrolling, you can write
with SMG$PUT_CHARS and scroll explicitly with SMG$SCROLL_DISPLAY_
AREA. SMG$PUT_CHARS leaves the cursor after the last character written
and does not force scrolling; SMG$SCROLL_DISPLAY_AREA scrolls the current
contents of the display forward, backward, or sideways without writing to the
display. To restrict the scrolling region to a portion of the display area, use the
SMG$SET_DISPLAY_SCROLL_REGION routine.
Inserting and Overwriting Text
To insert text rather than overwrite the current contents of the screen, use the
SMG$INSERT_LINE routine. Existing lines are shifted up or down to open space
for the new text. If the text is longer than a single line, you can specify whether
or not you want the excess characters to be truncated or wrapped.
Using Double-Width Characters
In addition, you can use SMG$PUT_LINE_WIDE to write a line of text to the
screen using double-width characters. You must allot two spaces for each double-
width character on the line. You cannot mix single- and double-width characters
on a line.

Run-Time Library Input/Output Operations 22–21


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Specifying Special Video Attributes


All line routines provide rendition-set and rendition-complement arguments,
which allow you to specify special video attributes for the text being written.
SMG$PUT_LINE_MULTI allows you to specify more than one video attribute
for the text. The explanation of the SMG$CHANGE_RENDITION routine
in Section 22.4.4.5 discusses how to use the rendition-set and rendition-
complement arguments.
22.4.6.4 Drawing Lines
The routine SMG$DRAW_LINE draws solid lines on the screen. Appropriate
corner and crossing marks are drawn when lines join or intersect. The routine
SMG$DRAW_CHARACTER draws a single character. You can also use the
routine SMG$DRAW_RECTANGLE to draw a solid rectangle. Suppose that you
want to draw an object such as that shown in Figure 22–5 in the statistics display
area (an area of 10 rows by 55 columns).

Figure 22–5 Statistics Display

ZK−2048−GE

Example 22–9 shows how you can create a statistics display using SMG$DRAW_
LINE and SMG$DRAW_RECTANGLE.

Example 22–9 Creating a Statistics Display


STATUS = SMG$CREATE_VIRTUAL_DISPLAY (10,
2 55,
2 STATS_VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Draw rectangle with upper left corner at row 1 column 1
! and lower right corner at row 10 column 55
STATUS =SMG$DRAW_RECTANGLE (STATS_VDID,
2 1, 1,
2 10, 55)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Draw vertical lines at columns 11, 21, and 31
DO I = 11, 31, 10
STATUS = SMG$DRAW_LINE (STATS_VDID,
2 1, I,
2 10, I)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
END DO

(continued on next page)

22–22 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–9 (Cont.) Creating a Statistics Display


! Draw horizontal line at row 3
STATUS = SMG$DRAW_LINE (STATS_VDID,
2 3, 1,
2 3, 55)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (STATS_VDID,
2 PBID,
2 3,
2 2)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

22.4.6.5 Deleting Text


The following routines erase specified characters, leaving the rest of the screen
intact:
• SMG$ERASE_CHARS—Erases specified characters on one line.
• SMG$ERASE_LINE—Erases the characters on one line starting from a
specified position.
• SMG$ERASE_DISPLAY—Erases specified characters on one or more lines.
• SMG$ERASE_COLUMN—Erases a column from the specified row to the end
of the column from the virtual display.
The following routines perform delete operations. In a delete operation,
characters following the deleted characters are shifted into the empty space.
• SMG$DELETE_CHARS—Deletes specified characters on one line. Any
characters to the right of the deleted characters are shifted left.
• SMG$DELETE_LINE—Deletes one or more full lines. Any remaining lines in
the display are scrolled up to fill the empty space.
The following example erases the remaining characters on the line whose line
number is specified by LINE_NO, starting at the column specified by COLUMN_
NO:
STATUS = SMG$ERASE_LINE (STATS_VDID,
2 LINE_NO,
2 COLUMN_NO)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

22.4.7 Using Menus


You can use SMG$ routines to set up menus to read user input. The type of
menus you can create include the following:
• Block menu—Selections are in matrix format. This is the type of menu often
used.
• Vertical menu—Each selection is on its own line.
• Horizontal menu—All selections are on one line.
Menus are associated with a virtual display, and only one menu can be used for
each virtual display.

Run-Time Library Input/Output Operations 22–23


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

The menu routines include the following:


• SMG$CREATE_MENU—Creates a menu associated with a virtual display.
This routine allows you to specify the type of menu, the position in which
the menu is displayed, the format of the menu (single or double spaced), and
video attributes.
• SMG$SELECT_FROM_MENU—Sets up menu selection capability. You can
specify a default menu selection (which is shown in reverse video), whether
online help is available, a maximum time limit for making a menu selection,
a key indicating read termination, whether to send the text of the menu item
selected to a string, and a video attribute.
• SMG$DELETE_MENU—Discontinues access to the menu and erases it.
When you are using menus, no other output should be sent to the menu area;
otherwise, unpredictable results may occur.
The default SMG$SELECT_FROM_MENU allows specific operations, such as
use of the arrow keys to move up and down the menu selections, keys to make a
menu selection, ability to select more than one item at a time, ability to reselect
an item already selected, and the key sequence to invoke online help. By using
the flags argument to modify this operation, you have the option of disallowing
reselection of a menu item and of allowing any key pressed to select an item.

22.4.8 Reading Data


You can read text from a virtual display (SMG$READ_FROM_DISPLAY) or from
a virtual keyboard (SMG$READ_STRING, SMG$READ_COMPOSED_LINE, or
SMG$READ_KEYSTROKE). The three routines for virtual keyboard input are
known as the SMG$ input routines. SMG$READ_FROM_DISPLAY is not a true
input routine because it reads text from the virtual display rather than from a
user.
The SMG$ input routines can be used alone or with the SMG$ output routines.
This section assumes that you are using the input routines with the output
routines. Section 22.5 describes how to use the input routines without the output
routines.
When you use the SMG$ input routines with the SMG$ output routines, always
specify the optional vdid argument of the input routine, which specifies the
virtual display in which the input is to occur. The specified virtual display must
be pasted to the device associated with the virtual keyboard that is specified as
the first argument of the input routine. The display must be pasted in column 1,
cannot be occluded, and cannot have any other display to its right; input begins
at the current cursor position, but the cursor must be in column 1.
22.4.8.1 Reading from a Display
You can read the contents of the display using the routine SMG$READ_
FROM_DISPLAY. By default, the read operation reads all of the characters
from the current cursor position to the end of that line. The row argument of
SMG$READ_FROM_DISPLAY allows you to choose the starting point of the read
operation, that is, the contents of the specified row to the rightmost column in
that row.
If the terminator-string argument is specified, SMG$READ_FROM_DISPLAY
searches backward from the current cursor position and reads the line beginning
at the first terminator encountered (or at the beginning of the line). A

22–24 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

terminator is a character string. You must calculate the length of the character
string read operation yourself.
The following example reads the current contents of the first line in the STATS_
VDID display:
CHARACTER*4 STRING
INTEGER*4 SIZE
.
.
.
STATUS = SMG$HOME_CURSOR (STATS_VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
STATUS = SMG$READ_FROM_DISPLAY (STATS_VDID,
2 STRING)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
SIZE = 55
DO WHILE ((STRING (SIZE:SIZE) .EQ. ’ ’) .AND.
2 (SIZE .GT. 1))
SIZE = SIZE - 1
END DO
22.4.8.2 Reading from a Virtual Keyboard
The SMG$CREATE_VIRTUAL_KEYBOARD routine establishes a device for input
operations; the default device is the user’s terminal. The routine SMG$READ_
STRING reads characters typed on the screen either until the user types a
terminator or until the maximum size (which defaults to 512 characters) is
exceeded. (The terminator is usually a carriage return; see the routine description
in the OpenVMS RTL Screen Management (SMG$) Manual for a complete list of
terminators.) The current cursor location for the display determines where the
read operation begins.
The operating system’s terminal driver processes carriage returns differently
than the SMG$ routines. Therefore, in order to scroll input accurately, you must
keep track of your vertical position in the display area. Explicitly set the cursor
position and scroll the display. If a read operation takes place on a row other
than the last row of the display, advance the cursor to the beginning of the next
row before the next operation. If a read operation takes place on the last row of
the display, scroll the display with SMG$SCROLL_DISPLAY_AREA and then set
the cursor to the beginning of the row. Modify the read operation with TRM$M_
TM_NOTRMECHO to ensure that no extraneous scrolling occurs.
Example 22–10 reads input until Ctrl/Z is pressed.

Example 22–10 Reading Data from a Virtual Keyboard


.
.
.
! Read first record
STATUS = SMG$HOME_CURSOR (VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$READ_STRING (KBID,
2 TEXT,
2 ’Prompt: ’,
2 4,
2 TRM$M_TM_TRMNOECHO,,,
2 TEXT_SIZE,,
2 VDID)

(continued on next page)

Run-Time Library Input/Output Operations 22–25


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–10 (Cont.) Reading Data from a Virtual Keyboard


! Read remaining records until CTRL/Z
DO WHILE (STATUS .NE. SMG$_EOF)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Process record
.
.
.
! Set up screen for next read
! Display area contains four rows
STATUS = SMG$RETURN_CURSOR_POS (VDID, ROW, COL)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
IF (ROW .EQ. 4) THEN
STATUS = SMG$SCROLL_DISPLAY_AREA (VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$SET_CURSOR_ABS (VDID, 4, 1)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
ELSE
STATUS = SMG$SET_CURSOR_ABS (VDID,, 1)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$SET_CURSOR_REL (VDID, 1)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
END IF
! Read next record
STATUS = SMG$READ_STRING (KBID,
2 TEXT,
2 ’Prompt: ’,
2 4,
2 TRM$M_TM_TRMNOECHO,,,
2 TEXT_SIZE,,
2 VDID)
END DO

Note
Because you are controlling the scrolling, SMG$PUT_LINE and
SMG$PUT_LINE_MULTI might not scroll as expected. When scrolling a
mix of input and output, you can prevent problems by using SMG$PUT_
CHARS.

22.4.8.3 Reading from the Keypad


To read from the keypad in keypad mode (that is, pressing a keypad character to
perform some special action rather than entering data), modify the read operation
with TRM$M_TM_ESCAPE and TRM$M_TM_NOECHO. Examine the terminator
to determine which key was pressed.
Example 22–11 moves the cursor on the screen in response to the user’s pressing
the keys surrounding the keypad 5 key. The keypad 8 key moves the cursor north
(up); the keypad 9 key moves the cursor northeast; the keypad 6 key moves the
cursor east (right); and so on. The SMG$SET_CURSOR_REL routine is called,
instead of being invoked as a function, because you do not want to abort the
program on an error. (The error attempts to move the cursor out of the display
area and, if this error occurs, you do not want the cursor to move.) The read
operation is also modified with TRM$M_TM_PURGE to prevent the user from
getting ahead of the cursor.

22–26 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

See Section 22.4.8.1 for the guidelines for reading from the display.

Example 22–11 Reading Data from the Keypad


.
.
.
INTEGER STATUS,
2 PBID,
2 ROWS,
2 COLUMNS,
2 VDID, ! Virtual display ID
2 KID, ! Keyboard ID
2 SMG$CREATE_PASTEBOARD,
2 SMG$CREATE_VIRTUAL_DISPLAY,
2 SMG$CREATE_VIRTUAL_KEYBOARD,
2 SMG$PASTE_VIRTUAL_DISPLAY,
2 SMG$HOME_CURSOR,
2 SMG$SET_CURSOR_REL,
2 SMG$READ_STRING,
2 SMG$ERASE_PASTEBOARD,
2 SMG$PUT_CHARS,
2 SMG$READ_FROM_DISPLAY
CHARACTER*31 INPUT_STRING,
2 MENU_STRING
INTEGER*2 TERMINATOR
INTEGER*4 MODIFIERS
INCLUDE ’($SMGDEF)’
INCLUDE ’($TRMDEF)’
! Set up screen and keyboard
STATUS = SMG$CREATE_PASTEBOARD (PBID,
2 ’SYS$OUTPUT’,
2 ROWS,
2 COLUMNS)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (ROWS,
2 COLUMNS,
2 VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PUT_CHARS (VDID,
2 ’__ MENU CHOICE ONE’,
2 10,30)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PUT_CHARS (VDID,
2 ’__ MENU CHOICE TWO’,
2 15,30)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (KID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (VDID,
2 PBID,
2 1,
2 1)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Put cursor in NW corner
STATUS = SMG$HOME_CURSOR (VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

(continued on next page)

Run-Time Library Input/Output Operations 22–27


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–11 (Cont.) Reading Data from the Keypad


! Read character from keyboard
MODIFIERS = TRM$M_TM_ESCAPE .OR.
2 TRM$M_TM_NOECHO .OR.
2 TRM$M_TM_PURGE
STATUS = SMG$READ_STRING (KID,
2 INPUT_STRING,
2 ,
2 6,
2 MODIFIERS,
2 ,
2 ,
2 ,
2 TERMINATOR)
DO WHILE ((STATUS) .AND.
2 (TERMINATOR .NE. SMG$K_TRM_CR))
! Check status of last read
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! North
IF (TERMINATOR .EQ. SMG$K_TRM_KP8) THEN
CALL SMG$SET_CURSOR_REL (VDID, -1, 0)
! Northeast
ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP9) THEN
CALL SMG$SET_CURSOR_REL (VDID, -1, 1)
! Northwest
ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP7) THEN
CALL SMG$SET_CURSOR_REL (VDID, -1, -1)
! South
ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP2) THEN
CALL SMG$SET_CURSOR_REL (VDID, 1, 0)
! Southeast
ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP3) THEN
CALL SMG$SET_CURSOR_REL (VDID, 1, 1)
! Southwest
ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP1) THEN
CALL SMG$SET_CURSOR_REL (VDID, 1, -1)
! East
ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP6) THEN
CALL SMG$SET_CURSOR_REL (VDID, 0, 1)
! West
ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP4) THEN
CALL SMG$SET_CURSOR_REL (VDID, 0, -1)
END IF
! Read another character
STATUS = SMG$READ_STRING (KID,
2 INPUT_STRING,
2 ,
2 6,
2 MODIFIERS,
2 ,
2 ,
2 ,
2 TERMINATOR)
END DO

(continued on next page)

22–28 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–11 (Cont.) Reading Data from the Keypad


! Read menu entry and process
!
STATUS = SMG$READ_FROM_DISPLAY (VDID,
2 MENU_STRING)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
! Clear screen
STATUS = SMG$ERASE_PASTEBOARD (PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
END

22.4.8.4 Reading Composed Input


The SMG$CREATE_KEY_TABLE routine creates a table that equates keys
to character strings. When you read input using the routine SMG$READ_
COMPOSED_LINE and the user presses a defined key, the corresponding
character string in the table is substituted for the key. You can use the
SMG$ADD_KEY_DEF routine to load the table. Composed input also permits the
following:
• If states—You can define the same key to mean different things in different
states. You can define a key to cause a change in state. The change in state
can be temporary (until after the next defined key is pressed) or permanent
(until a key that changes states is pressed).
• Input termination—You can define the key to cause termination of the input
transmission (as if the Return key were pressed after the character string). If
the key is not defined to cause termination of the input, the user must press
a terminator or another key that does cause termination.
Example 22–12 defines keypad keys 1 through 9 and permits the user to
change state temporarily by pressing the PF1 key. Pressing the keypad 1 key
is equivalent to typing 1000 and pressing the Return key. Pressing PF1 key and
then the keypad 1 key is equivalent to typing 10000 and pressing the Return
key.

Example 22–12 Redefining Keys


INTEGER*4 TABLEID
.
.
.
! Create table for key definitions
STATUS = SMG$CREATE_KEY_TABLE (TABLEID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Load table
! If user presses PF1, the state changes to BYTEN
! The BYTEN state is in effect only for the very next key
STATUS = SMG$ADD_KEY_DEF (TABLEID,
2 ’PF1’,
2 ,,,’BYTEN’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

(continued on next page)

Run-Time Library Input/Output Operations 22–29


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–12 (Cont.) Redefining Keys


! Pressing KP1 through Kp9 in the null state is like typing
! 1000 through 9000 and pressing return
STATUS = SMG$ADD_KEY_DEF (TABLEID,
2 ’KP1’,
2 ,
2 SMG$M_KEY_TERMINATE,
2 ’1000’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$ADD_KEY_DEF (TABLEID,
2 ’KP2’,
2 ,
2 SMG$M_KEY_TERMINATE,
2 ’2000’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
STATUS = SMG$ADD_KEY_DEF (TABLEID,
2 ’KP9’,
2 ,
2 SMG$M_KEY_TERMINATE,
2 ’9000’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Pressing KP1 through KP9 in the BYTEN state is like
! typing 10000 through 90000 and pressing return
STATUS = SMG$ADD_KEY_DEF (TABLEID,
2 ’KP1’,
2 ’BYTEN’,
2 SMG$M_KEY_TERMINATE,
2 ’10000’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$ADD_KEY_DEF (TABLEID,
2 ’KP2’,
2 ’BYTEN’,
2 SMG$M_KEY_TERMINATE,
2 ’20000’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
STATUS = SMG$ADD_KEY_DEF (TABLEID,
2 ’KP9’,
2 ’BYTEN’,
2 SMG$M_KEY_TERMINATE,
2 ’90000’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

(continued on next page)

22–30 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

Example 22–12 (Cont.) Redefining Keys


! End loading key definition table
.
.
.
! Read input which substitutes key definitions where appropriate
STATUS = SMG$READ_COMPOSED_LINE (KBID,
2 TABLEID,
2 STRING,
2 SIZE,
2 VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.

Use the SMG$DELETE_KEY_DEF routine to delete a key definition; use the


SMG$GET_KEY_DEF routine to examine a key definition. You can also load
key definition tables with the SMG$DEFINE_KEY and SMG$LOAD_KEY_DEFS
routines; use the DCL command DEFINE/KEY to specify input to these routines.
To use keypad keys 0 through 9, the keypad must be in application mode.
For details, see SMG$SET_KEYPAD_MODE in the OpenVMS RTL Screen
Management (SMG$) Manual.

22.4.9 Controlling Screen Updates


If your program needs to make a number of changes to a virtual display, you can
use SMG$ routines to make all of the changes before updating the display. The
SMG$BEGIN_DISPLAY_UPDATE routine causes output operations to a pasted
display to be reflected only in the display’s buffers. The SMG$END_DISPLAY_
UPDATE routine writes the display’s buffer to the pasteboard.
The SMG$BEGIN_DISPLAY_UPDATE and SMG$END_DISPLAY_UPDATE
routines increment and decrement a counter. When this counter’s value is
0, output to the virtual display is sent to the pasteboard immediately. The
counter mechanism allows a subroutine to request and turn off batching without
disturbing the batching state of the calling program.
A second set of routines, SMG$BEGIN_PASTEBOARD_UPDATE and
SMG$END_PASTEBOARD_UPDATE, allow you to buffer output to a pasteboard
in a similar manner.

22.4.10 Maintaining Modularity


When using the SMG$ routines, you must take care not to corrupt the mapping
between the screen appearance and the internal representation of the screen.
Therefore, observe the following guidelines:
• Mixing SMG I/O and other forms of I/O
In general, do not use any other form of terminal I/O while the terminal is
active as a pasteboard. If you do use I/O other than SMG I/O (for example,
if you invoke a subprogram that may perform non-SMG terminal I/O), first
invoke the SMG$SAVE_PHYSICAL_SCREEN routine and when the non-SMG
I/O completes, invoke the SMG$RESTORE_PHYSICAL_SCREEN routine, as
demonstrated in the following example:

Run-Time Library Input/Output Operations 22–31


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

STATUS = SMG$SAVE_PHYSICAL_SCREEN (PBID,


2 SAVE_VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
CALL GET_EXTRA_INFO (INFO_ARRAY)
STATUS = SMG$RESTORE_PHYSICAL_SCREEN (PBID,
2 SAVE_VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
• Sharing the pasteboard
A routine using the terminal screen without consideration for its current
contents must use the existing pasteboard ID associated with the terminal
and delete any virtual displays it creates before returning control to the
high-level code. This guideline also applies to the program unit that invokes
a subprogram that also performs screen I/O. The safest way to clean up your
virtual displays is to call the SMG$POP_VIRTUAL_DISPLAY routine and
name the first virtual display you created. The following example invokes a
subprogram that uses the terminal screen:
Invoking Program Unit
CALL GET_EXTRA_INFO (PBID,
2 INFO_ARRAY)
.
.
.
CALL STATUS = SMG$CREATE_PASTEBOARD (PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
Subprogram
SUBROUTINE GET_EXTRA_INFO (PBID,
2 INFO_ARRAY)
.
.
.
! Start executable code
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (4,
2 40,
2 INSTR_VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (INSTR_VDID,
2 PBID, 1, 1)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
STATUS = SMG$POP_VIRTUAL_DISPLAY (INSTR_VDID,
2 PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
END
• Sharing virtual displays
To share a virtual display created by high-level code, the low-level code must
use the virtual display ID created by the high-level code; an invoking program
unit must pass the virtual display ID to the subprogram. To share a virtual
display created by low-level code, the high-level code must use the virtual
display ID created by the low-level code; a subprogram must return the
virtual display ID to the invoking program.

22–32 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.4 Working with Complex User I/O

The following example permits a subprogram to use a virtual display created


by the invoking program unit:
Invoking Program Unit
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (4,
2 40,
2 INSTR_VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (INSTR_VDID,
2 PBID, 1, 1)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
CALL GET_EXTRA_INFO (PBID,
2 INSTR_VDID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
Subprogram
SUBROUTINE GET_EXTRA_INFO (PBID,
2 INSTR_VDID)

22.5 Performing Special Input/Output Actions


Screen management input routines and the SYS$QIO and SYS$QIOW system
services allow you to perform I/O operations otherwise unavailable to high-level
languages. For example, you can allow a user to interrupt normal program
execution by typing a character and by providing a mechanism for reading that
character. You can also control such things as echoing, time allowed for input,
and whether data is read from the type-ahead buffer.
Some of the operations described in the following sections require the use of
the SYS$QIO or SYS$QIOW system services. For more information about the
QIO system services, see the OpenVMS System Services Reference Manual and
Chapter 23.
Other operations, described in the following sections, can be performed by calling
the SMG$ input routines. The SMG$ input routines can be used alone or with
the SMG$ output routines. Section 22.4 describes how to use the input routines
with the output routines. This section assumes that you are using the input
routines alone. To use the SMG$ input routines, do the following:
1. Call SMG$CREATE_VIRTUAL_KEYBOARD to associate a logical keyboard
with a device or file specification (SYS$INPUT by default). SMG$CREATE_
VIRTUAL_KEYBOARD returns a keyboard identification number; use that
number to identify the device or file to the SMG$ input routines.
2. Call an SMG$ input routine (SMG$READ_STRING or SMG$READ_
COMPOSED_LINE) to read data typed at the device associated with the
virtual keyboard.
When using the SMG$ input routines without the SMG$ output routines, do not
specify the optional VDID argument of the input routine.

22.5.1 Using Ctrl/C and Ctrl/Y Interrupts


The QIO system services enable you to detect a Ctrl/C or Ctrl/Y interrupt at a
user terminal, even if you have not issued a read to the terminal. To do so, you
must take the following steps:
1. Queue an asynchronous system trap (AST)—Issue the SYS$QIO or
SYS$QIOW system service with a function code of IO$_SETMODE modified
by either IO$M_CTRLCAST (for Ctrl/C interrupts) or
IO$M_CTRLYAST (for Ctrl/Y interrupts). For the P1 argument, provide the

Run-Time Library Input/Output Operations 22–33


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

name of a subroutine to be executed when the interrupt occurs. For the P2


argument, you can optionally identify one longword argument to pass to the
AST subroutine.
2. Write an AST subroutine—Write the subroutine identified in the P1 argument
of the QIO system service and link the subroutine into your program. Your
subroutine can take one longword dummy argument to be associated with the
P2 argument in the QIO system service. You must define common areas to
access any other data in your program from the AST routine.
If you press Ctrl/C or Ctrl/Y after your program queues the appropriate AST, the
system interrupts your program and transfers control to your AST subroutine
(this action is called delivering the AST). After your AST subroutine executes,
the system returns control to your program at the point of interruption (unless
your AST subroutine causes the program to exit, or unless another AST has been
queued). Note the following guidelines for using Ctrl/C and Ctrl/Y ASTs:
• ASTs are asynchronous—Since your AST subroutine does not know exactly
where you are in your program when the interrupt occurs, you should avoid
manipulating data or performing other mainline activities. In general, the
AST subroutine should either notify the mainline code (for example, by
setting a flag) that the interrupt occurred, or clean up and exit from the
program (if that is what you want to do).
• ASTs need new channels to the terminal—If you try to access the terminal
with language I/O statements using SYS$INPUT or SYS$OUTPUT, you may
receive a redundant I/O error. You must establish another channel to the
terminal by explicitly opening the terminal.
• Ctrl/C and Ctrl/Y ASTs are one-time ASTs—After a Ctrl/C or Ctrl/Y AST is
delivered, it is dequeued. You must reissue the QIO system service if you
wish to trap another interrupt.
• Many ASTs can be queued—You can queue multiple ASTs (for the same or
different AST subroutines, on the same or different channels) by issuing the
appropriate number of QIO system services. The system delivers the ASTs on
a last-in, first-out (LIFO) basis.
• Unhandled Ctrl/Cs turn into Ctrl/Ys—If the user enters Ctrl/C and you do
not have an AST queued to handle the interrupt, the system turns the Ctrl/C
interrupt into a Ctrl/Y interrupt.
• DCL handles Ctrl/Y interrupts—DCL handles Ctrl/Y interrupts by returning
the user to DCL command level, where the user has the option of continuing
or exiting from your program. DCL takes precedence over your AST
subroutine for Ctrl/Y interrupts. Your Ctrl/Y AST subroutine is executed
only under the following circumstances:
If Ctrl/Y interrupts are disabled at DCL level (SET NOCONTROL_Y)
before your program is executed
If your program disables DCL Ctrl/Y interrupts with LIB$DISABLE_
CTRL
If the user elects to continue your program after DCL interrupts it
• You can dequeue Ctrl/C and Ctrl/Y ASTs—You can dequeue all Ctrl/C or
Ctrl/Y ASTs on a channel by issuing the appropriate QIO system service
with a value of 0 for the P1 argument (passed by immediate value). You can
dequeue all Ctrl/C ASTs on a channel by issuing the SYS$CANCEL system

22–34 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

service for the appropriate channel. You can dequeue all Ctrl/Y ASTs on a
channel by issuing the SYS$DASSGN system service for the appropriate
channel.
• You can use SMG$ routines—You can connect to the terminal using the SMG$
routines from either AST level or mainline code. Do not attempt to connect to
the terminal from AST level if you do so in your mainline code.
Example 22–13 permits the terminal user to interrupt a display to see how many
lines have been typed up to that point.

Example 22–13 Using Interrupts to Perform I/O


!Main Program
.
.
.
INTEGER STATUS
! Accumulated data records
CHARACTER*132 STORAGE (255)
INTEGER*4 STORAGE_SIZE (255),
2 STORAGE_COUNT
! QIOW and QIO structures
INTEGER*2 INPUT_CHAN
INTEGER*4 CODE
STRUCTURE /IOSTAT_BLOCK/
INTEGER*2 IOSTAT
BYTE TRANSMIT,
2 RECEIVE,
2 CRFILL,
2 LFFILL,
2 PARITY,
2 ZERO
END STRUCTURE
RECORD /IOSTAT_BLOCK/ IOSB
! Flag to notify program of CTRL/C interrupt
LOGICAL*4 CTRLC_CALLED
! AST subroutine to handle CTRL/C interrupt
EXTERNAL CTRLC_AST
! Subroutines
INTEGER SYS$ASSIGN,
2 SYS$QIOW
! Symbols used for I/O operations
INCLUDE ’($IODEF)’
! Put values into array
CALL LOAD_STORAGE (STORAGE,
2 STORAGE_SIZE,
2 STORAGE_COUNT)
! Assign channel and set up QIOW structures
STATUS = SYS$ASSIGN (’SYS$INPUT’,
2 INPUT_CHAN,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
CODE = IO$_SETMODE .OR. IO$M_CTRLCAST

(continued on next page)

Run-Time Library Input/Output Operations 22–35


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

Example 22–13 (Cont.) Using Interrupts to Perform I/O


! Queue an AST to handle CTRL/C interrupt
STATUS = SYS$QIOW (,
2 %VAL (INPUT_CHAN),
2 %VAL (CODE),
2 IOSB,
2 ,,
2 CTRLC_AST, ! Name of AST routine
2 CTRLC_CALLED, ! Argument for AST routine
2 ,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
IF (.NOT. IOSB.IOSTAT)
2 CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT))
! Display STORAGE array, one element per line
DO I = 1, STORAGE_COUNT
TYPE *, STORAGE (I) (1:STORAGE_SIZE (I))
! Additional actions if user types CTRL/C
IF (CTRLC_CALLED) THEN
CTRLC_CALLED = .FALSE.
! Show user number of lines displayed so far
TYPE *, ’Number of lines: ’, I
! Requeue AST
STATUS = SYS$QIOW (,
2 %VAL (INPUT_CHAN),
2 %VAL (CODE),
2 IOSB,
2 ,,
2 CTRLC_AST,
2 CTRLC_CALLED,
2 ,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
IF (.NOT. IOSB.IOSTAT)
2 CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT))
END IF
END DO
END
AST Routine
! AST routine
! Notifies program that user typed CTRL/C
SUBROUTINE CTRLC_AST (CTRLC_CALLED)
LOGICAL*4 CTRLC_CALLED
CTRLC_CALLED = .TRUE.
END

22.5.2 Detecting Unsolicited Input


You can detect input from the terminal even if you have not called SMG$READ_
COMPOSED_LINE or SMG$READ_STRING by using SMG$ENABLE_
UNSOLICITED_INPUT. This routine uses the AST mechanism to transfer
control to a subprogram of your choice each time the user types at the terminal;
the AST subprogram is responsible for reading any input. When the subprogram
completes, control returns to the point in your mainline code where it was
interrupted.

22–36 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

The SMG$ENABLE_UNSOLICITED_INPUT routine is not an SMG$ input


routine. Before invoking SMG$ENABLE_UNSOLICITED_INPUT, you must
invoke SMG$CREATE_PASTEBOARD to associate a pasteboard with the
terminal and SMG$CREATE_VIRTUAL_KEYBOARD to associate a virtual
keyboard with the same terminal.
SMG$ENABLE_UNSOLICITED_INPUT accepts the following arguments:
• The pasteboard identification number (use the value returned by
SMG$CREATE_PASTEBOARD)
• The name of an AST subprogram
• An argument to be passed to the AST subprogram
When SMG$ENABLE_UNSOLICITED_INPUT invokes the AST subprogram, it
passes two arguments to the subprogram: the pasteboard identification number
and the argument that you specified. Typically, you write the AST subprogram
to read the unsolicited input with SMG$READ_STRING. Since SMG$READ_
STRING requires that you specify the virtual keyboard at which the input was
typed, specify the virtual keyboard identification number as the second argument
to pass to the AST subprogram.
Example 22–14 permits the terminal user to interrupt the display of a series
of arrays, and either to go on to the next array (by typing input beginning with
an uppercase N) or to exit from the program (by typing input beginning with
anything else).

Example 22–14 Receiving Unsolicited Input from a Virtual Keyboard


! Main Program
! The main program calls DISPLAY_ARRAY once for each array.
! DISPLAY_ARRAY displays the array in a DO loop.
! If the user enters input from the terminal, the loop is
! interrupted and the AST routine takes over.
! If the user types anything beginning with an N, the AST
! sets DO_NEXT and resumes execution -- DISPLAY_ARRAY drops
! out of the loop processing the array (because DO_NEXT is
! set -- and the main program calls DISPLAY_ARRAY for the
! next array.
! If the user types anything not beginning with an N,
! the program exits.
.
.
.
INTEGER*4 STATUS,
2 VKID, ! Virtual keyboard ID
2 PBID ! Pasteboard ID
! Storage arrays
INTEGER*4 ARRAY1 (256),
2 ARRAY2 (256),
2 ARRAY3 (256)
! System routines
INTEGER*4 SMG$CREATE_PASTEBOARD,
2 SMG$CREATE_VIRTUAL_KEYBOARD,
2 SMG$ENABLE_UNSOLICITED_INPUT
! AST routine
EXTERNAL AST_ROUTINE

(continued on next page)

Run-Time Library Input/Output Operations 22–37


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

Example 22–14 (Cont.) Receiving Unsolicited Input from a Virtual Keyboard


! Create a pasteboard
STATUS = SMG$CREATE_PASTEBOARD (PBID, ! Pasteboard ID
2 ’SYS$INPUT’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Create a keyboard for the same device
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID, ! Keyboard ID
2 ’SYS$INPUT’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Enable unsolicited input
STATUS = SMG$ENABLE_UNSOLICITED_INPUT (PBID, ! Pasteboard ID
2 AST_ROUTINE,
2 VKID) ! Pass keyboard
! ID to AST
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
! Call display subroutine once for each array
CALL DISPLAY_ARRAY (ARRAY1)
CALL DISPLAY_ARRAY (ARRAY2)
CALL DISPLAY_ARRAY (ARRAY3)
END
Array Display Routine
! Subroutine to display one array
SUBROUTINE DISPLAY_ARRAY (ARRAY)
! Dummy argument
INTEGER*4 ARRAY (256)
! Status
INTEGER*4 STATUS
! Flag for doing next array
LOGICAL*4 DO_NEXT
COMMON /DO_NEXT/ DO_NEXT
! If AST has been delivered, reset
IF (DO_NEXT) DO_NEXT = .FALSE.
! Initialize control variable
I = 1
! Display entire array unless interrupted by user
! If interrupted by user (DO_NEXT is set), drop out of loop
DO WHILE ((I .LE. 256) .AND. (.NOT. DO_NEXT))
TYPE *, ARRAY (I)
I = I + 1
END DO
END

(continued on next page)

22–38 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

Example 22–14 (Cont.) Receiving Unsolicited Input from a Virtual Keyboard


AST Routine
! Subroutine to read unsolicited input
SUBROUTINE AST_ROUTINE (PBID,
2 VKID)
! dummy arguments
INTEGER*4 PBID, ! Pasteboard ID
2 VKID ! Keyboard ID
! Status
INTEGER*4 STATUS
! Flag for doing next array
LOGICAL*4 DO_NEXT
COMMON /DO_NEXT/ DO_NEXT
! Input string
CHARACTER*4 INPUT
! Routines
INTEGER*4 SMG$READ_STRING
! Read input
STATUS = SMG$READ_STRING (VKID, ! Keyboard ID
2 INPUT)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! If user types anything beginning with N, set DO_NEXT
! otherwise, exit from program
IF (INPUT (1:1) .EQ. ’N’) THEN
DO_NEXT = .TRUE.
ELSE
CALL EXIT
END IF
END

22.5.3 Using the Type-Ahead Buffer


Normally, if the user types at the terminal before your application is able to
read from that device, the input is saved in a special data structure maintained
by the system called the type-ahead buffer. When your application is ready to
read from the terminal, the input is transferred from the type-ahead buffer to
your input buffer. The type-ahead buffer is preset at a size of 78 bytes. If the
HOSTSYNC characteristic is on (the usual condition), input to the type-ahead
buffer is stopped (the keyboard locks) when the buffer is within 8 bytes of being
full. If the HOSTSYNC characteristic is off, the bell rings when the type-ahead
buffer is within 8 bytes of being full; if you overflow the buffer, the excess data
is lost. The TTY_ALTALARM system parameter determines the point at which
either input is stopped or the bell rings.
You can clear the type-ahead buffer by reading from the terminal with
SMG$READ_STRING and by specifying TRM$M_TM_PURGE in the modifiers
argument. Clearing the type-ahead buffer has the effect of reading only what the
user types on the terminal after the read operation is invoked. Any characters
in the type-ahead buffer are lost. The following example illustrates how to purge
the type-ahead buffer:
INTEGER*4 SMG$CREATE_VIRTUAL_KEYBOARD,
2 SMG$READ_STRING,
2 STATUS,
2 VKID, ! Virtual keyboard ID
2 INPUT_SIZE

Run-Time Library Input/Output Operations 22–39


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

CHARACTER*512 INPUT
INCLUDE ’($TRMDEF)’
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID,
2 ’SYS$INPUT’) ! I/O device
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$READ_STRING (VKID, ! Keyboard ID
2 INPUT, ! Data read
2 ’Prompt> ’,
2 512,
2 TRM$M_TM_PURGE,
2 ,,
2 INPUT_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
You can also clear the type-ahead buffer with a QIO read operation modified by
IO$M_PURGE (defined in $IODEF). You can turn off the type-ahead buffer for
further read operations with a QIO set mode operation that specifies TT$M_
NOTYPEAHD as a basic terminal characteristic.
You can examine the type-ahead buffer by issuing a QIO sense mode operation
modified by IO$M_TYPEAHDCNT. The number of characters in the type-ahead
buffer and the value of the first character are returned to the P1 argument.
The size of the type-ahead buffer is determined by the TTY_TYPAHDSZ system
parameter. You can specify an alternative type-ahead buffer by turning on the
ALTYPEAHD terminal characteristic; the size of the alternative type-ahead
buffer is determined by the TTY_ALTYPAHD system parameter.

22.5.4 Using Echo


Normally, the system writes back to the terminal any printable characters that
the user types at that terminal. The system also writes highlighted words in
response to certain control characters; for example, the system writes EXIT if the
user enters Ctrl/Z. If the user types ahead of your read, the characters are not
echoed until you read them from the type-ahead buffer.
You can turn off echoing when you invoke a read operation by reading from the
terminal with SMG$READ_STRING and by specifying TRM$M_TM_NOECHO
in the modifiers argument. You can turn off echoing for control characters only
by modifying the read operation with TRM$M_TM_TRMNOECHO. The following
example turns off all echoing for the read operation:
INTEGER*4 SMG$CREATE_VIRTUAL_KEYBOARD,
2 SMG$READ_STRING,
2 STATUS,
2 VKID, ! Virtual keyboard ID
2 INPUT_SIZE
CHARACTER*512 INPUT
INCLUDE ’($TRMDEF)’
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID, ! Keyboard ID
2 ’SYS$INPUT’) ! I/O device
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$READ_STRING (VKID, ! Keyboard ID
2 INPUT, ! Data read
2 ’Prompt> ’,
2 512,
2 TRM$M_TM_NOECHO,
2 ,,
2 INPUT_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

22–40 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

You can also turn off echoing with a QIO read operation modified by IO$M_
NOECHO (defined in $IODEF). You can turn off echoing for further read
operations with a QIO set mode operation that specifies TT$M_NOECHO as
a basic terminal characteristic.

22.5.5 Using Timeout


Using SMG$READ_STRING, you can restrict the user to a certain amount of
time in which to respond to a read command. If your application reads data
from the terminal using SMG$READ_STRING, you can modify the timeout
characteristic by specifying, in the timeout argument, the number of seconds the
user has to respond. If the user fails to type a character in the allotted time, the
error condition SS$_TIMEOUT (defined in $SSDEF) is returned. The following
example restricts the user to 8 seconds in which to respond to a read command:
INTEGER*4 SMG$CREATE_VIRTUAL_KEYBOARD,
2 SMG$READ_STRING,
2 STATUS,
2 VKID, ! Virtual keyboard ID
2 INPUT_SIZE
CHARACTER*512 INPUT
INCLUDE ’($SSDEF)’
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID,
2 ’SYS$INPUT’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$READ_STRING (VKID, ! Keyboard ID
2 INPUT, ! Data read
2 ’Prompt> ’,
2 512,
2 ,
2 8,
2 ,
2 INPUT_SIZE)
IF (.NOT. STATUS) THEN
IF (STATUS .EQ. SS$_TIMEOUT) CALL NO_RESPONSE ()
ELSE
CALL LIB$SIGNAL (%VAL (STATUS))
END IF
You can cause a QIO read operation to time out after a certain number of seconds
by modifying the operation with IO$M_TIMED and by specifying the number of
seconds in the P3 argument. A message broadcast to a terminal resets a timer
that is set for a timed read operation (regardless of whether the operation was
initiated with QIO or SMG).
Note that the timed read operations work on a character-by-character basis. To
set a time limit on an input record rather than an input character, you must use
the SYS$SETIMR system service. The SYS$SETIMR executes an AST routine at
a specified time. The specified time is the input time limit. When the specified
time is reached, the AST routine cancels any outstanding I/O on the channel that
is assigned to the user’s terminal.

Run-Time Library Input/Output Operations 22–41


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

22.5.6 Converting Lowercase to Uppercase


You can automatically convert lowercase user input to uppercase by reading from
the terminal with the SMG$READ_STRING routine and by specifying TRM$M_
TM_CVTLOW in the modifiers argument, as shown in the following example:
INTEGER*4 SMG$CREATE_VIRTUAL_KEYBOARD,
2 SMG$READ_STRING,
2 STATUS,
2 VKID, ! Virtual keyboard ID
2 INPUT_SIZE
CHARACTER*512 INPUT
INCLUDE ’($TRMDEF)’
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID, ! Keyboard ID
2 ’SYS$INPUT’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$READ_STRING (VKID, ! Keyboard ID
2 INPUT, ! Data read
2 ’Prompt> ’,
2 512,
2 TRM$M_TM_CVTLOW,
2 ,,
2 INPUT_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
You can also convert lowercase characters to uppercase with a QIO read operation
modified by IO$M_CVTLOW (defined in $IODEF).

22.5.7 Performing Line Editing and Control Actions


Normally, the user can edit input as explained in the OpenVMS I/O User’s
Reference Manual. You can inhibit line editing on the read operation by reading
from the terminal with SMG$READ_STRING and by specifying TRM$M_TM_
NOFILTR in the modifiers argument. The following example shows how you can
inhibit line editing:
INTEGER*4 SMG$CREATE_VIRTUAL_KEYBOARD,
2 SMG$READ_STRING,
2 STATUS,
2 VKID, ! Virtual keyboard ID
2 INPUT_SIZE
CHARACTER*512 INPUT
INCLUDE ’($TRMDEF)’
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID, ! Keyboard ID
2 ’SYS$INPUT’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$READ_STRING (VKID, ! Keyboard ID
2 INPUT, ! Data read
2 ’Prompt> ’,
2 512,
2 TRM$M_TM_NOFILTR,
2 ,,
2 INPUT_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
You can also inhibit line editing with a QIO read operation modified by IO$M_
NOFILTR (defined in $IODEF).

22–42 Run-Time Library Input/Output Operations


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

22.5.8 Using Broadcasts


You can write, or broadcast, to any interactive terminal by using the
SYS$BRKTHRU system service. The following example broadcasts a message to
all terminals at which users are currently logged in. Use of SYS$BRKTHRU to
write to a terminal allocated to a process other than your own requires the OPER
privilege.
INTEGER*4 STATUS,
2 SYS$BRKTHRUW
INTEGER*2 B_STATUS (4)
INCLUDE ’($BRKDEF)’
STATUS = SYS$BRKTHRUW (,
2 ’Accounting system started’,,
2 %VAL (BRK$C_ALLUSERS),
2 B_STATUS,,,,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
22.5.8.1 Default Handling of Broadcasts
If the terminal user has taken no action to handle broadcasts, a broadcast is
written to the terminal screen at the current position (after a carriage return and
line feed). If a write operation is in progress, the broadcast occurs after the write
ends. If a read operation is in progress, the broadcast occurs immediately; after
the broadcast, any echoed user input to the aborted read operation is written to
the screen (same effect as pressing Ctrl/R).
22.5.8.2 How to Create Alternate Broadcast Handlers
You can handle broadcasts to the terminal on which your program is running with
SMG$SET_BROADCAST_TRAPPING. This routine uses the AST mechanism to
transfer control to a subprogram of your choice each time a broadcast message is
sent to the terminal; when the subprogram completes, control returns to the point
in your mainline code where it was interrupted.
The SMG$SET_BROADCAST_TRAPPING routine is not an SMG$ input
routine. Before invoking SMG$SET_BROADCAST_TRAPPING, you must invoke
SMG$CREATE_PASTEBOARD to associate a pasteboard with the terminal.
SMG$CREATE_PASTEBOARD returns a pasteboard identification number; pass
that number to SMG$SET_BROADCAST_TRAPPING to identify the terminal
in question. Read the contents of the broadcast with SMG$GET_BROADCAST_
MESSAGE.
Example 22–15 demonstrates how you might trap a broadcast and write it at the
bottom of the screen. For more information about the use of SMG$ pasteboards
and virtual displays, see Section 22.4.

Run-Time Library Input/Output Operations 22–43


Run-Time Library Input/Output Operations
22.5 Performing Special Input/Output Actions

Example 22–15 Trapping Broadcast Messages


.
.
.
INTEGER*4 STATUS,
2 PBID, ! Pasteboard ID
2 VDID, ! Virtual display ID
2 SMG$CREATE_PASTEBOARD,
2 SMG$SET_BROADCAST_TRAPPING
2 SMG$PASTE_VIRTUAL_DISPLAY
COMMON /ID/ PBID,
2 VDID
INTEGER*2 B_STATUS (4)
INCLUDE ’($SMGDEF)’
INCLUDE ’($BRKDEF)’
EXTERNAL BRKTHRU_ROUTINE
STATUS = SMG$CREATE_PASTEBOARD (PBID)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (3, ! Height
2 80, ! Width
2 VDID,, ! Display ID
2 SMG$M_REVERSE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SMG$SET_BROADCAST_TRAPPING (PBID, ! Pasteboard ID
2 BRKTHRU_ROUTINE) ! AST
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
SUBROUTINE BRKTHRU_ROUTINE ()
INTEGER*4 STATUS,
2 PBID, ! Pasteboard ID
2 VDID, ! Virtual display ID
2 SMG$GET_BROADCAST_MESSAGE,
2 SMG$PUT_CHARS,
2 SMG$PASTE_VIRTUAL_DISPLAY
COMMON /ID/ PBID,
2 VDID
CHARACTER*240 MESSAGE
INTEGER*2 MESSAGE_SIZE
! Read the message
STATUS = SMG$GET_BROADCAST_MESSAGE (PBID,
2 MESSAGE,
2 MESSAGE_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Write the message to the virtual display
STATUS = SMG$PUT_CHARS (VDID,
2 MESSAGE (1:MESSAGE_SIZE),
2 1, ! Line
2 1) ! Column
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Make the display visble by pasting it to the pasteboard
STATUS = SMG$PASTE_VIRTUAL_DISPLAY (VDID,
2 PBID,
2 22, ! Row
2 1) ! Column
END

22–44 Run-Time Library Input/Output Operations


23
System Service Input/Output Operations

This chapter describes how to use system services to perform input and output
operations. It contains the following sections:
Section 23.1 describes the QIO operation.
Section 23.2 describes the use of quotas, privileges, and protection.
Section 23.3 describes device addressing modes.
Section 23.4 describes I/O function encoding.
Section 23.5 describes how to assign channels.
Section 23.6 describes how to queue I/O requests.
Section 23.7 describes how to synchronize I/O completions.
Section 23.8 describes the routine to use to wait for completion of an
asynchronous event.
Section 23.9 describes executing I/O services synchronously or asynchronously.
Section 23.10 describes the completion status of an I/O operation.
Section 23.11 describes how to deassign I/O channels.
Section 23.12 presents a program example of a complete input and output
operation.
Section 23.13 describes how to cancel I/O requests.
Section 23.14 describes how to use logical names and physical device names for
I/O operations.
Section 23.15 describes how to use device name defaults.
Section 23.16 describes how to obtain information about physical devices.
Section 23.17 describes device allocation.
Section 23.18 describes how to mount, dismount, and initialize disk and tape
volumes.
Section 23.19 describes format output strings.
Section 23.20 describes how to use mailboxes for I/O operations.
Section 23.21 provides a program example of using I/O system services.
Section 23.22 describes the Fast I/O and Fast Path features that improve I/O
performance.
Examples are provided to show you how to use the I/O services for simple
functions, such as terminal input and output operations. If you plan to write
device-dependent I/O routines, see the OpenVMS I/O User’s Reference Manual.

System Service Input/Output Operations 23–1


System Service Input/Output Operations

On VAX systems, if you want to write your own device driver or connect to a
device interrupt vector, see the OpenVMS VAX Device Support Reference Manual.
The OpenVMS VAX Device Support Reference Manual has been archived but is
available on the OpenVMS Documentation CD–ROM.
Besides using I/O system services, you can use OpenVMS Record Management
Services (RMS). OpenVMS RMS provides a set of routines for general-purpose,
device-independent functions such as data storage, retrieval, and modification.
Unlike RMS services, I/O system services permit you to use the I/O resources of
the operating system directly in a device-dependent manner. I/O services also
provide some specialized functions not available in OpenVMS RMS. Using I/O
services requires more programming knowledge than using OpenVMS RMS, but
can result in more efficient input/output operations.

23.1 Overview of OpenVMS QIO Operations


The OpenVMS operating system provides QIO operations that perform three
basic I/O functions: read, write, and set mode. The read function transfers data
from a device to a user-specified buffer. The write function transfers data in the
opposite direction—from a user-specified buffer to the device. For example, in
a read QIO function to a terminal device, a user-specified buffer is filled with
characters received from the terminal. In a write QIO function to the terminal,
the data in a user-specified buffer is transferred to the terminal where it is
displayed.
The set mode QIO function is used to control or describe the characteristics and
operation of a device. For example, a set mode QIO function to a line printer can
specify either uppercase or lowercase character format. Not all QIO functions are
applicable to all types of devices. The line printer, for example, cannot perform a
read QIO function.

23.2 Quotas, Privileges, and Protection


To preserve the integrity of the operating system, the I/O operations are
performed under the constraints of quotas, privileges, and protection.
Quotas limit the number and type of I/O operations that a process can perform
concurrently and the total size of outstanding transfers. They ensure that all
users have an equitable share of system resources and usage.
Privileges are granted to a user to allow the performance of certain I/O-related
operations, for example, creating a mailbox and performing logical I/O to a
file-structured device. Restrictions on user privileges protect the integrity and
performance of both the operating system and the services provided to other
users.
Protection controls access to files and devices. Device protection is provided in
much the same way as file protection: shareable and nonshareable devices are
protected by protection masks.
The Set Resource Wait Mode (SYS$SETRWM) system service allows a process
to select either of two modes when an attempt to exceed a quota occurs. In the
enabled (default) mode, the process waits until the required resource is available
before continuing. In the disabled mode, the process is notified immediately by
a system service status return that an attempt to exceed a quota has occurred.
Waiting for resources is transparent to the process when resource wait mode is
enabled; the process takes no explicit action when a wait is necessary.

23–2 System Service Input/Output Operations


System Service Input/Output Operations
23.2 Quotas, Privileges, and Protection

The different types of I/O-related quotas, privilege, and protection are described
in the following sections.

23.2.1 Buffered I/O Quota


The buffered I/O limit quota (BIOLM) specifies the maximum number of
concurrent buffered I/O operations that can be active in a process. In a buffered
I/O operation, the user’s data is buffered in system dynamic memory. The driver
deals with the system buffer and not the user buffer. Buffered I/O is used
for terminal, line printer, card reader, network, mailbox, and console medium
transfers and file system operations. For a buffered I/O operation, the system
does not have to lock the user’s buffer in memory.
The system manager, or the person who creates the process, establishes the
buffered I/O quota value in the user authorization file. If you use the Set
Resource Wait Mode (SYS$SETRWM) system service to enable resource wait
mode for the process, the process enters resource wait mode if it attempts to
exceed its direct I/O quota.

23.2.2 Buffered I/O Byte Count Quota


The buffered I/O byte count quota (BYTLM) specifies the maximum amount of
buffer space that can be consumed from system dynamic memory for buffering
I/O requests. All buffered I/O requests require system dynamic memory in which
the actual I/O operation takes place.
The system manager, or the person who creates the process, establishes the
buffered I/O byte count quota in the user authorization file. If you use the
SYS$SETRWM system service to enable resource wait mode for the process, the
process enters resource wait mode if it attempts to exceed its direct I/O quota.

23.2.3 Direct I/O Quota


The direct I/O limit quota (DIOLM) specifies the maximum number of concurrent
direct (unbuffered) I/O operations that a process can have active. In a direct I/O
operation, data is moved directly to or from the user buffer. Direct I/O is used
for disk, magnetic tape, most direct memory access (DMA) real-time devices, and
nonnetwork transfers, such as DMC11/DMR11 write transfers. For direct I/O, the
user’s buffer must be locked in memory during the transfer.
The system manager, or the person who creates the process, establishes the direct
I/O quota value in the user authorization file. If you use the SYS$SETRWM
system service to enable resource wait mode for the process, the process enters
resource wait mode if it attempts to exceed its direct I/O quota.

23.2.4 AST Quota


The AST quota specifies the maximum number of outstanding asynchronous
system traps that a process can have. The system manager, or the person who
creates the process, establishes the quota value in the user authorization file.
There is never an implied wait for that resource.

23.2.5 Physical I/O Privilege


Physical I/O privilege (PHY_IO) allows a process to perform physical I/O
operations on a device. Physical I/O privilege also allows a process to perform
logical I/O operations on a device.

System Service Input/Output Operations 23–3


System Service Input/Output Operations
23.2 Quotas, Privileges, and Protection

23.2.6 Logical I/O Privilege


Logical I/O privilege (LOG_IO) allows a process to perform logical I/O operations
on a device. A process can also perform physical operations on a device if the
process has logical I/O privilege, the volume is mounted foreign, and the volume
protection mask allows access to the device. (A foreign volume is one volume that
contains no standard file structure understood by any of the operating system
software.) See Section 23.3.2 for further information about logical I/O privilege.

23.2.7 Mount Privilege


Mount privilege (MOUNT) allows a process to use the IO$_MOUNT function to
perform mount operations on disk and magnetic tape devices. The IO$_MOUNT
function is used in ancillary control processs (ACP) interface operations.

23.2.8 Share Privilege


Share privilege (SHARE) allows a process to use the SYS$ASSIGN system service
to override another process’s exclusive access request on the specified device.
Performing any I/O operations to a device driver coded to expect exclusive
access—performing I/O to any device driver not explicitly coded to expect shared
multiple-process access—can result in unusual and unexpected device and
application behaviour, and can result in problems of device ownership, and
failures during the device driver last channel deassign operation.
Using SHARE to override access is useful for a few specific situations, such as
user-written device driver debugging and user-written device driver diagnostic
tools. General use of SHARE is not recommended.

23.2.9 Volume Protection


Volume protection protects the integrity of mailboxes and both foreign and
Files–11 On-Disk Structure Level 2 structured volumes. Volume protection for
a foreign volume is established when the volume is mounted. Volume protection
for a Files–11 structured volume is established when the volume is initialized. (If
the process mounting the volume has the override volume protection privilege,
VOLPRO, protection can be overridden when the volume is mounted.)
The SYS$CREMBX system service protection mask argument establishes mailbox
protection.
Set Protection QIO requests allow you to set volume protection on a mailbox. You
must either be the owner of the mailbox or have the BYPASS privilege.
Protection for structured volumes and mailboxes is provided by a volume
protection mask that contains four 4-bit fields. These fields correspond to the
four classes of user permitted to access the volume. (User classes are based on
the volume owner’s UIC.)
The 4-bit fields are interpreted differently for volumes that are mounted as
structured (that is, volumes serviced by an ACP), volumes that are mounted as
foreign, and mailboxes (both temporary and permanent).
Figure 23–1 shows the 4-bit protection fields for mailboxes. Usually, volume
protection is meaningful only for read and write operations.

23–4 System Service Input/Output Operations


System Service Input/Output Operations
23.2 Quotas, Privileges, and Protection

Figure 23–1 Mailbox Protection Fields

11 10 9 8

Logical I/O * Write Read

*Not Used ZK−0624−GE

23.2.10 Device Protection


Device protection protects the allocation of nonshareable devices, such as
terminals and card readers.
Protection is provided by a device protection mask similar to that of volume
protection. The difference is that only the bit corresponding to read access is
checked, and that bit determines whether the process can allocate or assign a
channel to the device.
You establish device protection with the DCL command SET PROTECTION
/DEVICE. This command sets both the protection mask and the device owner
UIC.

23.2.11 System Privilege


System UIC privilege (SYSPRV) allows a process to be eligible for the volume or
device protection specified for the system protection class, even if the process does
not have a UIC in one of the system groups.

23.2.12 Bypass Privilege


Bypass privilege (BYPASS) allows a process to bypass volume and device
protection completely.

23.3 Physical, Logical, and Virtual I/O


I/O data transfers can occur in any one of three device addressing modes:
physical, logical, or virtual. Any process with device access allowed by the volume
protection mask can perform logical I/O on a device that is mounted foreign;
physical I/O requires privileges. Virtual I/O does not require privileges; however,
intervention by an ACP to control user access might be necessary if the device
is under ACP control. (ACP functions are described in the OpenVMS I/O User’s
Reference Manual.)

23.3.1 Physical I/O Operations


In physical I/O operations, data is read from and written to the actual, physically
addressable units accepted by the hardware (for example, sectors on a disk or
binary characters on a terminal in the PASSALL mode). This mode allows direct
access to all device-level I/O operations.
Physical I/O requires that one of the following conditions be met:
• The issuing process has physical I/O privilege (PHY_IO).
• The issuing process has all of the following characteristics:
The issuing process has logical I/O privilege (LOG_IO).
The device is mounted foreign.

System Service Input/Output Operations 23–5


System Service Input/Output Operations
23.3 Physical, Logical, and Virtual I/O

The volume protection mask allows physical access to the device.


If neither of these conditions is met, the physical I/O operation is rejected by the
SYS$QIO system service, which returns a condition value of SS$_NOPRIV (no
privilege). Figure 23–2 illustrates the physical I/O access checks in greater detail.
The inhibit error-logging function modifier (IO$M_INHERLOG) can be specified
for all physical I/O functions. The IO$M_INHERLOG function modifier inhibits
the logging of any error that occurs during the I/O operation.

23.3.2 Logical I/O Operations


In logical I/O operations, data is read from and written to logically addressable
units of the device. Logical operations can be performed on both block-
addressable and record-oriented devices. For block-addressable devices (such
as disks), the addressable units are 512-byte blocks. They are numbered from
0 to n01, where n is the number of blocks on the device. For record-oriented or
non-block-structured devices (such as terminals), logical addressable units are
not pertinent and are ignored. Logical I/O requires that one of the following
conditions be met:
• The issuing process has physical I/O privilege (PHY_IO).
• The issuing process has logical I/O privilege (LOG_IO).
• The volume is mounted foreign and the volume protection mask allows access
to the device.
If none of these conditions is met, the logical I/O operation is rejected by the
SYS$QIO system service, which returns a condition value of SS$_NOPRIV (no
privilege). Figure 23–3 illustrates the logical I/O access checks in greater detail.

23.3.3 Virtual I/O Operations


You can perform virtual I/O operations on both record-oriented (non-file-
structured) and block-addressable (file-structured) devices. For record-oriented
devices (such as terminals), the virtual function is the same as a logical function;
the virtual addressable units of the devices are ignored.
For block-addressable devices (such as disks), data is read from and written
to open files. The addressable units in the file are 512-byte blocks. They are
numbered starting at 1 and are relative to a file rather than to a device. Block-
addressable devices must be mounted and structured and must contain a file that
was previously accessed on the I/O channel.
Virtual I/O operations also require that the volume protection mask allow
access to the device (a process having either physical or logical I/O privilege can
override the volume protection mask). If these conditions are not met, the virtual
I/O operation is rejected by the QIO system service, which returns one of the
following condition values:

Condition Value Meaning


SS$_NOPRIV No privilege
SS$_DEVNOTMOUNT Device not mounted
SS$_DEVFOREIGN Volume mounted foreign

Figure 23–4 shows the relationship of physical, logical, and virtual I/O to the
driver.

23–6 System Service Input/Output Operations


System Service Input/Output Operations
23.3 Physical, Logical, and Virtual I/O

Figure 23–2 Physical I/O Access Checks

Start

Yes Physical
I/O
Privilege
?
No

Logical No
I/O
Privilege
?
Yes

No File
Device
?

Yes

Device No
Mounted
?

Shareable Yes Yes


Device
?
No Mounted No
Foreign
?

Yes

Physical I/O No
Permitted*
?

Yes

Allow Deny
Access Access

*Volume protection mask allows access. ZK−0625−GE

System Service Input/Output Operations 23–7


System Service Input/Output Operations
23.3 Physical, Logical, and Virtual I/O

Figure 23–3 Logical I/O Access Checks

Start

Yes Physical
I/O
Privilege
?
No

Yes Logical No
I/O
Privilege
?
No Spooled
Device
?

No File Yes
Device
?

Yes

Device No
Mounted
?

Shareable Yes Yes


Device
?
No Mounted No
Foreign
?

Yes

Logical I/O No
Permitted*
?

Yes

Allow Deny
Access Access

* Volume protection mask allows access.


ZK−0626−GE

23–8 System Service Input/Output Operations


System Service Input/Output Operations
23.3 Physical, Logical, and Virtual I/O

Figure 23–4 Physical, Logical, and Virtual I/O

QIO
Request

No Physical Yes
I/O
Request
?

Logical Yes
I/O
Request
?
No
Translate Logical
Block Address
to Physical
Block Address

Virtual Yes
I/O
Request
?
No Map Virtual Block I/O
Address to Logical Driver
Block Address
Error

ACP No
Intervention*
?

Yes

Go to
ACP

Wake ACP to
Change Mapping
Window

*Needed to map virtual address to logical address.


ZK−0627−GE

System Service Input/Output Operations 23–9


System Service Input/Output Operations
23.4 I/O Function Encoding

23.4 I/O Function Encoding


I/O functions fall into three groups that correspond to the three I/O device
addressing modes (physical, logical, and virtual) described in Section 23.3.
Depending on the device to which it is directed, an I/O function can be expressed
in one, two, or all three modes.
I/O functions are described by 16-bit, symbolically expressed values that specify
the particular I/O operation to be performed and any optional function modifiers.
Figure 23–5 shows the format of the 16-bit function value.
Symbolic names for I/O function codes are defined by the $IODEF macro.

Figure 23–5 I/O Function Format

15 6 5 0

Function Modifiers Code

ZK−0628−GE

23.4.1 Function Codes


The low-order 6 bits of the function value are a code that specifies the particular
operation to be performed. For example, the code for read logical block is
expressed as IO$_READLBLK. Table 23–1 lists the symbolic values for read and
write I/O functions in the three transfer modes.

Table 23–1 Read and Write I/O Functions


Physical I/O Logical I/O Virtual I/O
IO$_READPBLK IO$_READLBLK IO$_READVBLK
IO$_WRITEPBLK IO$_WRITELBLK IO$_WRITEVBLK

The set mode I/O function has a symbolic value of IO$_SETMODE.


Function codes are defined for all supported devices. Although some of the
function codes (for example, IO$_READVBLK and IO$_WRITEVBLK) are used
with several types of devices, most are device dependent; that is, they perform
functions specific to particular types of devices. For example, IO$_CREATE is a
device-dependent function code; it is used only with file-structured devices such
as disks and magnetic tapes. The I/O user’s reference documentation provides
complete descriptions of the functions and function codes.

Note
You should determine the device class before performing any QIO
function, because the requested function might be incompatible with some
devices. For example, the SYS$INPUT device could be a terminal, a disk,
or some other device. Unless this device is a terminal, an IO$_SETMODE
request that enables a Ctrl/C AST is not performed.

23–10 System Service Input/Output Operations


System Service Input/Output Operations
23.4 I/O Function Encoding

23.4.2 Function Modifiers


The high-order 10 bits of the function value are function modifiers. These are
individual bits that alter the basic operation to be performed. For example,
you can specify the function modifier IO$M_NOECHO with the function IO$_
READLBLK to a terminal. When used together, the two values are written in
VAX MACRO as IO$_READLBLK!IO$M_NOECHO. This causes data typed at
the terminal keyboard to be entered into the user buffer but not echoed to the
terminal. Figure 23–6 shows the format of function modifiers.

Figure 23–6 Function Modifier Format

15 13 12 6 0

Device/Function Device/Function
Independent Dependent

ZK−0629−GE
As shown in Figure 23–6, bits <15:13> are device- or function-independent bits,
and bits <12:6> are device- or function-dependent bits. Device- or function-
dependent bits have the same meaning, whenever possible, for different device
classes. For example, the function modifier IO$M_ACCESS is used with both disk
and magnetic tape devices to cause a file to be accessed during a create operation.
Device- or function-dependent bits always have the same function within the
same device class.
There are two device- or function-independent modifier bits: IO$M_INHRETRY
and IO$M_DATACHECK (a third bit is reserved). IO$M_INHRETRY is used to
inhibit all error recovery. If any error occurs and this modifier bit is specified, the
operation is terminated immediately and a failure status is returned in the I/O
status block (see Section 23.10). Use IO$M_DATACHECK to compare the data in
memory with that on a disk or magnetic tape.

23.5 Assigning Channels


Before any input or output operation can be performed on a physical device, you
must assign a channel to the device to provide a path between the process and
the device. The Assign I/O Channel (SYS$ASSIGN) system service establishes
this path.
When you write a call to the SYS$ASSIGN service, you must supply the name
of the device, which can be a physical device name or a logical name, and the
address of a word to receive the channel number. The service returns a channel
number, and you use this channel number when you write an input or output
request.
For example, the following lines assign an I/O channel to the device TTA2. The
channel number is returned in the word at TTCHAN.

System Service Input/Output Operations 23–11


System Service Input/Output Operations
23.5 Assigning Channels

#include <descrip.h>
#include <lib$routines.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>
#include <stsdef.h>
main() {
unsigned int status;
unsigned short ttchan;
$DESCRIPTOR(ttname,"TTA2:");
/* Assign a channel to a device */
status = SYS$ASSIGN( &ttname, /* devnam - device name */
&ttchan, /* chan - channel number */
0, /* acmode - access mode */
0, /* mbxnam - logical name for mailbox */
0 ); /* flags */
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
return SS$_NORMAL;
}

To assign a channel to the current default input or output device, use the logical
name SYS$INPUT or SYS$OUTPUT.
For more details on how SYS$ASSIGN and other I/O services handle logical
names, see Section 23.2.5.

23.5.1 Using the Share Privilege with the SYS$ASSIGN and SYS$DASSGN
Services
Use of SHARE privilege should be made only with caution, as applications,
application protocols, and device drivers coded to expect only exclusive access can
encounter unexpected and potentially errant behavior when access to the device
is unexpectedly shared via use of SHARE privilege.
If you use the SHARE privilege to override the exclusivity requested by another
process’s call to the system service SYS$ASSIGN, and the original process then
attempts to deassign its channels via explicit calls to SYS$DASSGN or via the
implicit calls to SYS$DASSGN made during image or process rundown, the
OpenVMS last-channel-deassign code may not operate as expected due to the
assignment of the additional I/O channels to the device. The presence of these
extra channels will prevent the last-channel-deassign code from releasing the
ownership of the device, potentially resulting in a device owned by the process
identification (PID) of a nonexistent process.
Unless its use is explicitly supported by the application, the application protocol,
and the device driver, the use of SHARE privilege is generally discouraged.

23.6 Queuing I/O Requests


All input and output operations in the operating system are initiated with the
Queue I/O Request (SYS$QIO) system service. The SYS$QIO system service
permits direct interaction with the system’s terminal driver. SYS$QIOs permit
some operations that cannot be performed with language I/O statements and
RTL routines; calls to SYS$QIO reduce overhead and permit asynchronous I/O
operations. However, calls to SYS$QIO are device dependent. The SYS$QIO
service queues the request and returns immediately to the caller. While the

23–12 System Service Input/Output Operations


System Service Input/Output Operations
23.6 Queuing I/O Requests

operating system processes the request, the program that issued the request can
continue execution.
The format for SYS$QIO is as follows:
SYS$QIO([efn],chan,func[,iosb][,astadr][,astprm][,p1][,p2][,p3][,p4][,p5][,p6]
Required arguments to the SYS$QIO service include the channel number
assigned to the device on which the I/O is to be performed, and a function code
(expressed symbolically) that indicates the specific operation to be performed.
Depending on the function code, one to six additional parameters may be
required.
For example, the IO$_WRITEVBLK and IO$_READVBLK function codes are
device-independent codes used to read and write single records or virtual
blocks. These function codes are suitable for simple terminal I/O. They require
parameters indicating the address of an input or output buffer and the buffer
length. A call to SYS$QIO to write a line to a terminal may look like the
following:

#include <starlet.h>
unsigned int status, func=IO$_WRITEVBLK;
.
.
.
status = SYS$QIO(0, /* efn - event flag */
ttchan, /* chan - channel number */
func, /* func - function modifier */
0, /* iosb - I/O status block */
0, /* astadr - AST routine */
0, /* astprm - AST parameter */
buffadr, /* p1 - output buffer */
buflen); /* p2 - length of message */

Function codes are defined for all supported device types, and most of the codes
are device dependent; that is, they perform functions specific to a particular
device. The $IODEF macro defines symbolic names for these function codes.
For information about how to obtain a listing of these symbolic names, see
Appendix A. For details about all function codes and an explanation of the
parameters required by each, see the OpenVMS I/O User’s Reference Manual.
To read from or write to a terminal with the SYS$QIO or SYS$QIOW system
service, you must first associate the terminal name with an I/O channel by
calling the SYS$ASSIGN system service, then use the assigned channel in the
SYS$QIO or SYS$QIOW system service. To read from SYS$INPUT or write to
SYS$OUTPUT, specify the appropriate logical name as the terminal name in
the SYS$ASSIGN system service. In general, use SYS$QIO for asynchronous
operations, and use SYS$QIOW for all other operations.

23.7 Synchronizing Service Completion


The SYS$QIO system service returns control to the calling program as soon
as a request is queued; the status code returned in R0 indicates whether the
request was queued successfully. To ensure proper synchronization of the queuing
operation with respect to the program, the program must do the following:
• Test whether the operation was queued successfully.
• Test whether the operation itself completed successfully.

System Service Input/Output Operations 23–13


System Service Input/Output Operations
23.7 Synchronizing Service Completion

Optional arguments to the SYS$QIO service provide techniques for synchronizing


I/O completion. There are three methods you can use to test for the completion of
an I/O request:
• Specify the number of an event flag to be set when the operation completes.
• Specify the address of an AST routine to be executed when the operation
completes.
• Specify the address of an I/O status block in which the system can place the
return status when the operation completes.
I/O status blocks are explained in Section 23.10.
The use of these three techniques is shown in the examples that follow.
Example 23–1 shows specifying event flags.

23–14 System Service Input/Output Operations


System Service Input/Output Operations
23.7 Synchronizing Service Completion

Example 23–1 Event Flags


#include <lib$routines.h>
#include <starlet.h>
unsigned int status, efn=0, efn1=1, efn=2;
.
.
.
status = SYS$QIO(efn1, . . . ); /* Issue 1st I/O request */
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL( status ); /* Queued successfully? */ !
.
.
.
status = SYS$QIO(efn2, . . . ); /* Issue second I/O request */ "
if (!$VMS_STATUS_SUCCESS(status)) /* Queued successfully? */
LIB$SIGNAL( status );
.
.
. #
status = SYS$WFLAND( efn, / *Wait until both are done */
&mask, . . . $
.
.
.

! When you specify an event flag number as an argument, SYS$QIO clears the
event flag when it queues the I/O request. When the I/O completes, the flag
is set.
" In this example, the program issues two Queue I/O requests. A different
event flag is specified for each request.
# The Wait for Logical AND of Event Flags (SYS$WFLAND) system service
places the process in a wait state until both I/O operations are complete. The
efn argument indicates that the event flags are both in cluster 0; the mask
argument indicates the flags for which the process is to wait.
$ Note that the SYS$WFLAND system service (and the other wait system
services) wait for the event flag to be set; they do not wait for the I/O
operation to complete. If some other event were to set the required event
flags, the wait for event flag would complete too soon. You must coordinate
the use of event flags carefully. (See Section 23.8 for a discussion of the
recommended method for testing I/O completion.)

System Service Input/Output Operations 23–15


System Service Input/Output Operations
23.7 Synchronizing Service Completion

Example 23–2 shows specifying an AST routine.

Example 23–2 AST Routine

#include <lib$routines.h>
#include <starlet.h>
#include <stsdef.h>
unsigned int status, astprm=1;
.
.
.
status = SYS$QIO( . . . &ttast, /* I/O request with AST */ !
astprm . . . );
if (!$VMS_STATUS_SUCCESS( status )) /* Queued successfully? */
LIB$SIGNAL( status );
.
.
.
}
void ttast ( int astprm ) { /* AST service routine */ "
/* Handle I/O completion */
.
.
.
return;
} /* End of AST routine */

! When you specify the astadr argument to the SYS$QIO system service, the
system interrupts the process when the I/O completes and passes control to
the specified AST service routine.
The SYS$QIO system service call specifies the address of the AST routine,
TTAST, and a parameter to pass as an argument to the AST service routine.
When $QIO returns control, the process continues execution.
" When the I/O completes, the AST routine TTAST is called, and it responds to
the I/O completion. By examining the AST parameter, TTAST can determine
the origin of the I/O request.
When this routine is finished executing, control returns to the process at the
point at which it was interrupted. If you specify the astadr argument in your
call to SYS$QIO, you should also specify the iosb argument so that the AST
routine can evaluate whether the I/O completed successfully.

23–16 System Service Input/Output Operations


System Service Input/Output Operations
23.7 Synchronizing Service Completion

Example 23–3 shows specifying an I/O status block.

Example 23–3 I/O Status Block


#include <lib$routines.h>
#include <stdio.h>
#include <ssdef.h>
#include <starlet.h>
#include <stsdef.h>
.
.
.
/* I/O status block */
struct {
unsigned short iostat, iolen;
unsigned int dev_info;
}ttiosb; !
unsigned int status;
.
.
.
status = SYS$QIO(, . . . , &ttiosb, . . . ); "
if( !$VMS_STATUS_SUCCESS( status )) /* Queued successfully? */
LIB$SIGNAL( status );
.
.
.
while(ttiosb.iostat == 0) {
/* Loop -- with delay -- until done */ #
}
if( !$VMS_STATUS_SUCCESS( ttiosb.iostat )) {
/* Perform error handling */
.
.
.
}

! An I/O status block is a quadword structure that the system uses to post
the status of an I/O operation. You must define the quadword area in your
program. TTIOSB defines the I/O status block for this I/O operation. The
iosb argument in the SYS$QIO system service refers to this quadword.
" Instead of polling the low-order word of the I/O status block for the completion
status, the program uses the preferred method of using an event flag and
calling SYS$SYNCH to determine I/O completion.
# The process polls the I/O status block. If the low-order word still contains
zero, the I/O operation has not yet completed. In this example, the program
loops until the request is complete.

System Service Input/Output Operations 23–17


System Service Input/Output Operations
23.8 Recommended Method for Testing Asynchronous Completion

23.8 Recommended Method for Testing Asynchronous Completion


Compaq recommends that you use the Synchronize (SYS$SYNCH) system service
to wait for completion of an asynchronous event. The SYS$SYNCH service
correctly waits for the actual completion of an asynchronous event, even if some
other event sets the event flag.
To use the SYS$SYNCH service to wait for the completion of an asynchronous
event, you must specify both an event flag number and the address of an
I/O status block (IOSB) in your call to the asynchronous system service. The
asynchronous service queues the request and returns control to your program.
When the asynchronous service completes, it sets the event flag and places the
final status of the request in the IOSB.
In your call to SYS$SYNCH, you must specify the same efn and I/O status block
that you specified in your call to the asynchronous service. The SYS$SYNCH
service waits for the event flag to be set by means of the SYS$WAITFR system
service. When the specified event flag is set, SYS$SYNCH checks the specified
I/O status block. If the I/O status block is nonzero, the system service has
completed and SYS$SYNCH returns control to your program. If the I/O status
block is zero, SYS$SYNCH clears the event flag by means of the SYS$CLREF
service and calls the $WAITFR service to wait for the event flag to be set.
The SYS$SYNCH service sets the event flag before returning control to your
program. This ensures that the call to SYS$SYNCH does not interfere
with testing for completion of another asynchronous event that completes at
approximately the same time and uses the same event flag to signal completion.
The following call to the Queue I/O Request (SYS$QIO) system service
demonstrates how the SYS$SYNCH service is used:

.
.
.
#include <lib$routines.h>
#include <starlet.h>
unsigned int status, event_flag = 1;
struct {
short int iostat, iolen;
unsigned int dev_info;
}ttiosb;
.
.
.
/* Request I/O */
status = SYS$QIO (event_flag, . . . , &ttiosb . . . );
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL( status );
.
.
.
/* Wait until I/O completes */
status = SYS$SYNCH (event_flag, &ttiosb );
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL( status );
.
.
.

23–18 System Service Input/Output Operations


System Service Input/Output Operations
23.8 Recommended Method for Testing Asynchronous Completion

Note
The SYS$QIOW service provides a combination of SYS$QIO and
SYS$SYNCH.

23.9 Synchronous and Asynchronous Forms of Input/Output


Services
You can execute some input/output services either synchronously or
asynchronously. A ‘‘W’’ at the end of a system service name indicates the
synchronous version of the system service.
The synchronous version of a system service combines the functions of the
asynchronous version of the service and the Synchronize (SYS$SYNCH)
system service. The synchronous version acts exactly as if you had used the
asynchronous version of the system service followed immediately by a call to
SYS$SYNCH; it queues the I/O request, and then places the program in a wait
state until the I/O request completes. The synchronous version takes the same
arguments as the asynchronous version.
Table 23–2 lists the asynchronous and synchronous names of input/output
services that have synchronous versions.

Table 23–2 Asynchronous Input/Output Services and Their Synchronous


Versions
Asynchronous Name Synchronous Name Description
$BRKTHRU $BRKTHRUW Breakthrough
$GETDVI $GETDVIW Get Device/Volume Information
$GETJPI $GETJPIW Get Job/Process Information
$GETLKI $GETLKIW Get Lock Information
$GETQUI $GETQUIW Get Queue Information
$GETSYI $GETSYIW Get Systemwide Information
$QIO $QIOW Queue I/O Request
$SNDJBC $SNDJBCW Send to Job Controller
$UPDSEC $UPDSECW Update Section File on Disk

23.9.1 Reading Operations with SYS$QIOW


The SYS$QIO and SYS$QIOW system services move one record of data from
a terminal to a variable. For synchronous I/O, use SYS$QIOW. Complete
information about the SYS$QIO and SYS$QIOW system services is presented in
the OpenVMS System Services Reference Manual.

Note
Do not use the SYS$QIO and SYS$QIOW system services for input from
a file or nonterminal device.

System Service Input/Output Operations 23–19


System Service Input/Output Operations
23.9 Synchronous and Asynchronous Forms of Input/Output Services

The SYS$QIO and SYS$QIOW system services place the data read in the variable
specified in the 1 argument. The second word of the status block contains the
offset from the beginning of the buffer to the terminator—hence, it equals the size
of the data read. Always reference the data as a substring, using the offset to the
terminator as the position of the last character (that is, the size of the substring).
If you reference the entire buffer, your data will include the terminator for
the operation (for example, the CR character) and any excess characters from
a previous operation using the buffer. (The only exception to the substring
guideline is if you deliberately overflow the buffer to terminate the I/O operation.)
Example 23–4 shows use of the SYS$QIOW system service and reads a line of
data from the terminal and waits for the I/O to complete.

Example 23–4 Reading Data from the Terminal Synchronously


.
.
.
INTEGER STATUS
! QIOW structures
INTEGER*2 INPUT_CHAN ! I/O channel
INTEGER CODE, ! Type of I/O operation
2 INPUT_BUFF_SIZE, ! Size of input buffer
2 PROMPT_SIZE, ! Size of prompt
2 INPUT_SIZE ! Size of input line as read
PARAMETER (PROMPT_SIZE = 13,
2 INPUT_BUFF_SIZE = 132)
CHARACTER*132 INPUT
CHARACTER*(*) PROMPT
PARAMETER (PROMPT = ’Input value: ’)
! Define symbols used in I/O operations
INCLUDE ’($IODEF)’
! Status block for QIOW
STRUCTURE /IOSTAT_BLOCK/
INTEGER*2 IOSTAT, ! Return status
2 TERM_OFFSET, ! Location of line terminator
2 TERMINATOR, ! Value of terminator
2 TERM_SIZE ! Size of terminator
END STRUCTURE
RECORD /IOSTAT_BLOCK/ IOSB
! Subprograms
INTEGER*4 SYS$ASSIGN,
2 SYS$QIOW
.
.
.
! Assign an I/O channel to SYS$INPUT
STATUS = SYS$ASSIGN (’SYS$INPUT’,
2 INPUT_CHAN,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

(continued on next page)

23–20 System Service Input/Output Operations


System Service Input/Output Operations
23.9 Synchronous and Asynchronous Forms of Input/Output Services

Example 23–4 (Cont.) Reading Data from the Terminal Synchronously


! Read with prompt
CODE = IO$_READPROMPT
STATUS = SYS$QIOW (,
2 %VAL (INPUT_CHAN),
2 %VAL (CODE),
2 IOSB,
2 ,,
2 %REF (INPUT),
2 %VAL (INPUT_BUFF_SIZE),
2 ,,
2 %REF (PROMPT),
2 %VAL (PROMPT_SIZE))
! Check QIOW status
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Check status of I/O operation
IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT))
! Set size of input string
INPUT_SIZE = IOSB.TERM_OFFSET
.
.
.

23.9.2 Reading Operations with SYS$QIO


To perform an asynchronous read operation, use the SYS$QIO system service
and specify an event flag (the first argument, which must be passed by value).
Your program continues while the I/O is taking place. When you need the input
from the I/O operation, invoke the SYS$SYNCH system service to wait for the
event flag and status block specified in the SYS$QIO system service. If the
I/O is not complete, your program pauses until it is. In this manner, you can
overlap processing within your program. Naturally, you must take care not to
assume data has been returned by the I/O operation before you call SYS$SYNCH
and it returns successfully. Example 23–5 demonstrates an asynchronous read
operation.

Example 23–5 Reading Data from the Terminal Asynchronously


.
.
.
INTEGER STATUS
! QIO structures
INTEGER*2 INPUT_CHAN ! I/O channel
INTEGER CODE, ! Type of I/O operation
2 INPUT_BUFF_SIZE, ! Size of input buffer
2 PROMPT_SIZE, ! Size of prompt
2 INPUT_SIZE ! Size of input line as read
PARAMETER (INPUT_BUFF_SIZE = 132,
2 PROMPT = 13)
CHARACTER*132 INPUT
CHARACTER*(*) PROMPT
PARAMETER (PROMPT = ’Input value: ’)
INCLUDE ’($IODEF)’ ! Symbols used in I/O operations

(continued on next page)

System Service Input/Output Operations 23–21


System Service Input/Output Operations
23.9 Synchronous and Asynchronous Forms of Input/Output Services

Example 23–5 (Cont.) Reading Data from the Terminal Asynchronously


! Status block for QIO
STRUCTURE /IOSTAT_BLOCK/
INTEGER*2 IOSTAT, ! Return status
2 TERM_OFFSET, ! Location of line terminator
2 TERMINATOR, ! Value of terminator
2 TERM_SIZE ! Size of terminator
END STRUCTURE
RECORD /IOSTAT_BLOCK/ IOSB
! Event flag for I/O
INTEGER INPUT_EF
! Subprograms
INTEGER*4 SYS$ASSIGN,
2 SYS$QIO,
2 SYS$SYNCH,
2 LIB$GET_EF
.
.
.
! Assign an I/O channel to SYS$INPUT
STATUS = SYS$ASSIGN (’SYS$INPUT’,
2 INPUT_CHAN,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Get an event flag
STATUS = LIB$GET_EF (INPUT_EF)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Read with prompt
CODE = IO$_READPROMPT
STATUS = SYS$QIO (%VAL (INPUT_EF),
2 %VAL (INPUT_CHAN),
2 %VAL (CODE),
2 IOSB,
2 ,,
2 %REF (INPUT),
2 %VAL (INPUT_BUFF_SIZE),
2 ,,
2 %REF (PROMPT),
2 %VAL (PROMPT_SIZE))
! Check status of QIO
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
STATUS = SYS$SYNCH (%VAL (INPUT_EF),
2 IOSB)
! Check status of SYNCH
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Check status of I/O operation
IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT))
! Set size of input string
INPUT_SIZE = IOSB.TERM_OFFSET
.
.
.

Be sure to check the status of the I/O operation as returned in the I/O status
block. In an asynchronous operation, you can check this status only after the I/O
operation is complete (that is, after the call to SYS$SYNCH).

23–22 System Service Input/Output Operations


System Service Input/Output Operations
23.9 Synchronous and Asynchronous Forms of Input/Output Services

23.9.3 Write Operations with SYS$QIOW


The SYS$QIO and SYS$QIOW system services move one record of data from a
character value to the terminal. Do not use these system services, as described
here, for output to a file or nonterminal device.
For synchronous I/O, use SYS$QIOW and omit the first argument (the event flag
number). For complete information about SYS$QIO and SYS$QIOW, refer to the
OpenVMS System Services Reference Manual.
Example 23–6 writes a line of character data to the terminal.

Example 23–6 Writing Character Data to a Terminal


INTEGER STATUS,
2 ANSWER_SIZE
CHARACTER*31 ANSWER
INTEGER*2 OUT_CHAN
! Status block for QIO
STRUCTURE /IOSTAT_BLOCK/
INTEGER*2 IOSTAT,
2 BYTE_COUNT,
2 LINES_OUTPUT
BYTE COLUMN,
2 LINE
END STRUCTURE
RECORD /IOSTAT_BLOCK/ IOSB
! Routines
INTEGER SYS$ASSIGN,
2 SYS$QIOW
! IO$ symbol definitions
INCLUDE ’($IODEF)’
.
.
.
STATUS = SYS$ASSIGN (’SYS$OUTPUT’,
2 OUT_CHAN,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SYS$QIOW (,
2 %VAL (OUT_CHAN),
2 %VAL (IO$_WRITEVBLK),
2 IOSB,
2 ,
2 ,
2 %REF (’Answer: ’//ANSWER(1:ANSWER_SIZE)),
2 %VAL (8+ANSWER_SIZE),
2 ,
2 %VAL (32),,) ! Single spacing
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT))
END

23.10 I/O Completion Status


When an I/O operation completes, the system posts the completion status in the
I/O status block, if one is specified. The completion status indicates whether the
operation completed successfully, the number of bytes that were transferred, and
additional device-dependent return information.

System Service Input/Output Operations 23–23


System Service Input/Output Operations
23.10 I/O Completion Status

Figure 23–7 I/O Status Block

31 16 15 0
Count Condition value

Device−dependent information

ZK−0856−GE

Figure 23–7 illustrates the format for the SYS$QIO system service of the
information written in the IOSB.
The first word contains a system status code indicating the success or failure of
the operation. The status codes used are the same as for all returns from system
services; for example, SS$_NORMAL indicates successful completion.
The second word contains the number of bytes actually transferred in the I/O
operation. Note that for some devices this word contains only the low-order word
of the count. For information about specific devices, see the OpenVMS I/O User’s
Reference Manual.
The second longword contains device-dependent return information.
System services other than SYS$QIO use the quadword I/O status block, but the
format is different. See the description of each system service in the OpenVMS
System Services Reference Manual for the format of the information written in
the IOSB for that service.
To ensure successful I/O completion and the integrity of data transfers, you
should check the IOSB following I/O requests, particularly for device-dependent
I/O functions. For complete details about how to use the I/O status block, see the
OpenVMS I/O User’s Reference Manual.

23.11 Deassigning I/O Channels


When a process no longer needs access to an I/O device, it should release
the channel assigned to the device by calling the Deassign I/O Channel
(SYS$DASSGN) system service:
$DASSGN_S CHAN=TTCHAN
This service call releases the terminal channel assignment acquired in the
SYS$ASSIGN example shown in Section 23.5. The system automatically
deassigns channels for a process when the image that assigned the channel exits.

23.12 Using Complete Terminal I/O


The following example shows a complete sequence of input and output
operations using the $QIOW macro to read and write lines to the current
default SYS$INPUT device. Because the input/output of this program must be to
the current terminal, it functions correctly only if you execute it interactively.

23–24 System Service Input/Output Operations


System Service Input/Output Operations
23.12 Using Complete Terminal I/O

#include <descrip.h>
#include <iodef.h>
#include <lib$routines.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>
#include <string.h>
#define BUFSIZ 80
/* I/O status block */
struct { !
unsigned short iostat, ttiolen;
unsigned int dev_info;
}ttiosb;
main() {
unsigned int status ,outlen, inlen = BUFSIZ;
unsigned short ttchan;
char buffer[BUFSIZ]; "
$DESCRIPTOR(ttname,"SYS$INPUT"); #
/* Assign a channel */
status = SYS$ASSIGN(&ttname, /* devnam - device number */ $
&ttchan, /* chan - channel number */
0, 0, 0);
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL( status );
/* Request I/O */
status = SYS$QIOW(0, /* efn - event flag */
ttchan, /* chan - channel number */
IO$_READVBLK, /* func - function modifier */
&ttiosb, /* iosb - I/O status block */
0, /* astadr - AST routine */
0, /* astprm - AST parameter */
buffer, /* p1 - buffer */
inlen, /* p2 - length of buffer */
0, 0, 0, 0); %
if (!$VMS_STATUS_SUCCESS( status )) &
LIB$SIGNAL( status );
/* Get length from IOSB */
outlen = ttiosb.ttiolen; ’
status = SYS$QIOW(0, ttchan, IO$_WRITEVBLK, &ttiosb, 0, 0, buffer, outlen,
0, 0, 0, 0);
if (!$VMS_STATUS_SUCCESS( status ))
LIB$SIGNAL( status ); (
/* Deassign the channel */
status = SYS$DASSGN( ttchan ); /* chan - channel */ )
if (!$VMS_STATUS_SUCCESS( status ))
LIB$SIGNAL( status );
}
! The IOSB for the I/O operations is structured so that the program can easily
check for the completion status (in the first word) and the length of the input
string returned (in the second word).
" The string will be read into the buffer BUFFER; the longword OUTLEN will
contain the length of the string for the output operation.
# The TTNAME label is a character string descriptor for the logical device
SYS$INPUT, and TTCHAN is a word to receive the channel number assigned
to it.
$ The $ASSIGN service assigns a channel and writes the channel number at
TTCHAN.

System Service Input/Output Operations 23–25


System Service Input/Output Operations
23.12 Using Complete Terminal I/O

% If the $ASSIGN service completes successfully, the $QIOW macro reads a line
from the terminal, and requests that the completion status be posted in the
I/O status block defined at TTIOSB.
& The process waits until the I/O is complete, then checks the first word in the
I/O status block for a successful return. If unsuccessful, the program takes an
error path.
’ The length of the string read is moved into the longword at OUTLEN, because
the $QIOW macro requires a longword argument. However, the length field
of the I/O status block is only 1 word long. The $QIOW macro writes the line
just read to the terminal.
( The program performs error checks. First, it ensures that the $OUTPUT
macro successfully queued the I/O request; then, when the request is
completed, it ensures that the I/O was successful.
) When all I/O operations on the channel are finished, the channel is
deassigned.

23.13 Canceling I/O Requests


If a process must cancel I/O requests that have been queued but not yet
completed, it can issue the Cancel I/O On Channel (SYS$CANCEL) system
service. All pending I/O requests issued by the process on that channel are
canceled; you cannot specify a particular I/O request.
The SYS$CANCEL system service performs an asynchronous cancel operation.
This means that the application must wait for each I/O operation issued to the
driver to complete before checking the status for that operation.
For example, you can call the SYS$CANCEL system service as follows:

unsigned int status, efn1=3, efn2=4;


.
.
.
status = SYS$QIO(efn1, ttchan, &iosb1, . . . );
status = SYS$QIO(efn2, ttchan, &iosb2, . . . );
.
.
.
status = SYS$CANCEL(ttchan);
status = SYS$SYNCH(efn1, &iosb1);
status = SYS$SYNCH(efn2, &iosb2);

In this example, the SYS$CANCEL system service initiates the cancellation of all
pending I/O requests to the channel whose number is located at TTCHAN.
The SYS$CANCEL system service returns after initiating the cancellation of the
I/O requests. If the call to SYS$QIO specified either an event flag, AST service
routine, or I/O status block, the system sets either the flag, delivers the AST, or
posts the I/O status block as appropriate when the cancellation is completed.

23–26 System Service Input/Output Operations


System Service Input/Output Operations
23.14 Logical Names and Physical Device Names

23.14 Logical Names and Physical Device Names


When you specify a device name as input to an I/O system service, it can be a
physical device name or a logical name. If the device name contains a colon (:),
the colon and the characters after it are ignored. When an underscore character
( _ ) precedes a device name string, it indicates that the string is a physical device
name string, for example, _TTB3:.
Any string that does not begin with an underscore is considered a logical name,
even though it may be a physical device name. Table 23–3 lists system services
that translate a logical name iteratively until a physical device name is returned,
or until the system default number of translations have been performed.

Table 23–3 System Services for Translating Logical Names


System Service Definition
SYS$ALLOC Allocate Device
SYS$ASSIGN Assign I/O Channel
SYS$BRDCST Broadcast
SYS$DALLOC Deallocate Device
SYS$DISMOU Dismount Volume
SYS$GETDEV Get I/O Device Information
SYS$GETDVI Get Device/Volume Information
SYS$MOUNT Mount Volume

In each translation, the logical name tables defined by the logical name
LNM$FILE_DEV are searched in order. These tables, listed in search order,
are normally LNM$PROCESS, LNM$JOB, LNM$GROUP, and LNM$SYSTEM. If
a physical device name is located, the I/O request is performed for that device.
If the services do not locate an entry for the logical name, the I/O service treats
the name specified as a physical device name. When you specify the name of an
actual physical device in a call to one of these services, include the underscore
character to bypass the logical name translation.
When the SYS$ALLOC system service returns the device name of the physical
device that has been allocated, the device name string returned is prefixed
with an underscore character. When this name is used for the subsequent
SYS$ASSIGN system service, the SYS$ASSIGN service does not attempt to
translate the device name.
If you use logical names in I/O service calls, you must be sure to establish a
valid device name equivalence before program execution. You can do this either
by issuing a DEFINE command from the command stream, or by having the
program establish the equivalence name before the I/O service call with the
Create Logical Name (SYS$CRELNM) system service.
For details about how to create and use logical names, see Chapter 32.

System Service Input/Output Operations 23–27


System Service Input/Output Operations
23.15 Device Name Defaults

23.15 Device Name Defaults


If, after logical name translation, a device name string in an I/O system service
call does not fully specify the device name (that is, device, controller, and unit),
the service either provides default values for nonspecified fields, or provides
values based on device availability.
The following rules apply:
• The SYS$ASSIGN and SYS$DALLOC system services apply default values,
as shown in Table 23–4.
• The SYS$ALLOC system service treats the device name as a generic device
name and attempts to find a device that satisfies the components of the device
name specified, as shown in Table 23–4.

Table 23–4 Default Device Names for I/O Services


Device Device Name1 Generic Device
dd: ddA0: (unit 0 on controller ddxy: (any available device of the specified
A) type)
ddc: ddc0: (unit 0 on controller ddcy: (any available unit on the specified
specified) controller)
ddu: ddAu: (unit specified on ddxu: (device of specified type and unit on any
controller A) available controller)
ddcu: ddcu: (unit and controller ddcu: (unit and controller specified)
specified)
1 See the OpenVMS User’s Manual for a summary of the device names.
Key

dd—Specified device type (capital letters indicate a specific controller; numbers indicate a specific
unit)
c—Specified controller
x—Any controller
u—Specified unit number
y—Any unit number

23.16 Obtaining Information About Physical Devices


The Get Device/Volume Information (SYS$GETDVI) system service returns
information about devices. The information returned is specified by an item list
created before the call to SYS$GETDVI.
When you call the SYS$GETDVI system service, you must provide the address
of an item list that specifies the information to be returned. The format of the
item list is described in the description of SYS$GETDVI in the OpenVMS System
Services Reference Manual. The OpenVMS I/O User’s Reference Manual contains
details on the device-specific information these services return.
In cases where a generic (that is, nonspecific) device name is used in an I/O
service, a program may need to find out what device has been used. To do this,
the program should provide SYS$GETDVI with the number of the channel to
the device and request the name of the device with the DVI$_DEVNAM item
identifier.

23–28 System Service Input/Output Operations


System Service Input/Output Operations
23.16 Obtaining Information About Physical Devices

The operating system also supports a device called the null device for program
development. The mnemonic for the null device is NL. Its characteristics are as
follows:
• A read from NL returns an end-of-file error (SS$_ENDOFFILE).
• A write to NL immediately returns a success message (SS$_NORMAL).
The null device functions as a virtual device to which you can direct output but
from which the data does not return.

23.16.1 Checking the Terminal Device


You are restricted to a terminal device if you use any of the special functions
described in this section. If the user of your program redirects SYS$INPUT
or SYS$OUTPUT to a file or nonterminal device, an error occurs. You can use
the SYS$GETDVIW system service to make sure the logical name is associated
with a terminal, as shown in Example 23–7. SYS$GETDVIW returns a status
of SS$_IVDEVNAM if the logical name is defined as a file or otherwise does not
equate to a device name. The type of device is the response associated with the
DVI$_DEVCLASS request code and should be DC$_TERM for a terminal.

Example 23–7 Using SYS$GETDVIW to Verify the Device Name

RECORD /ITMLST/ DVI_LIST


LOGICAL*4 STATUS
! GETDVI buffers
INTEGER CLASS, ! Response buffer
2 CLASS_LEN ! Response length
! GETDVI symbols
INCLUDE ’($DCDEF)’
INCLUDE ’($SSDEF)’
INCLUDE ’($DVIDEF)’
! Define subprograms
INTEGER SYS$GETDVIW
! Find out the device class of SYS$INPUT
DVI_LIST.BUFLEN = 4
DVI_LIST.CODE = DVI$_DEVCLASS
DVI_LIST.BUFADR = %LOC (CLASS)
DVI_LIST.RETLENADR = %LOC (CLASS_LEN)
STATUS = SYS$GETDVIW (,,’SYS$INPUT’,
2 DVI_LIST,,,,,)
IF ((.NOT. STATUS) .AND. (STATUS .NE. SS$_IVDEVNAM)) THEN
CALL LIB$SIGNAL (%VAL (STATUS))
END IF
! Make sure device is a terminal
IF ((STATUS .NE. SS$_IVDEVNAM) .AND. (CLASS .EQ. DC$_TERM)) THEN
.
.
.
ELSE
TYPE *, ’Input device not a terminal’
END IF

23.16.2 Terminal Characteristics


The OpenVMS I/O User’s Reference Manual describes device-specific
characteristics associated with terminals. To examine a characteristic, issue
a call to SYS$QIO or SYS$QIOW system service with the IO$_SENSEMODE
function and examine the appropriate bit in the structure returned to the P1
argument. To change a characteristic:

System Service Input/Output Operations 23–29


System Service Input/Output Operations
23.16 Obtaining Information About Physical Devices

1. Issue a call to SYS$QIO or SYS$QIOW system service with the IO$_


SENSEMODE function.
2. Set or clear the appropriate bit in the structure returned to the P1 argument.
3. Issue a call to SYS$QIO or SYS$QIOW system service with the IO$_
SETMODE function passing, as the P1 argument, to modify the structure you
obtained from the sense mode operation.
Example 23–8 turns off the HOSTSYNC terminal characteristic. To check
whether NOHOSTSYNC has been set, enter the SHOW TERMINAL command.

Example 23–8 Disabling the HOSTSYNC Terminal Characteristic


.
.
.
INTEGER*4 STATUS
! I/O channel
INTEGER*2 INPUT_CHAN
! I/O status block
STRUCTURE /IOSTAT_BLOCK/
INTEGER*2 IOSTAT
BYTE TRANSMIT,
2 RECEIVE,
2 CRFILL,
2 LFFILL,
2 PARITY,
2 ZERO
END STRUCTURE
RECORD /IOSTAT_BLOCK/ IOSB
! Characteristics buffer
! Note: basic characteristics are first three
! bytes of second longword -- length is
! last byte
STRUCTURE /CHARACTERISTICS/
BYTE CLASS,
2 TYPE
INTEGER*2 WIDTH
UNION
MAP
INTEGER*4 BASIC
END MAP
MAP
BYTE LENGTH(4)
END MAP
END UNION
INTEGER*4 EXTENDED
END STRUCTURE
RECORD /CHARACTERISTICS/ CHARBUF
! Define symbols used for I/O and terminal operations
INCLUDE ’($IODEF)’
INCLUDE ’($TTDEF)’
! Subroutines
INTEGER*4 SYS$ASSIGN,
2 SYS$QIOW

(continued on next page)

23–30 System Service Input/Output Operations


System Service Input/Output Operations
23.16 Obtaining Information About Physical Devices

Example 23–8 (Cont.) Disabling the HOSTSYNC Terminal Characteristic


! Assign channel to terminal
STATUS = SYS$ASSIGN (’SYS$INPUT’,
2 INPUT_CHAN,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Get current characteristics
STATUS = SYS$QIOW (,
2 %VAL (INPUT_CHAN),
2 %VAL (IO$_SENSEMODE),
2 IOSB,,,
2 CHARBUF, ! Buffer
2 %VAL (12),,,,) ! Buffer size
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT))
! Turn off hostsync
CHARBUF.BASIC = IBCLR (CHARBUF.BASIC, TT$V_HOSTSYNC)
! Set new characteristics
STATUS = SYS$QIOW (,
2 %VAL (INPUT_CHAN),
2 %VAL (IO$_SETMODE),
2 IOSB,,,
2 CHARBUF,
2 %VAL (12),,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT))
END

If you modify terminal characteristics with set mode QIO operations, you should
save the characteristics buffer that you obtain on the first sense mode operation,
and restore those characteristics with a set mode operation before exiting.
(Resetting is not necessary if you just use modifiers on each read operation.) To
ensure that the restoration is performed if the program aborts (for example, if
the user presses Ctrl/Y), you should restore the user’s environment in an exit
handler. See Chapter 9 for a description of exit handlers.

23.16.3 Record Terminators


A QIO read operation ends when the user enters a terminator or when the input
buffer fills, whichever occurs first. The standard set of terminators applies unless
you specify the 4 argument in the read QIO operation. You can examine the
terminator that ended the read operation by examining the input buffer starting
at the terminator offset (second word of the I/O status block). The length, in
bytes, of the terminator is specified by the high-order word of the I/O status
block. The third word of the I/O status block contains the value of the first
character of the terminator.
Examining the terminator enables you to read escape sequences from the
terminal, provided that you modify the QIO read operation with the IO$M_
ESCAPE modifier (or the ESCAPE terminal characteristic is set). The first
character of the terminator will be the ESC character (an ASCII value of 27). The
remaining characters will contain the value of the escape sequence.

23.16.4 File Terminators


You must examine the terminator to detect end-of-file (Ctrl/Z) on the terminal.
No error condition is generated at the QIO level. If the user presses Ctrl/Z, the
terminator will be the SUB character (an ASCII value of 26).

System Service Input/Output Operations 23–31


System Service Input/Output Operations
23.17 Device Allocation

23.17 Device Allocation


Many I/O devices are shareable; that is, more than one process at a time can
access the device. By calling the Assign I/O Channel (SYS$ASSIGN) system
service, a process is given a channel to the device for I/O operations.
In some cases, a process may need exclusive use of a device so that data is not
affected by other processes. To reserve a device for exclusive use, you must
allocate it.
Device allocation is normally accomplished with the DCL command ALLOCATE.
A process can also allocate a device by calling the Allocate Device (SYS$ALLOC)
system service. When a device has been allocated by a process, only the process
that allocated the device and any subprocesses it creates can assign channels to
the device.
When you call the SYS$ALLOC system service, you must provide a device name.
The device name specified can be any of the following:
• A physical device name, for example, the tape drive MTB3:
• A logical name, for example, TAPE
• A generic device name, for example, MT:
If you specify a physical device name, SYS$ALLOC attempts to allocate the
specified device.
If you specify a logical name, SYS$ALLOC translates the logical name and
attempts to allocate the physical device name equated to the logical name.
If you specify a generic device name (that is, if you specify a device type but
do not specify a controller or unit number, or both), SYS$ALLOC attempts to
allocate any device available of the specified type. For more information about
the allocation of devices by generic names, see Section 23.15.
When you specify generic device names, you must provide fields for the
SYS$ALLOC system service to return the name and the length of the physical
device that is actually allocated so that you can provide this name as input to the
SYS$ASSIGN system service.
The following example illustrates the allocation of a tape device specified by the
logical name TAPE:

#include <descrip.h>
#include <lib$routines.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>
main() {
unsigned int status;
char devstr[64];
unsigned short phylen, tapechan;
$DESCRIPTOR(logdev,"TAPE"); /* Descriptor for logical name */
$DESCRIPTOR(devdesc,devstr); /* Descriptor for physical name */

23–32 System Service Input/Output Operations


System Service Input/Output Operations
23.17 Device Allocation

/* Allocate a device */
status = SYS$ALLOC( &logdev, /* devnam - device name */ !
&phylen, /* phylen - length device name string */
&devdesc, /* phybuf - buffer for devnam string */
0, 0);
if (!$VMS_STATUS_SUCCESS( status ))
LIB$SIGNAL( status );
/* Assign a channel to the device */
status = SYS$ASSIGN( &devdesc, /* devnam - device name */ "
&tapechan, /* chan - channel number */
0, 0, 0);
if (!$VMS_STATUS_SUCCESS( status ))
LIB$SIGNAL( status );
/* Deassign the channel */
status = SYS$DASSGN( tapechan ); /* chan - channel number */#
if (!$VMS_STATUS_SUCCESS( status ))
LIB$SIGNAL( status );
/* Deallocate the device */
status = SYS$DALLOC( &devdesc, /* devnam - device name */
0 ); /* acmode - access mode */
if (!$VMS_STATUS_SUCCESS( status ))
LIB$SIGNAL( status );
}
! The SYS$ALLOC system service call requests allocation of a device
corresponding to the logical name TAPE, defined by the character string
descriptor LOGDEV. The argument DEVDESC refers to the buffer provided
to receive the physical device name of the device that is allocated and the
length of the name string. The SYS$ALLOC service translates the logical
name TAPE and returns the equivalence name string of the device actually
allocated into the buffer at DEVDESC. It writes the length of the string in
the first word of DEVDESC.
" The SYS$ASSIGN command uses the character string returned by the
SYS$ALLOC system service as the input device name argument, and
requests that the channel number be written into TAPECHAN.
# When I/O operations are completed, the SYS$DASSGN system service
deassigns the channel, and the SYS$DALLOC system service deallocates the
device. The channel must be deassigned before the device can be deallocated.

23.17.1 Implicit Allocation


Devices that cannot be shared by more than one process (for example, terminals
and line printers) do not have to be explicitly allocated. Because they are
nonshareable, they are implicitly allocated by the SYS$ASSIGN system service
when SYS$ASSIGN is called to assign a channel to the device.

23.17.2 Deallocation
When the program has finished using an allocated device, it should release the
device with the Deallocate Device (SYS$DALLOC) system service to make it
available for other processes.
At image exit, the system automatically deallocates devices allocated by the
image.

System Service Input/Output Operations 23–33


System Service Input/Output Operations
23.18 Mounting, Dismounting, and Initializing Volumes

23.18 Mounting, Dismounting, and Initializing Volumes


This section introduces you to using system services to mount, dismount, and
initialize disk and tape volumes.

23.18.1 Mounting a Volume


Mounting a volume establishes a link between a volume, a device, and a process.
A volume, or volume set, must be mounted before I/O operations can be performed
on the volume. You interactively mount or dismount a volume from the DCL
command stream with the MOUNT or DISMOUNT command. A process can also
mount or dismount a volume or volume set programmatically using the Mount
Volume (SYS$MOUNT) or the Dismount Volume (SYS$DISMOU) system service,
respectively.
Mounting a volume involves two operations:
1. Place the volume on the device and start the device (by pressing the START
or LOAD button).
2. Mount the volume with the SYS$MOUNT system service.
23.18.1.1 Calling the SYS$MOUNT System Service
The Mount Volume (SYS$MOUNT) system service allows a process to mount a
single volume or a volume set. When you call the SYS$MOUNT system service,
you must specify a device name.
The SYS$MOUNT system service has a single argument, which is the address of
a list of item descriptors. The list is terminated by a longword of binary zeros.
Figure 23–8 shows the format of an item descriptor.

Figure 23–8 SYS$MOUNT Item Descriptor

31 15 0

Item code Buffer length

Buffer address

Return length address

ZK−1705−GE

Most item descriptors do not have to be in any order. To mount volume sets,
you must specify one item descriptor per device and one item descriptor per
volume; you must specify the descriptors for the volumes in the same order as the
descriptors for the devices on which the volumes are loaded.
For item descriptors other than device and volume names, if you specify the same
item descriptor more than once, the last occurrence of the descriptor is used.
The following example illustrates a call to SYS$MOUNT. The call is equivalent to
the DCL command that precedes the example.

23–34 System Service Input/Output Operations


System Service Input/Output Operations
23.18 Mounting, Dismounting, and Initializing Volumes

$ MOUNT/SYSTEM/NOQUOTA DRA4:,DRA5: USER01,USER02 USERD$

#include <descrip.h>
#include <lib$routines.h>
#include <mntdef.h>
#include <starlet.h>
#include <stdio.h>
.
.
.

struct {
unsigned short buflen, item_code;
void *bufaddr;
int *retlenaddr;
}itm;
struct itm itm[7];
main() {
.
.
.
unsigned int status, flags;
$DESCRIPTOR(dev1,"DRA4:");
$DESCRIPTOR(vol1,"USER01");
$DESCRIPTOR(dev2,"DRA5:");
$DESCRIPTOR(vol2,"USER02");
$DESCRIPTOR(log,"USERD$:");
flags = MNT$M_SYSTEM | MNT$M_NODISKQ;
i = 0;
itm[i].buflen = sizeof( flags );
itm[i].item_code = MNT$_FLAGS;
itm[i].bufaddr = flags;
itm[i++].retlenaddr = NULL;
itm[i].buflen = dev1.dsc$w_length;
itm[i].item_code = MNT$_DEVNAM;
itm[i].bufaddr = dev1.dsc$a_pointer;
itm[i++].retlenaddr = NULL;
itm[i].buflen = vol1.dsc$w_length;
itm[i].item_code = MNT$_VOLNAM;
itm[i].bufaddr = vol1.dsc$a_pointer;
itm[i++].retlenaddr = NULL;
itm[i].buflen = dev2.dsc$w_length;
itm[i].item_code = MNT$_DEVNAM;
itm[i].bufaddr = dev2.dsc$a_pointer;
itm[i++].retlenaddr = NULL;
itm[i].buflen = vol2.dsc$w_length;
itm[i].item_code = MNT$_VOLNAM;
itm[i].bufaddr = vol2.dsc$a_pointer;
itm[i++].retlenaddr = NULL;
itm[i].buflen = log.dsc$w_length;
itm[i].item_code = MNT$_LOGNAM;
itm[i].bufaddr = log.dsc$a_pointer;
itm[i++].retlenaddr = NULL;
itm[i].buflen = 0;
itm[i].item_code = 0;
itm[i].bufaddr = NULL;
itm[i++].retlenaddr = NULL;

System Service Input/Output Operations 23–35


System Service Input/Output Operations
23.18 Mounting, Dismounting, and Initializing Volumes

.
.
.
status = SYS$MOUNT ( itm );
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL( status );
.
.
.
}
23.18.1.2 Calling the SYS$DISMOU System Service
The SYS$DISMOU system service allows a process to dismount a volume or
volume set. When you call SYS$DISMOU, you must specify a device name. If the
volume mounted on the device is part of a fully mounted volume set, and you do
not specify flags, the whole volume set is dismounted.
The following example illustrates a call to SYS$DISMOU. The call dismounts the
volume set mounted in the previous example.

$DESCRIPTOR(dev1_desc,"DRA4:");
.
.
.
status = SYS$DISMOU(&dev1_desc); /* devnam - device */
.
.
.

23.18.2 Initializing Volumes


Initializing a volume writes a label on the volume, sets protection and ownership
for the volume, formats the volume (depending on the device type), and overwrites
data already on the volume.
You interactively initialize a volume from the DCL command stream using the
INITIALIZE command. A process can programmatically initialize a volume using
the Initialize Volume (SYS$INIT_VOL) system service.
23.18.2.1 Calling the Initialize Volume System Service
You must specify a device name and a new volume name when you call the
SYS$INIT_VOL system service. You can also use the itmlst argument of $INIT_
VOL to specify options for the initialization. For example, you can specify that
data compaction should be performed by specifying the INIT$_COMPACTION
item code. See the OpenVMS System Services Reference Manual for more
information on initialization options.
Before initializing the volume with SYS$INIT_VOL, be sure you have placed the
volume on the device and started the device (by pressing the START or LOAD
button).
The default format for files on disk volumes is called Files–11 On-Disk Structure
Level 2. Files–11 On-Disk Structure Level 1 format, available on VAX systems, is
used by other Compaq operating systems, including RSX–11M, RSX–11M–PLUS,
RSX–11D, and IAS, but is not supported on Alpha systems. For more information,
see the OpenVMS System Manager’s Manual.
Here are two examples of calling SYS$INIT_VOL programmatically: one from a
C program and one from a BASIC program.

23–36 System Service Input/Output Operations


System Service Input/Output Operations
23.18 Mounting, Dismounting, and Initializing Volumes

The following example illustrates a call to SYS$INIT_VOL from Compaq C:

#include <descrip.h>
#include <initdef.h>
#include <lib$routines.h>
#include <starlet.h>
#include <stsdef.h>
struct item_descrip_3
{
unsigned short buffer_size;
unsigned short item_code;
void *buffer_address;
unsigned short *return_length;
};
main ()
{
unsigned long
density_code,
status;
$DESCRIPTOR(drive_dsc, "MUA0:");
$DESCRIPTOR(label_dsc, "USER01");
struct
{
struct item_descrip_3 density_item;
long terminator;
} init_itmlst;
/*
** Initialize the input item list.
*/
density_code = INIT$K_DENSITY_6250_BPI;
init_itmlst.density_item.buffer_size = 4;
init_itmlst.density_item.item_code = INIT$_DENSITY;
init_itmlst.density_item.buffer_address = &density_code;
init_itmlst.terminator = 0;
/*
** Initialize the volume.
*/
status = SYS$INIT_VOL (&drive_dsc, &label_dsc, &init_itmlst);
/*
** Report an error if one occurred.
*/
if (!$VMS_STATUS_SUCCESS (status ))
LIB$STOP (status);
}
The following example illustrates a call to SYS$INIT_VOL from VAX BASIC:

OPTION TYPE = EXPLICIT


%INCLUDE ’$INITDEF’ %FROM %LIBRARY
EXTERNAL LONG FUNCTION SYS$INIT_VOL

System Service Input/Output Operations 23–37


System Service Input/Output Operations
23.18 Mounting, Dismounting, and Initializing Volumes

RECORD ITEM_DESC
VARIANT
CASE
WORD BUFLEN
WORD ITMCOD
LONG BUFADR
LONG LENADR
CASE
LONG TERMINATOR
END VARIANT
END RECORD
DECLARE LONG RET_STATUS, &
ITEM_DESC INIT_ITMLST(2)
! Initialize the input item list.
INIT_ITMLST(0)::ITMCOD = INIT$_READCHECK
INIT_ITMLST(1)::TERMINATOR = 0
! Initialize the volume.
RET_STATUS = SYS$INIT_VOL ("DJA21:" BY DESC, "USERVOLUME" BY DESC,
INIT_ITMLST() BY REF)

23.19 Formatting Output Strings


When you are preparing output strings for a program, you may need to insert
variable information into a string prior to output, or you may need to convert
a numeric value to an ASCII string. The Formatted ASCII Output (SYS$FAO)
system service performs these functions.
Input to the SYS$FAO system service consists of the following:
• A control string that contains the fixed text portion of the output and
formatting directives. The directives indicate the position within the string
where substitutions are to be made, and describe the data type and length of
the input values that are to be substituted or converted.
• An output buffer to contain the string after conversions and substitutions
have been made.
• An optional argument indicating a word to receive the final length of the
formatted output string.
• Parameters that provide arguments for the formatting directives.
The following example shows a call to the SYS$FAO system service to format an
output string for a SYS$QIOW macro. Complete details on how to use SYS$FAO,
with additional examples, are provided in the description of the SYS$FAO system
service in the OpenVMS System Services Reference Manual.

#include <descrip.h>
#include <lib$routines.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>
#include <stsdef.h>
main() {

23–38 System Service Input/Output Operations


System Service Input/Output Operations
23.19 Formatting Output Strings

unsigned int status, faolen;


char faobuf[80];
$DESCRIPTOR(faostr,"FILE !AS DOES NOT EXIST"); !
$DESCRIPTOR(outbuf, faobuf); "
$DESCRIPTOR(filespec,"DISK$USER:MYFILE.DAT"); #
status = SYS$FAO( &faostr, &outlen, &outbuf, &filespec ); $
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
.
.
.
status = SYS$QIOW( . . . faobuf, outlen, . . . ); %
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
.
.
.
}
! FAOSTR provides the FAO control string. !AS is an example of an FAO
directive: it requires an input parameter that specifies the address of a
character string descriptor. When SYS$FAO is called to format this control
string, !AS will be substituted with the string whose descriptor address is
specified.
" FAODESC is a character string descriptor for the output buffer; SYS$FAO
writes the string into the buffer, and writes the length of the final formatted
string in the low-order word of FAOLEN. (A longword is reserved so that it
can be used for an input argument to the SYS$QIOW macro.)
# FILESPEC is a character string descriptor defining an input string for the
FAO directive !AS.
$ The call to SYS$FAO specifies the control string, the output buffer and length
fields, and the parameter P1, which is the address of the string descriptor for
the string to be substituted.
% When SYS$FAO completes successfully, SYS$QIOW writes the following
output string:
FILE DISK$USER:MYFILE.DAT DOES NOT EXIST

23.20 Mailboxes
Mailboxes are virtual devices that can be used for communication among
processes. You accomplish actual data transfer by using OpenVMS RMS or I/O
services. When the Create Mailbox and Assign Channel (SYS$CREMBX) system
service creates a mailbox, it also assigns a channel to it for use by the creating
process. Other processes can then assign channels to the mailbox using either
the SYS$CREMBX or SYS$ASSIGN system service.
The SYS$CREMBX system service creates the mailbox. The SYS$CREMBX
system service identifies a mailbox by a user-specified logical name and assigns
it an equivalence name. The equivalence name is a physical device name in the
format MBAn, where n is a unit number. The equivalence name has the terminal
attribute.

System Service Input/Output Operations 23–39


System Service Input/Output Operations
23.20 Mailboxes

When another process assigns a channel to the mailbox with the SYS$CREMBX
or SYS$ASSIGN system service, it can identify the mailbox by its logical name.
The service automatically translates the logical name. The process can obtain
the MBAn name either by translating the logical name (with the SYS$TRNLNM
system service), or by calling the Get Device/Volume Information (SYS$GETDVI)
system service to obtain the unit number and the physical device name.
On VAX systems, channels assigned to mailboxes can be either bidirectional or
unidirectional. Bidirectional channels (read/write) allow both SYS$QIO read and
SYS$QIO write requests to be issued to the channel. Unidirectional channels
(read-only or write-only) allow only a read request or a write request to the
channel. The unidirectional channels and unidirectional $QIO function modifiers
provide for greater synchronization between users of the mailbox.
On VAX systems, the Create Mailbox and Assign Channel (SYS$CREMBX) and
Assign I/O Channel (SYS$ASSIGN) system services use the flags argument to
enable unidirectional channels. If the flags argument is not specified or is zero,
then the channel assigned to the mailbox is bidirectional (read/write). For more
information, see the discussion and programming examples in the mailbox driver
chapter in the OpenVMS I/O User’s Reference Manual. Chapter 3 of this manual
also discusses the use of mailboxes.
Mailboxes are either temporary or permanent. You need the user privileges
TMPMBX and PRMMBX to create temporary and permanent mailboxes,
respectively.
For a temporary mailbox, the SYS$CREMBX service enters the logical name and
equivalence name in the logical name table LNM$TEMPORARY_MAILBOX. This
logical name table name usually specifies the LNM$JOB logical name table name.
The system deletes a temporary mailbox when no more channels are assigned to
it.
For a permanent mailbox, the SYS$CREMBX service enters the logical name and
equivalence name in the logical name table LNM$PERMANENT_MAILBOX. This
logical name table name usually specifies the LNM$SYSTEM logical name table
name. Permanent mailboxes continue to exist until they are specifically marked
for deletion with the Delete Mailbox (SYS$DELMBX) system service.
The following example shows how processes can communicate by means of a
mailbox:

/* Process ORION */
#include <descrip.h>
#include <iodef.h>
#include <lib$routines.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>
#define MBXBUFSIZ 128
#define MBXBUFQUO 384
/* I/O status block */
struct {
unsigned short iostat, iolen;
unsigned int remainder;
}mbxiosb;

23–40 System Service Input/Output Operations


System Service Input/Output Operations
23.20 Mailboxes

main() {
void *p1, mbxast();
char mbuffer[MBXBUFSIZ], prmflg=0;
unsigned short mbxchan, mbxiosb;
unsigned int status, outlen;
unsigned int mbuflen=MBXBUFSIZ, bufquo=MBXBUFQUO, promsk=0;
$DESCRIPTOR(mblognam,"GROUP100_MAILBOX");
/* Create a mailbox */
status = SYS$CREMBX( prmflg, /* Permanent or temporary */ !
&mbxchan, /* chan - channel number */
mbuflen, /* maxmsg - buffer length */
bufquo, /* bufquo - quota */
promsk, /* promsk - protection mask */
0, /* acmode - access mode */
&mblognam, /* lognam - mailbox logical name */
0); /* flags - options */
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
.
.
.
/* Request I/O */
status = SYS$QIO(0, /* efn - event flag */ "
mbxchan, /* chan - channel number */
IO$_READVBLK, /* func - function modifier */
&mbxiosb, /* iosb - I/O status block */
&mbxast, /* astadr - AST routine */
&mbuffer, /* p1 - output buffer */
mbuflen); /* p2 - length of buffer */
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
.
.
.
}
void mbxast(void) { #
if (mbxiosb.iostat != SS$_NORMAL)
status = SYS$QIOW( . . . , &mbuffer, &outlen, . . . )
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
return;
}

/* Process Cygnus */
#include <descrip.h>
#include <iodef.h>
#include <lib$routines.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>
#include <stsdef.h>
#define MBXBUFSIZ 128
main() {
unsigned short int mailchan;
unsigned int status, outlen;
char outbuf[MBXBUFSIZ];
$DESCRIPTOR(mailbox,"GROUP100_MAILBOX");

System Service Input/Output Operations 23–41


System Service Input/Output Operations
23.20 Mailboxes

status = SYS$ASSIGN(&mailbox, &mailchan, 0, 0, 0); $


if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
.
.
.
status = SYS$QIOW(0, mailchan, 0, 0, 0, 0, &outbuf, outlen, 0, 0, 0, 0)
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
.
.
.
}
! Process ORION creates the mailbox and receives the channel number at
MBXCHAN.
The prmflg argument indicates that the mailbox is a temporary mailbox.
The logical name is entered in the LNM$TEMPORARY_MAILBOX logical
name table.
The maxmsg argument limits the size of messages that the mailbox can
receive. Note that the size indicated in this example is the same size as the
buffer (MBUFFER) provided for the SYS$QIO request. A buffer for mailbox
I/O must be at least as large as the size specified in the maxmsg argument.
When a process creates a temporary mailbox, the amount of system memory
allocated for buffering messages is subtracted from the process’s buffer quota.
Use the bufquo argument to specify how much of the process quota should
be used for mailbox message buffering.
Mailboxes are protected devices. By specifying a protection mask with the
promsk argument, you can restrict access to the mailbox. (In this example,
all bits in the mask are clear, indicating unlimited read and write access.)
" After creating the mailbox, process ORION calls the SYS$QIO system service,
requesting that it be notified when I/O completes (that is, when the mailbox
receives a message) by means of an AST interrupt. The process can continue
executing, but the AST service routine at MBXAST will interrupt and begin
executing when a message is received.
# When a message is sent to the mailbox (by CYGNUS), the AST is delivered
and ORION responds to the message. Process ORION gets the length of the
message from the first word of the I/O status block at MBXIOSB and places it
in the longword OUTLEN so it can pass the length to SYS$QIOW_S.
$ Process CYGNUS assigns a channel to the mailbox, specifying the logical
name the process ORION gave the mailbox. The SYS$QIOW system service
writes a message from the output buffer provided at OUTBUF.
Note that on a write operation to a mailbox, the I/O is not complete until
the message is read, unless you specify the IO$M_NOW function modifier.
Therefore, if SYS$QIOW (without the IO$M_NOW function modifier) is used
to write the message, the process will not continue executing until another
process reads the message.

23–42 System Service Input/Output Operations


System Service Input/Output Operations
23.20 Mailboxes

23.20.1 Mailbox Name


The lognam argument to the SYS$CREMBX service specifies a descriptor that
points to a character string for the mailbox name.
Translation of the lognam argument proceeds as follows:
1. The current name string is prefixed with MBX$ and the result is subject to
logical name translation.
2. If the result is a logical name, step 1 is repeated until translation does not
succeed or until the number of translations performed exceeds the number
specified by the SYSGEN parameter LNM$C_MAXDEPTH.
3. The MBX$ prefix is stripped from the current name string that could not be
translated. This current string is made a logical name with an equivalence
name MBAn (n is a number assigned by the system).
For example, assume that you have made the following logical name assignment:
$ DEFINE MBX$CHKPNT CHKPNT_001
Assume also that your program contains the following statements:
$DESCRIPTOR(mbxdesc,"CHKPNT");
.
.
.
status = SYS$CREMBX( . . . ,&mbxdesc, . . . );
The following logical name translation takes place:
1. MBX$ is prefixed to CHKPNT.
2. MBX$CHKPNT is translated to CHKPNT_001.
Because further translation is unsuccessful, the logical name CHKPNT_001 is
created with the equivalence name MBAn (n is a number assigned by the system).
There are two exceptions to the logical name translation method discussed in this
section:
• If the name string starts with an underscore ( _ ), the operating system strips
the underscore and considers the resultant string to be the actual name (that
is, further translation is not performed).
• If the name string is the result of a logical name translation, then the name
string is checked to see whether it has the terminal attribute. If the name
string is marked with the terminal attribute, the operating system considers
the resultant string to be the actual name (that is, further translation is not
performed).

23.20.2 System Mailboxes


The system uses mailboxes for communication among system processes. All
system mailbox messages contain, in the first word of the message, a constant
that identifies the sender of the message. These constants have symbolic names
(defined in the $MSGDEF macro) in the following format:
MSG$_sender

System Service Input/Output Operations 23–43


System Service Input/Output Operations
23.20 Mailboxes

The symbolic names included in the $MSGDEF macro and their meanings are as
follows:

Symbolic Name Meaning


MSG$_TRMUNSOLIC Unsolicited terminal data
MSG$_CRUNSOLIC Unsolicited card reader data
MSG$_ABORT Network partner aborted link
MSG$_CONFIRM Network connect confirm
MSG$_CONNECT Network inbound connect initiate
MSG$_DISCON Network partner disconnected
MSG$_EXIT Network partner exited prematurely
MSG$_INTMSG Network interrupt message; unsolicited data
MSG$_PATHLOST Network path lost to partner
MSG$_PROTOCOL Network protocol error
MSG$_REJECT Network connect reject
MSG$_THIRDPARTY Network third-party disconnect
MSG$_TIMEOUT Network connect timeout
MSG$_NETSHUT Network shutting down
MSG$_NODEACC Node has become accessible
MSG$_NODEINACC Node has become inaccessible
MSG$_EVTAVL Events available to DECnet Event Logger
MSG$_EVTRCVCHG Event receiver database change
MSG$_INCDAT Unsolicited incoming data available
MSG$_RESET Request to reset the virtual circuit
MSG$_LINUP PVC line up
MSG$_LINDWN PVC line down
MSG$_EVTXMTCHG Event transmitter database change

The remainder of the message contains variable information, depending on the


system component that is sending the message.
The format of the variable information for each message type is documented with
the system function that uses the mailbox.

23.20.3 Mailboxes for Process Termination Messages


When a process creates another process, it can specify the unit number of a
mailbox as an argument to the Create Process ($CREPRC) system service. When
you delete the created process, the system sends a message to the specified
termination mailbox.
You cannot use a mailbox in memory shared by multiple processors as a process
termination mailbox.

23–44 System Service Input/Output Operations


System Service Input/Output Operations
23.21 Example of Using I/O Services

23.21 Example of Using I/O Services


In the following Fortran example, the first program, SEND.FOR, creates a
mailbox named MAIL_BOX, writes data to it, and then indicates the end of the
data by writing an end-of-file message.
The second program, RECEIVE.FOR, creates a mailbox with the same logical
name, MAIL_BOX. It reads the messages from the mailbox into an array. It stops
the read operations when a read operation generates an end-of-file message and
the second longword of the I/O status block is nonzero. By checking that the I/O
status block is nonzero, the second program confirms that the writing process
sent the end-of-file message.
The processes use common event flag number 64 to ensure that SEND.FOR
does not exit until RECEIVE.FOR has established a channel to the mailbox. (If
RECEIVE.FOR executes first, an error occurs because SYS$ASSIGN cannot find
the mailbox.)

SEND.FOR
INTEGER STATUS
! Name and channel number for mailbox
CHARACTER*(*) MBX_NAME
PARAMETER (MBX_NAME = ’MAIL_BOX’)
INTEGER*2 MBX_CHAN
! Mailbox message
CHARACTER*80 MBX_MESSAGE
INTEGER LEN
CHARACTER*80 MESSAGES (255)
INTEGER MESSAGE_LEN (255)
INTEGER MAX_MESSAGE
PARAMETER (MAX_MESSAGE = 255)
! I/O function codes and status block
INCLUDE ’($IODEF)’
INTEGER*4 WRITE_CODE
INTEGER*2 IOSTAT,
2 MSG_LEN
INTEGER READER_PID
COMMON /IOBLOCK/ IOSTAT,
2 MSG_LEN,
2 READER_PID
! System routines
INTEGER SYS$CREMBX,
2 SYS$ASCEFC,
2 SYS$WAITFR,
2 SYS$QIOW
! Create the mailbox.
STATUS = SYS$CREMBX (,
2 MBX_CHAN,
2 ,,,,
2 MBX_NAME)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Fill MESSAGES array
.
.
.

System Service Input/Output Operations 23–45


System Service Input/Output Operations
23.21 Example of Using I/O Services

! Write the messages.


DO I = 1, MAX_MESSAGE
WRITE_CODE = IO$_WRITEVBLK .OR. IO$M_NOW
MBX_MESSAGE = MESSAGES(I)
LEN = MESSAGE_LEN(I)
STATUS = SYS$QIOW (,
2 %VAL(MBX_CHAN), ! Channel
2 %VAL(WRITE_CODE), ! I/O code
2 IOSTAT, ! Status block
2 ,,
2 %REF(MBX_MESSAGE), ! P1
2 %VAL(LEN),,,,) ! P2
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
IF (.NOT. IOSTAT) CALL LIB$SIGNAL (%VAL(STATUS))
END DO
! Write end of file
WRITE_CODE = IO$_WRITEOF .OR. IO$M_NOW
STATUS = SYS$QIOW (,
2 %VAL(MBX_CHAN), ! Channel
2 %VAL(WRITE_CODE), ! End of file code
2 IOSTAT, ! Status block
2 ,,,,,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
IF (.NOT. IOSTAT) CALL LIB$SIGNAL (%VAL(IOSTAT))
.
.
.
! Make sure cooperating process can read the information
! by waiting for it to assign a channel to the mailbox.
STATUS = SYS$ASCEFC (%VAL(64),
2 ’CLUSTER’,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
STATUS = SYS$WAITFR (%VAL(64))
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
END

RECEIVE.FOR
INTEGER STATUS
INCLUDE ’($IODEF)’
INCLUDE ’($SSDEF)’
! Name and channel number for mailbox
CHARACTER*(*) MBX_NAME
PARAMETER (MBX_NAME = ’MAIL_BOX’)
INTEGER*2 MBX_CHAN
! QIO function code
INTEGER READ_CODE
! Mailbox message
CHARACTER*80 MBX_MESSAGE
INTEGER*4 LEN
! Message arrays
CHARACTER*80 MESSAGES (255)
INTEGER*4 MESSAGE_LEN (255)
! I/O status block
INTEGER*2 IOSTAT,
2 MSG_LEN
INTEGER READER_PID
COMMON /IOBLOCK/ IOSTAT,
2 MSG_LEN,
2 READER_PID

23–46 System Service Input/Output Operations


System Service Input/Output Operations
23.21 Example of Using I/O Services

! System routines
INTEGER SYS$ASSIGN,
2 SYS$ASCEFC,
2 SYS$SETEF,
2 SYS$QIOW
! Create the mailbox and let the other process know
STATUS = SYS$ASSIGN (MBX_NAME,
2 MBX_CHAN,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
STATUS = SYS$ASCEFC (%VAL(64),
2 ’CLUSTER’,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
STATUS = SYS$SETEF (%VAL(64))
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Read first message
READ_CODE = IO$_READVBLK .OR. IO$M_NOW
LEN = 80
STATUS = SYS$QIOW (,
2 %VAL(MBX_CHAN), ! Channel
2 %VAL(READ_CODE), ! Function code
2 IOSTAT, ! Status block
2 ,,
2 %REF(MBX_MESSAGE), ! P1
2 %VAL(LEN),,,,) ! P2
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
IF ((.NOT. IOSTAT) .AND.
2 (IOSTAT .NE. SS$_ENDOFFILE)) THEN
CALL LIB$SIGNAL (%VAL(IOSTAT))
ELSE IF (IOSTAT .NE. SS$_ENDOFFILE) THEN
I = 1
MESSAGES(I) = MBX_MESSAGE
MESSAGE_LEN(I) = MSG_LEN
END IF
! Read messages until cooperating process writes end-of-file
DO WHILE (.NOT. ((IOSTAT .EQ. SS$_ENDOFFILE) .AND.
2 (READER_PID .NE. 0)))
STATUS = SYS$QIOW (,
2 %VAL(MBX_CHAN), ! Channel
2 %VAL(READ_CODE), ! Function code
2 IOSTAT, ! Status block
2 ,,
2 %REF(MBX_MESSAGE), ! P1
2 %VAL(LEN),,,,) ! P2
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
IF ((.NOT. IOSTAT) .AND.
2 (IOSTAT .NE. SS$_ENDOFFILE)) THEN
CALL LIB$SIGNAL (%VAL(IOSTAT))
ELSE IF (IOSTAT .NE. SS$_ENDOFFILE) THEN
I = I + 1
MESSAGES(I) = MBX_MESSAGE
MESSAGE_LEN(I) = MSG_LEN
END IF
END DO
.
.
.

System Service Input/Output Operations 23–47


System Service Input/Output Operations
23.22 Fast I/O and Fast Path Features (Alpha Only)

23.22 Fast I/O and Fast Path Features (Alpha Only)


Fast I/O and Fast Path are two optional features that can provide improved
I/O performance. Performance improvement is achieved by reducing the CPU
cost per I/O request, and improving symmetric multiprocessing (SMP) scaling
of I/O operations. The CPU cost per I/O is reduced by optimizing code for high-
volume I/O and by using better SMP CPU memory cache. SMP scaling of I/O is
increased by reducing the number of spinlocks taken per I/O and by substituting
finer-granularity spinlocks for global spinlocks.
The improvements follow a division that already exists between the device-
independent and device-dependent layers in the OpenVMS I/O subsystem. The
device-independent overhead is addressed by Fast I/O, which is a set of system
services that can substitute for certain $QIO operations. Using these services
requires some coding changes in existing applications, but the changes are
usually modest and well contained. The device-dependent overhead is addressed
by Fast Path, which is an optional performance feature that creates a ‘‘fast path’’
to the device. It requires no application changes.
Fast I/O and Fast Path can be used independently. However, together they can
provide a reduction in CPU cost per I/O on uniprocessor and on multiprocessor
systems.

23.22.1 Fast I/O (Alpha Only)


Fast I/O is a set of three system services, SYS$IO_SETUP, SYS$IO_PERFORM,
and SYS$IO_CLEANUP, that were developed as an alternative to $QIO.
These services are not a $QIO replacement; $QIO is unchanged, and $QIO
interoperation with these services is fully supported. Rather, the services
substitute for a subset of $QIO operations, namely, only the high-volume read
/write I/O requests.
The Fast I/O services support 64-bit addresses for data transfers to and from disk
and tape devices.
While Fast I/O services are available on OpenVMS VAX, the performance
advantage applies only to OpenVMS Alpha. OpenVMS VAX has a run-time
library (RTL) compatibility package that translates the Fast I/O service requests
to $QIO system service requests, so one set of source code can be used on both
VAX and Alpha systems.
23.22.1.1 Fast I/O Benefits
The performance benefits of Fast I/O result from streamlining high-volume I/O
requests. The Fast I/O system service interfaces are optimized to avoid the
overhead of general-purpose services. For example, I/O request packets (IRPs)
are now permanently allocated and used repeatedly for I/O rather than allocated
and deallocated anew for each I/O.
The greatest benefits stem from having user data buffers and user I/O status
structures permanently locked down and mapped using system space. This
allows Fast I/O to do the following:
• Avoid per-I/O buffer lockdown or unlocking for direct I/O.
• Avoid allocation and deallocation for buffered I/O of a separate system buffer,
because the user buffer is always addressable.

23–48 System Service Input/Output Operations


System Service Input/Output Operations
23.22 Fast I/O and Fast Path Features (Alpha Only)

• Complete Fast I/O operations at IPL 8, thereby avoiding the interrupt


chaining usually required by the more general-purpose $QIO system service.
For each I/O, this eliminates the IPL 4 IOPOST interrupt and a kernel AST.
In total, Fast I/O services eliminate four spinlock acquisitions per I/O (two for the
MMG spinlock and two for the SCHED spinlock). The reduction in CPU cost per
I/O is 20% for uniprocessor systems and 10% for multiprocessor systems.
23.22.1.2 Buffer Objects
Buffer objects accomplish the lockdown of user-process data structures. Buffer
objects are process entities that are associated with a process’s virtual address
range. When a buffer object is created, all its physical pages in its address range
are locked in memory and can be double-mapped into system space. These locked
pages in a process’s address range cannot be freed until the buffer object has been
deleted. The Fast I/O environment uses this feature by locking the buffer object
itself during $IO_SETUP. This prevents the buffer object and its associated pages
from being deleted. The buffer object is unlocked during $IO_CLEANUP, or at
image rundown. After creating a buffer object, the process remains fully pageable
and swappable and the process retains normal virtual memory access to its pages
in the buffer object.
If the buffer object contains process data structures to be passed to an OpenVMS
system service, the OpenVMS system can use the buffer object to avoid any
probing, lockdown, and unlocking overhead associated with these process data
structures. Additionally, if the buffer object has performed double-mapping into
system space, this allows the OpenVMS system direct access to the process
memory from system context.
To date, only the Fast I/O services are supported with buffer objects. For example,
a buffer object allows a programmer to eliminate I/O memory management
overhead. On each I/O, each page of a user data buffer is probed and then locked
down on I/O initiation and unlocked on I/O completion. Instead of incurring
this overhead for each I/O, it can be done once at buffer object creation time.
Subsequent I/O operations involving the buffer object can completely avoid this
memory management overhead.
System Space Window Buffer Objects
The system space window buffer object allows several I/O related tasks to be
performed entirely from system context at high IPL, without having to assume
process context. When a buffer object is created, the system maps by default a
section of system space (S2) to process pages associated with the buffer object.
This protected system space window allows read and write access only from
kernel mode. Because all of system space is equally accessible from within any
context, it is now possible to avoid the context switch to assume the original
user’s process context. Optionally, the system space window can be in S0/S1
space, or it can be suppressed.
Buffer Object System Services
Two system services are used to create and delete buffer objects: SYS$CREATE_
BUFOBJ_64 and SYS$DELETE_BUFOBJ. Both services can be called from any
access mode. To create a buffer object, the SYS$CREATE_BUFOBJ_64 system
service is called. This service expects as inputs an existing process memory range
and returns a handle for the buffer object. The handle is an opaque identifier
used to identify the buffer object on future requests. The SYS$DELETE_BUFOBJ
system service is used to delete the buffer object and accepts as input the handle.
Although image rundown deletes all existing buffer objects, it is good practice for
the application to clean up properly.

System Service Input/Output Operations 23–49


System Service Input/Output Operations
23.22 Fast I/O and Fast Path Features (Alpha Only)

Buffer Object Management


Buffer objects require system management. Because buffer objects tie up physical
memory, extensive use of buffer objects require system management planning.
All the bytes of memory in the buffer object are deducted from the systemwide
SYSGEN parameter MAXBOBMEM (maximum buffer object memory). System
managers must set this parameter correctly for the application loads that run on
their systems. Additionally, two other SYSGEN parameters MAXBOBS0S1 and
MAXBOBS2 are available for system managers. Table 23–5 shows these three
parameters and their meanings.

Table 23–5 SYSGEN Buffer Object Parameters


Parameter Meaning
MAXBOBMEM Defines the maximum amount of physical memory, measured in
pagelets, that can be associated with buffer objects.
A page associated with a buffer object is counted against this
parameter only once, even if it is associated with more than one
buffer object at the same time.
Memory resident pages are not counted against this parameter.
However, pages locked in memory through the SYS$LCKPAG
system service are counted.
This is a DYNAMIC parameter.
MAXBOBS0S1 Defines the maximum amount of 32-bit system space, measured
in pagelets, that can be used as windows to buffer objects.
This is a DYNAMIC parameter.
MAXBOBS2 Defines the maximum amount of 64-bit system space, measured
in pagelets, that can be used as windows to buffer objects.
This is a DYNAMIC parameter.

The MAXBOBMEM, MAXBOBS0S1, and MAXBOBS2 parameters default to


100 Alpha pages, but for applications with large buffer pools it can be set much
larger. To prevent user-mode code from tying up excessive physical memory,
user-mode callers of $CREATE_BUFOBJ_64 must have a new system identifier,
VMS$BUFFER_OBJECT_USER, assigned. The system manager can assign
this identifier with the DCL command SET ACL command to a protected
subsystem or application that creates buffer objects from user mode. It may
also be appropriate to grant the identifier to a particular user with the Authorize
utility command GRANT/IDENTIFIER, for example, to a programmer who is
working on a development system.
Buffer Object Restrictions
There are several buffer object restrictions which are listed as follows:
• Buffer objects can only be associated with process space (P0, P1, or P2) pages.
• PFN-mapped pages cannot be associated with buffer objects.
• The special buffer object type without associated system space can only be
used to describe Fast I/O data buffers. The IOSA must always be associated
with a full buffer object with system space.

23–50 System Service Input/Output Operations


System Service Input/Output Operations
23.22 Fast I/O and Fast Path Features (Alpha Only)

Further Fast I/O Information


For complete information about using Fast I/O, the Fast I/O system services, and
the buffer objects system services that are in the following list, see the OpenVMS
I/O User’s Reference Manual, and the OpenVMS System Services Reference
Manual: A–GETUAI and the OpenVMS System Services Reference Manual:
GETUTC–Z:
SYS$CREATE_BUFOBJ_64
SYS$DELETE_BUFOBJ
SYS$IO_SETUP
SYS$IO_PERFORM
SYS$IO_CLEANUP

23.22.2 Fast Path (Alpha Only)


Like Fast I/O, Fast Path is an optional, high-performance feature designed to
improve I/O performance. By restructuring and optimizing class and port device
driver code around high-volume I/O code paths, Fast Path creates a streamlined
path to the device. Fast Path is of interest to any application where enhanced
I/O performance is desirable. Two examples are database systems and real-time
applications, where the speed of transferring data to disk is often a vital concern.
Using Fast Path features does not require source-code changes. Minor interface
changes are available for expert programmers who want to maximize Fast Path
benefits.
At this time, Fast Path is not available on the OpenVMS VAX operating system.
23.22.2.1 Fast Path Features and Benefits
Fast Path achieves performance gains by reducing CPU time for I/O requests on
both uniprocessor and SMP systems. The performance benefits are produced by:
• Reducing code paths through streamlining for the case of high-volume I/O
• Substituting port-specific spinlocks for global I/O subsystem spinlocks
• Affinitizing an I/O request for a given port to a specific CPU
The performance improvement can best be seen by contrasting the current
OpenVMS I/O scheme to the new Fast Path scheme. While transparent to an
OpenVMS user, each disk and tape device is tied to a specific port interconnect.
All I/O for a device is sent out over its assigned port. Under the current
OpenVMS I/O scheme, a multiprocessor I/O can be initiated on any CPU, but
I/O completion must occur on the primary CPU. Under Fast Path, all I/O for
a given port is affinitized to a specific CPU, eliminating the requirement for
completing the I/O on the primary CPU. This means that the entire I/O can be
initiated and completed on a single CPU. Because I/O operations are no longer
split among different CPUs, performance increases as memory cache thrashing
between CPUs decreases.
Fast Path also removes a possible SMP bottleneck on the primary CPU. If
the primary CPU must be involved in all I/O, then once this CPU becomes
saturated, no further increase in I/O throughput is possible. Spreading the I/O
load evenly among CPUs in a multiprocessor system provides greater maximum
I/O throughput on a multiprocessor system.
With most of the I/O code path executing under port-specific spinlocks and with
each port assigned to a specific CPU, a scalable SMP model of parallel operation
exists. Given multiple port and CPUs, I/O can be issued in parallel to a large
degree.

System Service Input/Output Operations 23–51


System Service Input/Output Operations
23.22 Fast I/O and Fast Path Features (Alpha Only)

23.22.2.2 Additional Information About Fast Path


For complete information about using Fast Path, see the OpenVMS I/O User’s
Reference Manual.

23–52 System Service Input/Output Operations


24
Using Run-Time Library Routines to Access
Operating System Components

This chapter describes the run-time library (RTL) routines that allow access to
various operating system components and it contains the following sections:
Section 24.1 describes how to use RTL routines to make system services return
different types of strings.
Section 24.2 describes how to use RTL routines to provide access to the command
language interpreter.
Section 24.3 describes how to use RTL routines to allow high-level language
programs to use most VAX machine instructions or their Alpha equivalent.
Section 24.4 describes how to use RTL routines to allocate processwide resources
to a single operating system process.
Section 24.5 describes how to use RTL routines to measure performance.
Section 24.6 describes how to use RTL routines to control output formatting.
Section 24.7 describes how to use RTL routines for miscellaneous interface
routines.
Run-time library routines allow access to the following operating system
components:
• System services
• Command language interpreter
• Some VAX machine instructions

24.1 System Service Access Routines


You can usually call the OpenVMS system services directly from your program.
However, system services return only fixed-length strings. In some applications,
you may want the result of a system service to be returned as a character array,
dynamic string, or variable-length string. For this reason, the RTL provides
jacket routines for the system services that return strings.
You call jacket routines exactly as you would the corresponding system service,
but you can pass an output argument of any valid string class. The routines write
the output string using the semantics (fixed, varying, or dynamic) associated with
the string’s descriptor.
The jacket routines follow the conventions established for all RTL routines, except
that the arguments are listed in the order of the arguments for the corresponding
system service. Thus, they may not be listed in the standard RTL order (read,
modify, write).

Using Run-Time Library Routines to Access Operating System Components 24–1


Using Run-Time Library Routines to Access Operating System Components
24.1 System Service Access Routines

For example, the LIB$SYS_ASCTIM routine calls the SYS$ASCTIM system


service to convert a binary date and time value to ASCII text. It returns the
resulting string using the semantics that the calling program specifies in the
destination string argument.
For further information about the operations of the system services, see the
OpenVMS System Services Reference Manual.
The RTL routines provide access to only the system services that produce output
strings, which are listed in Table 24–1. The corresponding RTL routines recognize
all VAX string classes.
The RTL does not provide jacket routines for all the system services that accept
strings as input. Your program should pass only fixed-length or dynamic input
strings to all system services and RTL jacket routines.

Table 24–1 System Service Access Routines


Entry Point System Service Function
LIB$SYS_ASCTIM $ASCTIM Converts system time in binary form
to ASCII text
LIB$SYS_FAO $FAO Converts a binary value to ASCII text
LIB$SYS_FAOL $FAOL Converts a binary value to ASCII text,
using a list argument
LIB$SYS_GETMSG $GETMSG Obtains a system or user-defined
message text
LIB$SYS_TRNLOG $TRNLOG Returns the translation of the specified
logical name

24.2 Access to the Command Language Interpreter


Two command language interpreters (CLIs) are available on the operating
system: DCL and MCR. The run-time library provides several routines that
provide access to the CLI callback facility. These routines allow your program to
call the current CLI. In most cases, these routines are called from programs that
execute as part of a command procedure. They allow the command procedure and
the CLI to exchange information.
These routines call the CLI associated with the current process to perform the
specified function. In some cases, however, a CLI is not present. For example, the
program may be running directly as a subprocess or as a detached process. If a
CLI is not present, these routines return the status LIB$_NOCLI. Therefore, you
should be sure that these routines are called when a CLI is active. Table 24–2
lists the RTL routines that access the CLI.

Table 24–2 CLI Access Routines


Entry Point Function
LIB$GET_FOREIGN Gets a command line
LIB$DO_COMMAND Executes a command line after exiting the current
program
(continued on next page)

24–2 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.2 Access to the Command Language Interpreter

Table 24–2 (Cont.) CLI Access Routines


Entry Point Function

LIB$RUN_PROGRAM Runs another program after exiting the current program


(chain)
LIB$GET_SYMBOL Returns the value of a CLI symbol as a string
LIB$DELETE_SYMBOL Deletes a CLI symbol
LIB$SET_SYMBOL Defines or redefines a CLI symbol
LIB$DELETE_LOGICAL Deletes a supervisor-mode process logical name
LIB$SET_LOGICAL Defines or redefines a supervisor-mode process logical
name
LIB$DISABLE_CTRL Disables CLI interception of control characters
LIB$ENABLE_CTRL Enables CLI interception of control characters
LIB$ATTACH Attaches a terminal to another process
LIB$SPAWN Creates a subprocess of the current process

The following routines execute only when the current CLI is DCL:
LIB$GET_SYMBOL
LIB$SET_SYMBOL
LIB$DELETE_SYMBOL
LIB$DISABLE_CTRL
LIB$ENABLE_CTRL
LIB$SPAWN
LIB$ATTACH

24.2.1 Obtaining the Command Line


The LIB$GET_FOREIGN routine returns the contents of the command line that
you use to activate an image. You can use it either to give your program access to
the qualifiers of a foreign command or to prompt for further command line text.
A foreign command is a command that you can define and then use, as if it
were a DCL or MCR command to run a program. When you use the foreign
command at command level, the CLI parses the foreign command only and
activates the image. It ignores any options or qualifiers that you have defined for
the foreign command. Once the CLI has activated the image, the program can
call LIB$GET_FOREIGN to obtain and parse the remainder of the command line
(after the command itself) for whatever options it may contain.
The OpenVMS DCL Dictionary describes how to define a foreign command.
The action of LIB$GET_FOREIGN depends on the environment in which the
image is activated:
• If you use a foreign command to invoke the image, you can call LIB$GET_
FOREIGN to obtain the command qualifiers following the foreign command.
You can also use LIB$GET_FOREIGN to prompt repeatedly for more
qualifiers after the command. This technique is illustrated in the following
example.
• If the image is in the SYS$SYSTEM: directory, the image can be invoked
by the DCL command MCR or by the MCR CLI. In this case, LIB$GET_
FOREIGN returns the command line text following the image name.

Using Run-Time Library Routines to Access Operating System Components 24–3


Using Run-Time Library Routines to Access Operating System Components
24.2 Access to the Command Language Interpreter

• If the image is invoked by the DCL command RUN, you can use LIB$GET_
FOREIGN to prompt for additional text.
• If the image is not invoked by a foreign command or by MCR, or if there is no
information remaining on the command line, and the user-supplied prompt
is present, LIB$GET_INPUT is called to prompt for a command line. If the
prompt is not present, LIB$GET_FOREIGN returns a zero-length string.
Example
The following PL/I example illustrates the use of the optional force-prompt
argument to permit repeated calls to LIB$GET_FOREIGN. The command line
text is retrieved on the first pass only; after this, the program prompts from
SYS$INPUT.

EXAMPLE: ROUTINE OPTIONS (MAIN);


%INCLUDE $STSDEF; /* Status-testing definitions */
DECLARE COMMAND_LINE CHARACTER(80) VARYING,
PROMPT_FLAG FIXED BINARY(31) INIT(0),
LIB$GET_FOREIGN ENTRY (CHARACTER(*) VARYING,
CHARACTER(*) VARYING,
FIXED BINARY(15),
FIXED BINARY(31))
OPTIONS(VARIABLE) RETURNS (FIXED BINARY(31)),
RMS$_EOF GLOBALREF FIXED BINARY(31) VALUE;
/* Call LIB$GET_FOREIGN repeatedly to obtain and print
subcommand text. Exit when end-of-file is found. */
DO WHILE (’1’B); /* Do while TRUE */
STS$VALUE = LIB$GET_FOREIGN
(COMMAND_LINE,’Input: ’,,
PROMPT_FLAG);
IF STS$SUCCESS THEN
PUT LIST (’ Command was ’,COMMAND_LINE);
ELSE DO;
IF STS$VALUE ^= RMS$_EOF THEN
PUT LIST (’Error encountered’);
RETURN;
END;
PUT SKIP; /* Skip to next line */
END; /* End of DO WHILE loop */
END;

Assuming that this program is present as SYS$SYSTEM:EXAMPLE.EXE, you


can define the foreign command EXAMPLE to invoke it, as follows:
$ EXAM*PLE :== $EXAMPLE
Note the optional use of the asterisk in the symbol name to denote an abbreviated
command name. This permits the command name to be abbreviated as EXAM,
EXAMP, EXAMPL or to be specified fully as EXAMPLE. See the OpenVMS DCL
Dictionary for information about abbreviated command names.
Note that the use of the dollar sign ($) before the image name is required in
foreign commands.

24–4 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.2 Access to the Command Language Interpreter

Now assume that a user runs the image by typing the foreign command and
giving ‘‘subcommands’’ that the program displays:
$ EXAMP Subcommand 1
Command was SUBCOMMAND 1
Input: Subcommand 2
Command was SUBCOMMAND 2
Input: ^Z
$
In this example, Subcommand 1 was obtained from the command line; the
program prompts the user for the second subcommand. The program terminated
when the user pressed the Ctrl/Z key sequence (displayed as ^Z) to indicate
end-of-file.

24.2.2 Chaining from One Program to Another


The LIB$RUN_PROGRAM routine causes the current image to exit at the point
of the call and directs the CLI, if present, to start running another program.
If LIB$RUN_PROGRAM executes successfully, control passes to the second
program; if not, control passes to the CLI. The calling program cannot regain
control. This technique is called chaining.
This routine is provided primarily for compatibility with PDP–11 systems, on
which chaining is used to extend the address space of a system. Chaining may
also be useful in an operating system environment where address space is
severely limited and large images are not possible. For example, you can use
chaining to perform system generation on a small virtual address space because
disk space is lacking.
With LIB$RUN_PROGRAM, the calling program can pass arguments to the
next program in the chain only by using the common storage area. One way to
do this is to direct the calling program to call LIB$PUT_COMMON to pass the
information into the common area. The called program then calls LIB$GET_
COMMON to retrieve the data.
In general, this practice is not recommended. There is no convenient way
to specify the order and type of arguments passed into the common area, so
programs that pass arguments in this way must know about the format of the
data before it is passed. Fortran COMMON or BASIC MAP/COMMON areas
are global OWN storage. When you use this type of storage, it is very difficult
to keep your program modular and AST reentrant. Further, you cannot use
LIB$RUN_PROGRAM if a CLI is present, as with image subprocesses and
detached subprocesses.
Examples
The following PL/I example illustrates the use of LIB$RUN_PROGRAM. It
prompts the user for the name of a program to run and calls the RTL routine to
execute the specified program.

Using Run-Time Library Routines to Access Operating System Components 24–5


Using Run-Time Library Routines to Access Operating System Components
24.2 Access to the Command Language Interpreter

CHAIN: ROUTINE OPTIONS (MAIN) RETURNS (FIXED BINARY (31));


DECLARE LIB$RUN_PROGRAM ENTRY (CHARACTER (*)) /* Address of string
/* descriptor */
RETURNS (FIXED BINARY (31)); /* Return status */
%INCLUDE $STSDEF; /* Include definition of return status values */
DECLARE COMMAND CHARACTER (80);
GET LIST (COMMAND) OPTIONS (PROMPT(’Program to run: ’));
STS$VALUE = LIB$RUN_PROGRAM (COMMAND);
/*
If the function call is successful, the program will terminate
here. Otherwise, return the error status to command level.
*/
RETURN (STS$VALUE);
END CHAIN;
The following COBOL program also demonstrates the use of LIB$RUN_
PROGRAM. When you compile and link these two programs, the first calls
LIB$RUN_PROGRAM, which activates the executable image of the second. This
call results in the following screen display:
THIS MESSAGE DISPLAYED BY PROGRAM PROG2
WHICH WAS RUN BY PROGRAM PROG1
USING LIB$RUN_PROGRAM

IDENTIFICATION DIVISION.
PROGRAM-ID. PROG1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 PROG-NAME PIC X(9) VALUE "PROG2.EXE".
01 STAT PIC 9(9) COMP.
88 SUCCESSFUL VALUE 1.
ROUTINE DIVISION.
001-MAIN.
CALL "LIB$RUN_PROGRAM"
USING BY DESCRIPTOR PROG-NAME
GIVING STAT.
IF NOT SUCCESSFUL
DISPLAY "ATTEMPT TO CHAIN UNSUCCESSFUL"
STOP RUN.
IDENTIFICATION DIVISION.
PROGRAM-ID. PROG2.
ENVIRONMENT DIVISION.
DATA DIVISION.
ROUTINE DIVISION.

001-MAIN.
DISPLAY " ".
DISPLAY "THIS MESSAGE DISPLAYED BY PROGRAM PROG2".
DISPLAY " ".
DISPLAY "WHICH WAS RUN BY PROGRAM PROG1".
DISPLAY " ".
DISPLAY "USING LIB$RUN_PROGRAM".
STOP RUN.

24–6 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.2 Access to the Command Language Interpreter

24.2.3 Executing a CLI Command


The LIB$DO_COMMAND routine stops program execution and directs the CLI to
execute a command. The routine’s argument is the text of the command line that
you want to execute.
This routine is especially useful when you want to execute a CLI command after
your program has finished executing. For example, you could set up a series of
conditions, each associated with a different command. You could also use the
routine to execute a SUBMIT or PRINT command to handle a file that your
program creates.
Because of the following restrictions on LIB$DO_COMMAND, you should be
careful when you incorporate it in your program:
• After the call to LIB$DO_COMMAND, the current image exits, and control
cannot return to it.
• The text of the command is passed to the current CLI. Because you can define
your own CLI in addition to DCL and MCR, you must make sure that the
command is handled by the intended CLI.
• If the routine is called from a subprocess and a CLI is not associated with
that subprocess, the routine executes correctly.
You can also use LIB$DO_COMMAND to execute a DCL command file. To do
this, include the at sign (@) along with a command file specification as the input
argument to the routine.
Some DCL CLI$ routines perform the functions of LIB$DO_COMMAND. See the
OpenVMS DCL Dictionary for more information.
Example
The following PL/I example prompts the user for a DCL command to execute after
the program exits:
EXECUTE: ROUTINE OPTIONS (MAIN) RETURNS (FIXED BINARY (31));
DECLARE LIB$DO_COMMAND ENTRY (CHARACTER (*)) /* Pass DCL command */
/* by descriptor */
RETURNS (FIXED BINARY (31)); /* Return status */
%INCLUDE $STSDEF; /* Include definition of return status values */
DECLARE COMMAND CHARACTER (80);
GET LIST (COMMAND) OPTIONS (PROMPT(’DCL command to execute: ’));
STS$VALUE = LIB$DO_COMMAND (COMMAND);
/*
If the call to LIB$DO_COMMAND is successful, the program will terminate
here. Otherwise, it will return the error status to command level.
*/
RETURN (STS$VALUE);
END EXECUTE;
This example displays the following prompt:
DCL command to execute:

Using Run-Time Library Routines to Access Operating System Components 24–7


Using Run-Time Library Routines to Access Operating System Components
24.2 Access to the Command Language Interpreter

What you type after this prompt determines the action of LIB$DO_COMMAND.
LIB$DO_COMMAND executes any command that is entered as a valid string
according to the syntax of PL/I. If the command you enter is incomplete, you
are prompted for the rest of the command. For example, if you enter the SHOW
command, you receive the following prompt:
$_Show what?:

24.2.4 Using Symbols and Logical Names


The RTL provides a number of routines that give you access to the CLI callback
facility. These routines allow a program to ‘‘call back’’ to the CLI to perform
functions that normally are performed by CLI commands. These routines perform
the following functions:
LIB$GET_SYMBOL Returns the value of a CLI symbol as a string.
Optionally, this routine also returns the length of the
returned value and a value indicating whether the symbol
was found in the local or global symbol table. This routine
executes only when the current CLI is DCL.
LIB$SET_SYMBOL Causes the CLI to define or redefine a CLI symbol.
The optional argument specifies whether the symbol is to
be defined in the local or global symbol table; the default
is local. This routine executes only when the current CLI
is DCL.
LIB$DELETE_SYMBOL Causes the CLI to delete a symbol.
An optional argument specifies the local or global symbol
table. If the argument is omitted, the symbol is deleted
from the local symbol table. This routine executes only
when the current CLI is DCL.
LIB$SET_LOGICAL Defines or redefines a supervisor-mode process logical
name.
Supervisor-mode logical names are not deleted when
an image exits. This routine is equivalent to the DCL
command DEFINE. LIB$SET_LOGICAL allows the
calling program to define a supervisor-mode process
logical name without itself executing in supervisor mode.
LIB$DELETE_LOGICAL Deletes a supervisor-mode process logical name.
This routine is equivalent to the DCL command
DEASSIGN. LIB$DELETE_LOGICAL does not require
the calling program to be executing in supervisor mode to
delete a supervisor-mode logical name.
For information about using logical names, see Chapter 32.

24.2.5 Disabling and Enabling Control Characters


Two run-time library routines, LIB$ENABLE_CTRL and LIB$DISABLE_CTRL,
allow you to call the CLI to enable or disable control characters. These routines
take a longword bit mask argument that specifies the control characters to be
disabled or enabled. Acceptable values for this argument are LIB$M_CLI_CTRLY
and LIB$M_CLI_CTRLT.

24–8 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.2 Access to the Command Language Interpreter

LIB$DISABLE_CTRL Disables CLI interception of control characters.


This routine performs the same function as the DCL
command SET NOCONTROL=n, where n is T or Y.
It prevents the currently active CLI from intercepting the
control character specified during an interactive session.
For example, you might use LIB$DISABLE_CTRL to
disable CLI interception of Ctrl/Y. Normally, Ctrl/Y
interrupts the current command, command procedure,
or image. If LIB$DISABLE_CTRL is called with LIB$M_
CLI_CTRLY specified as the control character to be
disabled, Ctrl/Y is treated like Ctrl/U followed by a
carriage return.
LIB$ENABLE_CTRL Enables CLI interception of control characters.
This routine performs the same function as the DCL
command SET CONTROL=n, where n is T or Y.
LIB$ENABLE_CTRL restores the normal operation of
Ctrl/Y or Ctrl/T.

24.2.6 Creating and Connecting to a Subprocess


You can use LIB$SPAWN and LIB$ATTACH together to spawn a subprocess and
attach the terminal to that subprocess. These routines execute correctly only
if the current CLI is DCL. For more information on the SPAWN and ATTACH
commands, see the OpenVMS DCL Dictionary. For more information on creating
processes, see Chapter 2.
LIB$SPAWN Spawns a subprocess.
This routine is equivalent to the DCL command SPAWN. It requests
the CLI to spawn a subprocess for executing CLI commands.
LIB$ATTACH Attaches the terminal to another process.
This routine is equivalent to the DCL command ATTACH. It requests
the CLI to detach the terminal from the current process and reattach it
to a different process.

24.3 Access to VAX Machine Instructions


The VAX instruction set was designed for efficient use by high-level languages
and, therefore, contains many functions that are directly useful in your programs.
However, some of these functions cannot be used directly by high-level languages.
The run-time library provides routines that allow your high-level language
program to use most VAX machine instructions that are otherwise unavailable.
On Alpha machines, these routines execute a series of Alpha instructions that
emulate the operation of the VAX instructions. In most cases, these routines
simply execute the instruction, using the arguments you provide. Some routines
that accept string arguments, however, provide some additional functions that
make them easier to use.
These routines fall into the following categories:
• Variable-length bit field instruction routines (Section 24.3.1)
• Integer and floating-point instructions (Section 24.3.2)
• Queue instructions (Section 24.3.3)
• Character string instructions (Section 24.3.4)

Using Run-Time Library Routines to Access Operating System Components 24–9


Using Run-Time Library Routines to Access Operating System Components
24.3 Access to VAX Machine Instructions

• Routine call instructions (Section 24.3.5)


• Cyclic redundancy check (CRC) instruction (Section 24.3.5)
The VAX Architecture Reference Manual describes the VAX instruction set in
detail.

24.3.1 Variable-Length Bit Field Instruction Routines


The variable-length bit field is a VAX data type used to store small integers
packed together in a larger data structure. It is often used to store single flag
bits.
The run-time library contains five routines for performing operations on variable-
length bit fields. These routines give higher-level languages that do not have the
inherent ability to manipulate bit fields direct access to the bit field instructions
in the VAX instruction set. Further, if a program calls a routine written in a
different language to perform some function that also involves bit manipulation,
the called routine can include a call to the run-time library to perform the bit
manipulation.
Table 24–3 lists the run-time library variable-length bit field routines.

Table 24–3 Variable-Length Bit Field Routines


Entry Point Function
LIB$EXTV Extracts a field from the specified variable-length bit field and returns
it in sign-extended longword form.
LIB$EXTZV Extracts a field from the specified variable-length bit field and returns
it in zero-extended longword form.
LIB$FFC Searches the specified field for the first clear bit. If it finds one, it
returns SS$_NORMAL and the bit position (find-pos argument) of
the clear bit. If not, it returns a failure status and sets the find-pos
argument to the start position plus the size.
LIB$FFS Searches the specified field for the first set bit. If it finds one, it
returns SS$_NORMAL and the bit position (find-pos argument) of
the set bit. If not, it returns a failure status and sets the find-pos
argument to the start position plus the size.
LIB$INSV Replaces the specified field with bits 0 through [size -1] of the source
(src argument). If the size argument is 0, nothing is inserted.

Three scalar attributes define a variable bit field:


• Base address—The address of the byte in memory that serves as a reference
point for locating the bit field.
• Bit position—The signed longword containing the displacement of the least
significant bit of the field with respect to bit 0 of the base address.
• Size—A byte integer indicating the size of the bit field in bits (in the range
0 <= size <= 32). That is, a bit field can be no more than one longword in
length.
Figure 24–1 shows the format of a variable-length bit field. The shaded area
indicates the field.

24–10 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.3 Access to VAX Machine Instructions

Figure 24–1 Format of a Variable-Length Bit Field

P+S−1 P 8 7 0

.. .. :A

S = Size of Field in Bits

P = Bit Displacement of Field


from Bit 0 of Address A
ZK−1981−GE

Bit fields are zero-origin, which means that the routine regards the first bit in
the field as being the zero position. For more detailed information about VAX bit
numbering and data formats, see the VAX Architecture Reference Manual.
The attributes of the bit field are passed to an RTL routine in the form of three
arguments in the following order:

pos
Operating system usage: longword_signed
type: longword integer (signed)
access: read only
mechanism: by reference
Bit position relative to the base address. The pos argument is the address of a
signed longword integer that contains this bit position.

size
Operating system usage: byte_unsigned
type: byte (unsigned)
access: read only
mechanism: by reference
Size of the bit field. The size argument is the address of an unsigned byte that
contains this size.

base
Operating system usage: longword_unsigned
type: longword (unsigned)
access: read only
mechanism: by reference
Base address. The base argument contains the address of the base address.
Example
The following BASIC example illustrates three RTL routines. It opens the
terminal as a file and specifies HEX> as the prompt. This prompt allows you to
obtain input from the terminal without the question mark that VAX BASIC
normally adds to the prompt in an INPUT statement. The program calls
OTS$CVT_TZ_L to convert the character string input to a longword. It then
calls LIB$EXTZV once for each position in the longword to extract the bit in
that position. Because LIB$EXTVZ is called with a function reference within the
PRINT statement, the bits are displayed.

Using Run-Time Library Routines to Access Operating System Components 24–11


Using Run-Time Library Routines to Access Operating System Components
24.3 Access to VAX Machine Instructions

10 EXTERNAL LONG FUNCTION


OTS$CVT_TZ_L, ! Convert hex text to LONG
LIB$EXTZV ! Extract zero-ended bit field
20 OPEN "TT:" FOR INPUT AS FILE #1% ! Open terminal as a file
INPUT #1%, "HEX>"; HEXIN$ ! Prompt for input
STAT%=OTS$CVT_TZ_L(HEXIN$, BINARY%) ! Convert to longword
IF (STAT% AND 1%) <> 1% ! Failed?
THEN
PRINT "Conversion failed, decimal status ";STAT%
GO TO 20 ! Try again
ELSE
PRINT HEXIN$,
PRINT STR$(LIB$EXTZV(N%, 1%, BINARY%));
FOR N%=31% to 0% STEP -1%

24.3.2 Integer and Floating-Point Routines


Integer and floating-point routines give a high-level language program access
to the corresponding machine instructions. For a complete description of these
instructions, see the VAX Architecture Reference Manual. Table 24–4 lists the
integer and floating-point routines once up front.

Table 24–4 Integer and Floating-Point Routines


Entry Point Function
LIB$EMUL Multiplies integers with extended precision
LIB$EDIV Divides integers with extended precision

24.3.3 Queue Access Routines


A queue is a doubly linked list. A run-time library routine specifies a queue entry
by its address. Two longwords, a forward link and a backward link, define the
location of the entry in relation to the preceding and succeeding entries. A self-
relative queue is a queue in which the links between entries are displacements;
the two longwords represent the displacements of the current entry’s predecessor
and successor. The VAX instructions INSQHI, INSQTI, REMQHI, and REMQTI
allow you to insert and remove an entry at the head or tail of a self-relative
queue. Each queue instruction has a corresponding RTL routine.
The self-relative queue instructions are interlocked and cannot be interrupted,
so that other processes cannot insert or remove queue entries while the current
program is doing so. Because the operation requires changing two pointers at the
same time, a high-level language cannot perform this operation without calling
the RTL queue access routines.
When you use these routines, cooperating processes can communicate without
further synchronization and without danger of being interrupted, either on a
single processor or in a multiprocessor environment. The queue access routines
are also useful in an AST environment; they allow you to add or remove an entry
from a queue without being interrupted by an asynchronous system trap.
The remove queue instructions (REMQHI or REMQTI) return the address of the
removed entry. Some languages, such as BASIC, COBOL, and Fortran, do not
provide a mechanism for accessing an address returned from a routine. Further,
BASIC and COBOL do not allow routines to be arguments.

24–12 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.3 Access to VAX Machine Instructions

Table 24–5 lists the queue access routines.

Table 24–5 Queue Access Routines


Entry Point Function
LIB$INSQHI Inserts queue entry at head
LIB$INSQTI Inserts queue entry at tail
LIB$REMQHI Removes queue entry at head
LIB$REMQTI Removes queue entry at tail

Examples
LIB$INSQHI
In BASIC and Fortran, queues can be quadword aligned in a named COMMON
block by using a linker option file to specify alignment of program sections. The
LIB$GET_VM routine returns memory that is quadword aligned. Therefore,
you should use LIB$GET_VM to allocate the virtual memory for a queue. For
instance, to create a COMMON block called QUEUES, use the LINK command
with the FILE/OPTIONS qualifier, where FILE.OPT is a linker option file
containing the line:
PSECT = QUEUES, QUAD
A Fortran application using processor-shared memory follows:
INTEGER*4 FUNCTION INSERT_Q (QENTRY)
COMMON/QUEUES/QHEADER
INTEGER*4 QENTRY(10), QHEADER(2)
INSERT_Q = LIB$INSQHI (QENTRY, QHEADER)
RETURN
END
A BASIC application using processor-shared memory follows:
COM (QUEUES) QENTRY%(9), QHEADER%(1)
EXTERNAL INTEGER FUNCTION LIB$INSQHI
IF LIB$INSQHI (QENTRY%() BY REF, QHEADER%() BY REF) AND 1%
THEN GOTO 1000
.
.
.
1000 REM INSERTED OK
LIB$REMQHI
In Fortran, the address of the removed queue entry can be passed to another
routine as an array using the %VAL built-in function.

Using Run-Time Library Routines to Access Operating System Components 24–13


Using Run-Time Library Routines to Access Operating System Components
24.3 Access to VAX Machine Instructions

In the following example, queue entries are 10 longwords, including the two
longword pointers at the beginning of each entry:
COMMON/QUEUES/QHEADER
INTEGER*4 QHEADER(2), ISTAT
ISTAT = LIB$REMQHI (QHEADER, ADDR)
IF (ISTAT) THEN
CALL PROC (%VAL (ADDR)) ! Process removed entry
GO TO ...
ELSE IF (ISTAT .EQ. %LOC(LIB$_QUEWASEMP)) THEN
GO TO ... ! Queue was empty
ELSE IF
... ! Secondary interlock failed
END IF
.
.
.
END
SUBROUTINE PROC (QENTRY)
INTEGER*4 QENTRY(10)
.
.
.
RETURN
END

24.3.4 Character String Routines


The character string routines listed in Table 24–6 give a high-level language
program access to the corresponding VAX machine instructions. For a complete
description of these instructions, see the VAX Architecture Reference Manual. For
each instruction, the VAX Architecture Reference Manual specifies the contents of
all the registers after the instruction executes. The corresponding RTL routines
do not make the contents of all the registers available to the calling program.
Table 24–6 lists the LIB$ character string routines and their functions.

Table 24–6 Character String Routines


Entry Point Function
LIB$LOCC Locates a character in a string
LIB$MATCHC Returns the relative position of a substring
LIB$SCANC Scans characters
LIB$SKPC Skips characters
LIB$SPANC Spans characters
LIB$MOVC3 Moves characters
LIB$MOVC5 Moves characters and fills
LIB$MOVTC Moves translated characters
LIB$MOVTUC Move translated characters until specified character is found

The OpenVMS RTL String Manipulation (STR$) Manual describes STR$ string
manipulation routines.

24–14 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.3 Access to VAX Machine Instructions

Example
This COBOL program uses LIB$LOCC to return the position of a given letter of
the alphabet.

IDENTIFICATION DIVISION.
PROGRAM-ID. LIBLOC.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SEARCH-STRING PIC X(26)
VALUE "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
01 SEARCH-CHAR PIC X.
01 IND-POS PIC 9(9) USAGE IS COMP.
01 DISP-IND PIC 9(9).
ROUTINE DIVISION.
001-MAIN.
MOVE SPACE TO SEARCH-CHAR.
DISPLAY " ".
DISPLAY "ENTER SEARCH CHARACTER: " WITH NO ADVANCING.
ACCEPT SEARCH-CHAR.
CALL "LIB$LOCC"
USING BY DESCRIPTOR SEARCH-CHAR, SEARCH-STRING
GIVING IND-POS.
IF IND-POS = ZERO
DISPLAY
"CHAR ENTERED (" SEARCH-CHAR ") NOT A VALID SEARCH CHAR"
STOP RUN.
MOVE IND-POS TO DISP-IND.
DISPLAY
"SEARCH CHAR (" SEARCH-CHAR ") WAS FOUND IN POSITION "
DISP-IND.
GO TO 001-MAIN.

24.3.5 Miscellaneous Instruction Routines


Table 24–7 lists additional routines that you can use.

Table 24–7 Miscellaneous Instruction Routines


Entry Point Function
LIB$CALLG Calls a routine using an array argument list
LIB$CRC Computes a cyclic redundancy check
LIB$CRC_TABLE Constructs a table for a cyclic redundancy check

LIB$CALLG
The LIB$CALLG routine gives your program access to the CALLG instruction.
This instruction calls a routine using an argument list stored as an array in
memory, as opposed to the CALLS instruction, in which the argument list is
pushed on the stack.

Using Run-Time Library Routines to Access Operating System Components 24–15


Using Run-Time Library Routines to Access Operating System Components
24.3 Access to VAX Machine Instructions

LIB$CRC
The LIB$CRC routine allows your high-level language program to use the CRC
instruction, which calculates the cyclic redundancy check. This instruction checks
the integrity of a data stream by comparing its state at the sending point and the
receiving point. Each character in the data stream is used to generate a value
based on a polynomial. The values for each character are then added together.
This operation is performed at both ends of the data transmission, and the two
result values are compared. If the results disagree, then an error occurred during
the transmission.
LIB$CRC_TABLE
The LIB$CRC_TABLE routine takes a polynomial as its input and builds the
table that LIB$CRC uses to calculate the CRC. You must specify the polynomial
to be used.
For more details, see the VAX Architecture Reference Manual.

24.4 Processwide Resource Allocation Routines


This section discusses routines that allocate processwide resources to a single
operating system process. The processwide resources discussed here are:
• Local event flags
• BASIC and Fortran logical unit numbers (LUNs)
The resource allocation routines are provided so that user routines can use the
processwide resources without conflicting with one another.
In general, you must use run-time library resource allocation routines when your
program needs processwide resources. This allows RTL routines supplied by
Compaq, and user routines that you write to perform together within a process.
If your called routine includes a call to any RTL routine that frees a processwide
resource, and that called routine fails to execute normally, the resource will not
be freed. Thus, your routine should establish a condition handler that frees
the allocated resource before resignaling or unwinding. For information about
condition handling, see Chapter 9.
Table 24–8 list routines that perform processwide resource allocation.

Table 24–8 Processwide Resource Allocation Routines


Entry Point Function
LIB$FREE_LUN Deallocates a specific logical unit number
LIB$GET_LUN Allocates next arbitrary logical unit number
LIB$FREE_EF Frees a local event flag
LIB$GET_EF Allocates a local event flag
LIB$RESERVE_EF Reserves a local event flag

24.4.1 Allocating Logical Unit Numbers


BASIC and Fortran use a logical unit number (LUN) to define the file or device
a program uses to perform input and output. For a routine to be modular, it
does not need to know the LUNs being used by other routines that are running
at the same time. For this reason, logical units are allocated and deallocated at
run time. You can use LIB$GET_LUN and LIB$FREE_LUN to obtain the next

24–16 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.4 Processwide Resource Allocation Routines

available number. This ensures that your BASIC or Fortran routine does not
use a logical unit that is already being used by a calling program. Therefore,
you should use this routine whenever your program calls or is called by another
program that also allocates LUNs. Logical unit numbers 100 to 119 are available
to modular routines through these entry points.
To allocate an LUN, call LIB$GET_LUN and use the value returned as the LUN
for your I/O statements. If no LUNs are available, an error status is returned
and the logical unit is set to 01. When the program unit exits, it should use
LIB$FREE_LUN to free any LUNs that have been allocated by LIB$GET_LUN.
If it does not free any LUNs, the available pool of numbers is freed for use.
If your called routine contains a call to LIB$FREE_LUN to free the LUNs upon
exit, and your routine fails to execute normally, the LUNs will not be freed.
For this reason, you should make sure to establish a condition handler to call
LIB$FREE_LUN before resignaling or unwinding. Otherwise, the allocated LUN
is lost until the image exits.

24.4.2 Allocating Event Flag Numbers


The LIB$GET_EF and LIB$FREE_EF routines operate in a similar way to
LIB$GET_LUN and LIB$FREE_LUN. They cause local event flags to be allocated
and deallocated at run time, so that your routine remains independent of other
routines executing in the same process.
Local event flags numbered 32 to 63 are available to your program. These event
flags allow routines to communicate and synchronize their operations. If you
use a specific event flag in your routine, another routine may attempt to use the
same flag, and the flag will no longer function as expected. Therefore, you should
call LIB$GET_EF to obtain the next arbitrary event flag and LIB$FREE_EF
to return it to the storage pool. You can obtain a specific event flag number by
calling LIB$RESERVE_EF. This routine takes as its argument the event flag
number to be allocated.
For information about using event flags, see Chapter 3 and Chapter 6.

24.5 Performance Measurement Routines


The run-time library timing facility consists of four routines to store count and
timing information, display the requested information, and deallocate the storage.
Table 24–9 lists these routines and their functions.

Table 24–9 Performance Measurement Routines


Entry Point Function
LIB$INIT_TIMER Stores the values of the specified times and counts in units of
static or heap storage, depending on the value of the routine’s
argument
LIB$SHOW_TIMER Obtains and formats for output the specified times and counts
that are accumulated since the last call to LIB$INIT_TIMER
LIB$STAT_TIMER Obtains one of the times and counts since the last call to
LIB$INIT_TIMER and returns it as an unsigned quadword or
longword
LIB$FREE_TIMER Frees the storage allocated by LIB$INIT_TIMER

Using these routines, you can access the following statistics:

Using Run-Time Library Routines to Access Operating System Components 24–17


Using Run-Time Library Routines to Access Operating System Components
24.5 Performance Measurement Routines

• Elapsed time
• CPU time
• Buffered I/O count
• Direct I/O count
• Page faults
The LIB$SHOW_TIMER and LIB$STAT_TIMER routine are relatively simple
tools for testing the performance of a new application. To obtain more detailed
information, use the system services SYS$GETTIM (Get Time) and SYS$GETJPI
(Get Job/Process Information).
The simplest way to use the run-time library routines is to call LIB$INIT_TIMER
with no arguments at the beginning of the portion of code to be monitored. This
causes the statistics to be placed in OWN storage. To get the statistics from OWN
storage, call LIB$SHOW_TIMER (with no arguments) at the end of the portion of
code to be monitored.
If you want a particular statistic, you must include a code argument with a call
to LIB$SHOW_TIMER or LIB$STAT_TIMER. LIB$SHOW_TIMER returns the
specified statistic(s) in formatted form and sends them to SYS$OUTPUT. On
each call, LIB$STAT_TIMER returns one statistic to the calling program as an
unsigned longword or quadword value.
Table 24–10 shows the code argument in LIB$SHOW_TIMER or LIB$STAT_
TIMER.

Table 24–10 The Code Argument in LIB$SHOW_TIMER and LIB$STAT_TIMER


Argument LIB$SHOW_TIMER LIB$STAT_TIMER
Value Meaning Format Format
1 Elapsed real time dddd hh:mm:ss.cc Quadword, in
system time
format
2 Elapsed CPU time hhhh:mm:ss.cc Longword, in
10-millisecond
increments
3 Number of buffered I/O nnnn Longword
operations
4 Number of direct I/O nnnn Longword
operations
5 Number of page faults nnnn Longword

When you call LIB$INIT_TIMER, you must use the optional handler argument
only if you want to keep several sets of statistics simultaneously. This argument
points to a block in heap storage where the statistics are to be stored. You need to
call LIB$FREE_TIMER only if you have specified handler in LIB$INIT_TIMER
and you want to deallocate all heap storage resources. In most cases, the implicit
deallocation when the image exits is sufficient.
The LIB$STAT_TIMER routine returns only one of the five statistics for each call,
and it returns that statistic in the form of an unsigned quadword or longword.
LIB$SHOW_TIMER returns the virtual address of the stored information,
which BASIC cannot directly access. Therefore, a BASIC program must call

24–18 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.5 Performance Measurement Routines

LIB$STAT_TIMER and format the returned statistics, as the following example


demonstrates.
Example
The following BASIC example uses the run-time library performance analysis
routines to obtain timing statistics. It then calls the $ASCTIM system service to
translate the 64-bit binary value returned by LIB$STAT_TIMER into an ASCII
text string.

100 EXTERNAL INTEGER FUNCTION LIB$INIT_TIMER


EXTERNAL INTEGER FUNCTION LIB$STAT_TIMER
EXTERNAL INTEGER FUNCTION LIB$FREE_TIMER
EXTERNAL INTEGER CONSTANT SS$_NORMAL
200 DECLARE LONG COND_VALUE, RANDOM_SLEEP
DECLARE LONG CODE, HANDLE
DECLARE STRING TIME_BUFFER
HANDLE = 0
TIME_BUFFER = SPACE$(50%)
300 MAP (TIMER) LONG ELAPSED_TIME, FILL
MAP (TIMER) LONG CPU_TIME
MAP (TIMER) LONG BUFIO
MAP (TIMER) LONG DIRIO
MAP (TIMER) LONG PAGE_FAULTS
400 PRINT "This program returns information about:"
PRINT "Elapsed time (1)"
PRINT "CPU time (2)"
PRINT "Buffered I/O (3)"
PRINT "Direct I/O (4)"
PRINT "Page faults (5)"
PRINT "Enter zero to exit program"
PRINT "Enter a number from one to"
PRINT "five for performance information"
INPUT "One, two, three, four, or five"; CODE
PRINT
450 GOTO 32766 IF CODE = 0
500 COND_VALUE = LIB$INIT_TIMER( HANDLE )
550 IF (COND_VALUE <> SS$_NORMAL) THEN PRINT @
"Error in initialization"
GOTO 32767
650 A = 0 !
FOR I = 1 to 100000 ! This code merely uses some CPU time
A = A + 1 !
NEXT I !
700 COND_VALUE = LIB$STAT_TIMER( CODE, ELAPSED_TIME, HANDLE )
750 IF (COND_VALUE <> SS$_NORMAL) THEN PRINT @
"Error in statistics routine"
GOTO 32767
800 GOTO 810 IF CODE <> 1%
CALL SYS$ASCTIM ( , TIME_BUFFER, ELAPSED_TIME, 1% BY VALUE)
PRINT "Elapsed time: "; TIME_BUFFER
810 PRINT "CPU time in seconds: "; .01 * CPU_TIME IF CODE = 2%
PRINT "Buffered I/O: ";BUFIO IF CODE = 3%
PRINT "Direct I/O: ";DIRIO IF CODE = 4%
PRINT "Page faults: ";PAGE_FAULTS IF CODE = 5%
PRINT
900 GOTO 400

Using Run-Time Library Routines to Access Operating System Components 24–19


Using Run-Time Library Routines to Access Operating System Components
24.5 Performance Measurement Routines

32765 COND_VALUE = LIB$FREE_TIMER( HANDLE )


32766 IF (COND_VALUE <> SS$_NORMAL) THEN PRINT @
"Error in LIB$FREE_TIMER"
GOTO 32767
32767 END
For information about using system time, see Chapter 27.

24.6 Output Formatting Control Routines


Table 24–11 lists the run-time library routines that customize output.

Table 24–11 Routines for Customizing Output


Entry Point Function
LIB$CURRENCY Defines the default currency symbol for process
LIB$DIGIT_SEP Defines the default digit separator for process
LIB$LP_LINES Defines the process default size for a printed page
LIB$RADIX_POINT Defines the process default radix point character

The LIB$CURRENCY, LIB$DIGIT_SEP, LIB$LP_LINES, and LIB$RADIX_


POINT routines allow you to customize output. Using them, you can define
the logical names SYS$CURRENCY, SYS$DIGIT_SEP, SYS$LP_LINES, and
SYS$RADIX_POINT to specify your own currency symbol, digit separator, radix
point, or number of lines per printed page. Each routine works by attempting
to translate the associated logical name as a process, group, or system logical
name. If you have redefined a logical name for a specific local application, then
the translation succeeds, and the routine returns the value that corresponds to
the option you have chosen. If the translation fails, the routine returns a default
value provided by the run-time library, as follows:
$ SYS$CURRENCY
, SYS$DIGIT_SEP
. SYS$RADIX_POINT
66 SYS$LP_LINES
For example, if you want to use the British pound sign (£) as the currency symbol
within your process, but you want to leave the dollar sign ($) as the system
default, define SYS$CURRENCY to be in your process logical name table. Then,
any calls to LIB$CURRENCY within your process return ‘‘£’’, while any calls
outside your process return ‘‘$’’.
You can use LIB$LP_LINES to monitor the current default length of the line
printer page. You can also supply your own default length for the current process.
United States standard paper size permits 66 lines on each physical page.
If you are writing programs for a utility that formats a listing file to be printed
on a line printer, you can use LIB$LP_LINES to make your utility independent
of the default page length. Your program can use LIB$LP_LINES to obtain the
current length of the page. It can then calculate the number of lines of text per
page by subtracting the lines used for margins and headings.
The following is one suggested format:
• Three lines for the top margin
• Three lines for the bottom margin

24–20 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.6 Output Formatting Control Routines

• Three lines for listing heading information, consisting of:


Language-processor identification line
Source program identification line
One blank line

24.7 Miscellaneous Interface Routines


There are several other RTL routines that permit high-level access to components
of the operating system. Table 24–12 lists these routines and their functions. The
sections that follow give further details about some of these routines.

Table 24–12 Miscellaneous Interface Routines


Entry Point Function
LIB$AST_IN_PROG Indicates whether an asynchronous system trap is in
progress
LIB$ASN_WTH_MBX Assigns an I/O channel and associates it with a
mailbox
LIB$CREATE_DIR Creates a directory or subdirectory
LIB$FIND_IMAGE_SYMBOL Reads a global symbol from the shareable image file
and dynamically activates a shareable image into the
P0 address space of a process
LIB$ADDX Performs addition on signed two’s complement
integers of arbitrary length (multiple-precision
addition)
LIB$SUBX Performs subtraction on signed two’s complement
integers of arbitrary length (multiple-precision
subtraction)
LIB$FILE_SCAN Finds file names given OpenVMS RMS file access
block (FAB)
LIB$FILE_SCAN_END Specifies end-of-file scan
LIB$FIND_FILE Finds file names given string
LIB$FIND_FILE_END Specifies the end-of-find file
LIB$INSERT_TREE Inserts an element in a binary tree
LIB$LOOKUP_TREE Finds an element in a binary tree
LIB$TRAVERSE_TREE Traverses a binary tree
LIB$GET_COMMON Gets a record from the process’s COMMON storage
area
LIB$PUT_COMMON Puts a record to the process’s COMMON storage area

24.7.1 Indicating Asynchronous System Trap in Progress


An asynchronous system trap (AST) is a mechanism for providing a software
interrupt when an external event occurs, such as when a user presses the Ctrl/C
key sequence. When an external event occurs, the operating system interrupts
the execution of the current process and calls a routine that you supply. While
that routine is active, the AST is said to be in progress, and the process is said to
be executing at AST level. When your AST routine returns control to the original
process, the AST is no longer active and execution continues where it left off.

Using Run-Time Library Routines to Access Operating System Components 24–21


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

The LIB$AST_IN_PROG routine indicates to the calling program whether an


AST is currently in progress. Your program can call LIB$AST_IN_PROG to
determine whether it is executing at AST level, and then take appropriate action.
This routine is useful if you are writing AST-reentrant code.
For information about using ASTs, see Chapter 8.

24.7.2 Create a Directory or Subdirectory


The LIB$CREATE_DIR routine creates a directory or a subdirectory. The calling
program must specify the directory specification in standard OpenVMS RMS
format. This directory specification may also contain a disk specification.
In addition to the required directory specification argument, LIB$CREATE_DIR
takes the following five optional arguments:
• The user identification code (UIC) of the owner of the created directory or
subdirectory
• The protection enable mask
• The protection value mask
• The maximum number of versions allowed for files created in this directory or
subdirectory
• The relative volume number within the volume set on which the directory or
subdirectory is created
See the OpenVMS RTL Library (LIB$) Manual for a complete description of
LIB$CREATE_DIR.

24.7.3 File Searching Routines


The run-time library provides two routines that your program can call to search
for a file and two routines that your program can call to end a search sequence:
• When you call LIB$FILE_SCAN with a wildcard file specification and an
action routine, the routine calls the action routine for each file or error, or
both, found in the wildcard sequence. LIB$FILE_SCAN allows the search
sequence to continue even though certain errors are present.
• When you call LIB$FIND_FILE with a wildcard file specification, it finds the
next file specification that matches the wildcard specification.
In addition to the wildcard file specification, which is a required argument,
LIB$FIND_FILE takes the following four optional arguments:
• The default specification.
• The related specification.
• The OpenVMS RMS secondary status value from a failing RMS operation.
• A longword containing two flag bits. If bit 1 is set, LIB$FIND_FILE performs
temporary defaulting for multiple input files and the related specification
argument is ignored. See the OpenVMS RTL Library (LIB$) Manual for a
complete description of LIB$FIND_FILE in template format.
The LIB$FIND_FILE_END routine is called once after each call to LIB$FIND_
FILE in interactive use. LIB$FIND_FILE_END prevents the temporary default
values retained by the previous call to LIB$FIND_FILE from affecting the next
file specification.

24–22 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

The LIB$FILE_SCAN routine uses an optional context argument to perform


temporary defaulting for multiple input files. For example, a command such as
the following would specify A, B, and C in successive calls, retaining context, so
that portions of one file specification would affect the next file specification:
$ COPY [smith]A,B,C *
The LIB$FILE_SCAN_END routine is called once after each sequence of calls to
LIB$FILE_SCAN. LIB$FILE_SCAN_END performs a parse of the null string to
deallocate saved OpenVMS RMS context and to prevent the temporary default
values retained by the previous call to LIB$FILE_SCAN from affecting the next
file specification. For instance, in the previous example, LIB$FILE_SCAN_END
should be called after the C file specification is parsed, so that specifications from
the $COPY files do not affect file specifications in subsequent commands.
The following BLISS example illustrates the use of LIB$FIND_FILE. It prompts
for a file specification and default specification. The default specification indicates
the default information for the file for which you are searching. Once the routine
has searched for one file, the resulting file specification determines both the
related file specification and the default file specification for the next search.
LIB$FIND_FILE_END is called at the end of the following BLISS program to
deallocate the virtual memory used by LIB$FIND_FILE.

%TITLE ’FILE_EXAMPLE1 - Sample program using LIB$FIND_FILE’


MODULE FILE_EXAMPLE1( ! Sample program using LIB$FIND_FILE
IDENT = ’1-001’,
MAIN = EXAMPLE_START
) =
BEGIN
%SBTTL ’Declarations’
!+
! SWITCHES:
!-
SWITCHES ADDRESSING_MODE (EXTERNAL = GENERAL, NONEXTERNAL = WORD_RELATIVE);
!+
! TABLE OF CONTENTS:
!-
FORWARD ROUTINE
EXAMPLE_START; ! Main program
!+
! INCLUDE FILES:
!-
LIBRARY ’SYS$LIBRARY:STARLET.L32’; ! System symbols
!+
! Define facility-specific messages from shared system messages.
!-
$SHR_MSGDEF(CLI,3,LOCAL,
(PARSEFAIL,WARNING));
!+
! EXTERNAL REFERENCES:
!-
EXTERNAL ROUTINE
LIB$GET_INPUT, ! Read from SYS$INPUT
LIB$FIND_FILE, ! Wildcard scanning routine
LIB$FIND_FILE_END, ! End find file
LIB$PUT_OUTPUT, ! Write to SYS$OUTPUT
STR$COPY_DX; ! String copier

Using Run-Time Library Routines to Access Operating System Components 24–23


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

LITERAL
TRUE = 1, ! Success
FALSE = 0; ! Failure
%SBTTL ’EXAMPLE_START - Sample program main routine’;
ROUTINE EXAMPLE_START =
BEGIN
!+
! This program reads a file specification and default file
! specification from SYS$INPUT. It then prints all the files that
! match that specification and prompts for another file specification.
! After the first file specification no default specification is requested,
! and the previous resulting file specification becomes the related
! file specification.
!-
LOCAL
LINEDESC : $BBLOCK[DSC$C_S_BLN], ! String desc. for input line
RESULT_DESC : $BBLOCK[DSC$C_S_BLN], ! String desc. for result file
CONTEXT, ! LIB$FIND_FILE context pointer
DEFAULT_DESC : $BBLOCK[DSC$C_S_BLN], ! String desc. for default spec
RELATED_DESC : $BBLOCK[DSC$C_S_BLN], ! String desc. for related spec
HAVE_DEFAULT,
STATUS;
!+
! Make all string descriptors dynamic.
!-
CH$FILL(0,DSC$C_S_BLN,LINEDESC);
LINEDESC[DSC$B_CLASS] = DSC$K_CLASS_D;
CH$MOVE(DSC$C_S_BLN,LINEDESC,RESULT_DESC);
CH$MOVE(DSC$C_S_BLN,LINEDESC,DEFAULT_DESC);
CH$MOVE(DSC$C_S_BLN,LINEDESC,RELATED_DESC);
HAVE_DEFAULT = FALSE;
CONTEXT = 0;
!+
! Read file specification, default file specification, and
! related file specification.
!-
WHILE (STATUS = LIB$GET_INPUT(LINEDESC,
$DESCRIPTOR(’FILE SPECIFICATION: ’))) NEQ RMS$_EOF
DO BEGIN
IF NOT .STATUS
THEN SIGNAL_STOP(.STATUS);
!+
! If default file specification was not obtained, do so now.
!-
IF NOT .HAVE_DEFAULT
THEN BEGIN
STATUS = LIB$GET_INPUT(DEFAULT_DESC,
$DESCRIPTOR(’DEFAULT FILE SPECIFICATION: ’));
IF NOT .STATUS
THEN SIGNAL_STOP(.STATUS);
HAVE_DEFAULT = TRUE;
END;
!+
! CALL LIB$FIND_FILE until RMS$_NMF (no more files) is returned.
! If an error other than RMS$_NMF is returned, it is signaled.
! Print out the file specification if the call is successful.
!-
WHILE (STATUS = LIB$FIND_FILE(LINEDESC,RESULT_DESC,CONTEXT,
DEFAULT_DESC,RELATED_DESC)) NEQ RMS$_NMF
DO IF NOT .STATUS
THEN SIGNAL(CLI$_PARSEFAIL,1,RESULT_DESC,.STATUS)
ELSE LIB$PUT_OUTPUT(RESULT_DESC);
!+
! Make this resultant file specification the related file

24–24 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

! specification for next file.


!-
STR$COPY_DX(RELATED_DESC,LINEDESC);
END; ! End of loop
! reading file specification
!+
! Call LIB$FIND_FILE_END to deallocate the virtual memory used by LIB$FIND_FILE.
! Note that we do this outside of the loop. Since the MULTIPLE bit of the
! optional user flags argument to LIB$FIND_FILE wasn’t used, it is not
! necessary to call LIB$FIND_FILE_END after each call to LIB$FIND_FILE.
! (The MULTIPLE bit would have caused temporary defaulting for multiple input
! files.)
!-
STATUS = LIB$FIND_FILE_END (CONTEXT);
IF NOT .STATUS
THEN SIGNAL_STOP (.STATUS);
RETURN TRUE
END; ! End of main program
END ! End of module
ELUDOM

Using Run-Time Library Routines to Access Operating System Components 24–25


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

The following BLISS example illustrates the use of LIB$FILE_SCAN and


LIB$FILE_SCAN_END.

%TITLE ’FILE_EXAMPLE2 - Sample program using LIB$FILE_SCAN’


MODULE FILE_EXAMPLE1( ! Sample program using LIB$FILE_SCAN
IDENT = ’1-001’,
MAIN = EXAMPLE_START
) =
BEGIN
%SBTTL ’Declarations’
!+
! SWITCHES:
!-
SWITCHES ADDRESSING_MODE (EXTERNAL = GENERAL,
NONEXTERNAL = WORD_RELATIVE);
!+
! TABLE OF CONTENTS:
!-
FORWARD ROUTINE
EXAMPLE_START, ! Main program
SUCCESS_RTN, ! Success action routine
ERROR_RTN; ! Error action routine
!+
! INCLUDE FILES:
!-
LIBRARY ’SYS$LIBRARY:STARLET.L32’; ! System symbols
!+
! Define VMS block structures (BLOCK[,BYTE]).
!-
STRUCTURE
BBLOCK [O, P, S, E; N] =
[N]
(BBLOCK + O) <P, S, E>;
!+
! EXTERNAL REFERENCES:
!-
EXTERNAL ROUTINE
LIB$GET_INPUT, ! Read from SYS$INPUT
LIB$FILE_SCAN, ! Wildcard scanning routine
LIB$FILE_SCAN_END, ! End of file scan
LIB$PUT_OUTPUT; ! Write to SYS$OUTPUT

24–26 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

%SBTTL ’EXAMPLE_START - Sample program main routine’;


ROUTINE EXAMPLE_START =
BEGIN
!+
! This program reads the file specification, default file specification,
! and related file specification from SYS$INPUT and then displays on
! SYS$OUTPUT all files which match the specification.
!-
LOCAL
RESULT_BUFFER : VECTOR[NAM$C_MAXRSS,BYTE], !Buffer for resultant
! name string
EXPAND_BUFFER : VECTOR[NAM$C_MAXRSS,BYTE], !Buffer for expanded
! name string
LINEDESC : BBLOCK[DSC$C_S_BLN], !String descriptor
! for input line
RESULT_DESC : BBLOCK[DSC$C_S_BLN], !String descriptor
! for result file
DEFAULT_DESC : BBLOCK[DSC$C_S_BLN], !String descriptor
! for default specification
RELATED_DESC : BBLOCK[DSC$C_S_BLN], !String descriptor
! for related specification
IFAB : $FAB_DECL, !FAB for file_scan
INAM : $NAM_DECL, ! and a NAM block
RELNAM : $NAM_DECL, ! and a related NAM block
STATUS;
!+
! Make all descriptors dynamic.
!-
CH$FILL(0,DSC$C_S_BLN,LINEDESC);
LINEDESC[DSC$B_CLASS] = DSC$K_CLASS_D;
CH$MOVE(DSC$C_S_BLN,LINEDESC,RESULT_DESC);
CH$MOVE(DSC$C_S_BLN,LINEDESC,DEFAULT_DESC);
CH$MOVE(DSC$C_S_BLN,LINEDESC,RELATED_DESC);
!+
! Read file specification, default file specification, and related
! file specification
!-
STATUS = LIB$GET_INPUT(LINEDESC,
$DESCRIPTOR(’File specification: ’));
IF NOT .STATUS
THEN SIGNAL_STOP(.STATUS);
STATUS = LIB$GET_INPUT(DEFAULT_DESC,
$DESCRIPTOR(’Default file specification: ’));
IF NOT .STATUS
THEN SIGNAL_STOP(.STATUS);
STATUS = LIB$GET_INPUT(RELATED_DESC,
$DESCRIPTOR(’Related file specification: ’));
IF NOT .STATUS
THEN SIGNAL_STOP(.STATUS);
!+
! Initialize the FAB, NAM, and related NAM blocks.
!-
$FAB_INIT(FAB=IFAB,
FNS=.LINEDESC[DSC$W_LENGTH],
FNA=.LINEDESC[DSC$A_POINTER],
DNS=.DEFAULT_DESC[DSC$W_LENGTH],
DNA=.DEFAULT_DESC[DSC$A_POINTER],
NAM=INAM);
$NAM_INIT(NAM=INAM,
RSS=NAM$C_MAXRSS,
RSA=RESULT_BUFFER,
ESS=NAM$C_MAXRSS,
ESA=EXPAND_BUFFER,
RLF=RELNAM);

Using Run-Time Library Routines to Access Operating System Components 24–27


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

$NAM_INIT(NAM=RELNAM);
RELNAM[NAM$B_RSL] = .RELATED_DESC[DSC$W_LENGTH];
RELNAM[NAM$L_RSA] = .RELATED_DESC[DSC$A_POINTER];
!+
! Call LIB$FILE_SCAN. Note that errors need not be checked
! here because LIB$FILE_SCAN calls error_rtn for all errors.
!-
LIB$FILE_SCAN(IFAB,SUCCESS_RTN,ERROR_RTN);
!+
! Call LIB$FILE_SCAN_END to deallocate virtual memory used for
! file scan structures.
!-
STATUS = LIB$FILE_SCAN_END (IFAB);
IF NOT .STATUS
THEN SIGNAL_STOP (.STATUS);
RETURN 1
END; ! End of main program
ROUTINE SUCCESS_RTN (IFAB : REF BBLOCK) =
BEGIN
!+
! This routine is called by LIB$FILE_SCAN for each file that it
! successfully finds in the search sequence.
!
! Inputs:
!
! IFAB Address of a fab
!
! Outputs:
!
! file specification printed on SYS$OUTPUT
!-
LOCAL
DESC : BBLOCK[DSC$C_S_BLN]; ! A local string descriptor
BIND
INAM = .IFAB[FAB$L_NAM] : BBLOCK; ! Find NAM block
! from pointer in FAB
CH$FILL(0,DSC$C_S_BLN,DESC); ! Make static
! string descriptor
DESC[DSC$W_LENGTH] = .INAM[NAM$B_RSL]; ! Get string length
! from NAM block
DESC[DSC$A_POINTER] = .INAM[NAM$L_RSA]; ! Get pointer to the string
RETURN LIB$PUT_OUTPUT(DESC) ! Print name on SYS$OUTPUT
! and return
END;
ROUTINE ERROR_RTN (IFAB : REF BBLOCK) =
BEGIN
!+
! This routine is called by LIB$FILE_SCAN for each file specification that
! produces an error.
!
! Inputs:
!
! ifab Address of a fab
!
! Outputs:
!
! Error message is signaled
!-
LOCAL
DESC : BBLOCK[DSC$C_S_BLN]; ! A local string descriptor

24–28 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

BIND
INAM = .IFAB[FAB$L_NAM] : BBLOCK; ! Get NAM block pointer
! from FAB
CH$FILL(0,DSC$C_S_BLN,DESC); ! Create static
! string descriptor
DESC[DSC$W_LENGTH] = .INAM[NAM$B_RSL];
DESC[DSC$A_POINTER] = .INAM[NAM$L_RSA];
!+
! Signal the error using the shared message PARSEFAIL
! and the CLI facility code. The second part of the SIGNAL
! is the RMS STS and STV error codes.
!-
RETURN SIGNAL((SHR$_PARSEFAIL+3^16),1,DESC,
.IFAB[FAB$L_STS],.IFAB[FAB$L_STV])
END;
END ! End of module
ELUDOM

24.7.4 Inserting an Entry into a Balanced Binary Tree


Three routines allow you to manipulate the contents of a balanced binary tree:
• LIB$INSERT_TREE adds an entry to a balanced binary tree.
• LIB$LOOKUP_TREE looks up an entry in a balanced binary tree.
• LIB$TRAVERSE_TREE calls an action routine for each node in the tree.
Example
The following BLISS example illustrates all three routines. The program prompts
for input from SYS$INPUT and stores each data line as an entry in a binary
tree. When the user enters the end-of-file character (Ctrl/Z), the tree is printed in
sorted order. The program includes three subroutines:
• The first subroutine allocates virtual memory for a node.
• The second subroutine compares a key with a node.
• The third subroutine is called during the tree traversal. It prints out the left
and right subtree pointers, the current node balance, and the name of the
node.

%TITLE ’TREE_EXAMPLE - Sample program using binary tree routines’


MODULE TREE_EXAMPLE( ! Sample program using trees
IDENT = ’1-001’,
MAIN = TREE_START
) =
BEGIN
%SBTTL ’Declarations’
!+
! SWITCHES:
!-
SWITCHES ADDRESSING_MODE (EXTERNAL = GENERAL, NONEXTERNAL = WORD_RELATIVE);
!+
! LINKAGES:
!
! NONE
!
! TABLE OF CONTENTS:
!-

Using Run-Time Library Routines to Access Operating System Components 24–29


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

FORWARD ROUTINE
TREE_START, ! Main program
ALLOC_NODE, ! Allocate memory for a node
COMPARE_NODE, ! Compare two nodes
PRINT_NODE; ! Print a node (action routine
! for LIB$TRAVERSE_TREE)
!+
! INCLUDE FILES:
!-
LIBRARY ’SYS$LIBRARY:STARLET.L32’; ! System symbols
!+
! Define VMS block structures (BLOCK[,BYTE]).
!-
STRUCTURE
BBLOCK [O, P, S, E; N] =
[N]
(BBLOCK + O) <P, S, E>;
!+
! MACROS:
!-
MACRO
NODE$L_LEFT = 0,0,32,0%, ! Left subtree pointer in node
NODE$L_RIGHT = 4,0,32,0%, ! Right subtree pointer
NODE$W_BAL = 8,0,16,0%, ! Balance this node
NODE$B_NAMLNG = 10,0,8,0%, ! Length of name in this node
NODE$T_NAME = 11,0,0,0%; ! Start of name (variable length)
LITERAL
NODE$C_LENGTH = 11; ! Length of fixed part of node
!+
! EXTERNAL REFERENCES:
!-
EXTERNAL ROUTINE
LIB$GET_INPUT, ! Read from SYS$INPUT
LIB$GET_VM, ! Allocate virtual memory
LIB$INSERT_TREE, ! Insert into binary tree
LIB$LOOKUP_TREE, ! Lookup in binary tree
LIB$PUT_OUTPUT, ! Write to SYS$OUTPUT
LIB$TRAVERSE_TREE, ! Traverse a binary tree
STR$UPCASE, ! Convert string to all uppercase
SYS$FAO; ! Formatted ASCII output routine
%SBTTL ’TREE_START - Sample program main routine’;
ROUTINE TREE_START =
BEGIN
!+
! This program reads from SYS$INPUT and stores each data line
! as an entry in a binary tree. When end-of-file character (CTRL/Z)
! is entered, the tree will be printed in sorted order.
!-
LOCAL
NODE : REF BBLOCK, ! Address of allocated node
TREEHEAD, ! List head of binary tree
LINEDESC : BBLOCK[DSC$C_S_BLN], ! String descriptor for input line
STATUS;

24–30 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

TREEHEAD = 0; ! Zero binary tree head


CH$FILL(0,DSC$C_S_BLN,LINEDESC); ! Make a dynamic descriptor
LINEDESC[DSC$B_CLASS] = DSC$K_CLASS_D; ! ...
!+
! Read input lines until end of file seen.
!-
WHILE (STATUS = LIB$GET_INPUT(LINEDESC, ! Read input line
$DESCRIPTOR(’Text: ’))) ! with this prompt
NEQ RMS$_EOF
DO IF NOT .STATUS ! Report any errors found
THEN SIGNAL(.STATUS)
ELSE BEGIN
STR$UPCASE(LINEDESC,LINEDESC); ! Convert string
! to uppercase
IF NOT (STATUS = LIB$INSERT_TREE(
TREEHEAD, ! Insert good data into the tree
LINEDESC, ! Data to insert
%REF(1), ! Insert duplicate entries
COMPARE_NODE, ! Addr. of compare routine
ALLOC_NODE, ! Addr. of node allocation routine
NODE, ! Return addr. of
0)) ! allocated node here
THEN SIGNAL(.STATUS);
END;
!+
! End of file character encountered. Print the whole tree and exit.
!-
IF NOT (STATUS = LIB$TRAVERSE_TREE(
TREEHEAD, ! Listhead of tree
PRINT_NODE, ! Action routine to print a node
0))
THEN SIGNAL(.STATUS);
RETURN SS$_NORMAL
END; ! End of routine tree_start
ROUTINE ALLOC_NODE (KEYDESC,RETDESC,CONTEXT) =
BEGIN
!+
! This routine allocates virtual memory for a node.
!
! INPUTS:
!
! KEYDESC Address of string descriptor for key
! (this is the linedesc argument passed
! to LIB$INSERT_TREE)
! RETDESC Address of location to return address of
! allocated memory
! CONTEXT Address of user context argument passed
! to LIB$INSERT_TREE (not used in this
! example)
!
! OUTPUTS:
!
! Memory address returned in longword pointed to by retdesc
!-
MAP
KEYDESC : REF BBLOCK,
RETDESC : REF VECTOR[,LONG];
LOCAL
NODE : REF BBLOCK,
STATUS;

Using Run-Time Library Routines to Access Operating System Components 24–31


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

STATUS = LIB$GET_VM(%REF(NODE$C_LENGTH+.KEYDESC[DSC$W_LENGTH]),NODE);
IF NOT .STATUS
THEN RETURN .STATUS
ELSE BEGIN
NODE[NODE$B_NAMLNG] = .KEYDESC[DSC$W_LENGTH]; ! Set name length
CH$MOVE(.KEYDESC[DSC$W_LENGTH], ! Copy in the name
.KEYDESC[DSC$A_POINTER],
NODE[NODE$T_NAME]);
RETDESC[0] = .NODE; ! Return address to caller
END;
RETURN .STATUS
END;

ROUTINE COMPARE_NODE (KEYDESC,NODE,CONTEXT) =


BEGIN
!+
! This routine compares a key with a node.
!
! INPUTS:
!
! KEYDESC Address of string descriptor for new key
! (This is the linedesc argument passed to
! LIB$INSERT_TREE)
! NODE Address of current node
! CONTEXT User context data (Not used in this example)
!-
MAP
KEYDESC : REF BBLOCK,
NODE : REF BBLOCK;
RETURN CH$COMPARE(.KEYDESC[DSC$W_LENGTH], ! Compare key with
! current node
.KEYDESC[DSC$A_POINTER],
.NODE[NODE$B_NAMLNG],
NODE[NODE$T_NAME])
END;
ROUTINE PRINT_NODE (NODE,CONTEXT) =
BEGIN
!+
! This routine is called during the tree traversal. It
! prints out the left and right subtree pointers, the
! current node balance, and the name of the node.
!-
MAP
NODE : REF BBLOCK;

24–32 Using Run-Time Library Routines to Access Operating System Components


Using Run-Time Library Routines to Access Operating System Components
24.7 Miscellaneous Interface Routines

LOCAL
OUTBUF : BBLOCK[512], ! FAO output buffer
OUTDESC : BBLOCK[DSC$C_S_BLN], ! Output buffer descriptor
STATUS;
CH$FILL(0,DSC$C_S_BLN,OUTDESC); ! Zero descriptor
OUTDESC[DSC$W_LENGTH] = 512;
OUTDESC[DSC$A_POINTER] = OUTBUF;
IF NOT (STATUS = SYS$FAO($DESCRIPTOR(’!XL !XL !XL !XW !AC’),
OUTDESC,OUTDESC,
.NODE,.NODE[NODE$L_LEFT],
.NODE[NODE$L_RIGHT],
.NODE[NODE$W_BAL],
NODE[NODE$B_NAMLNG]))
THEN SIGNAL(.STATUS)
ELSE BEGIN
STATUS = LIB$PUT_OUTPUT(OUTDESC); ! Output the line
IF NOT .STATUS
THEN SIGNAL(.STATUS);
END;
RETURN SS$_NORMAL
END;
END ! End of module TREE_EXAMPLE
ELUDOM

Using Run-Time Library Routines to Access Operating System Components 24–33


25
Using Cross-Reference Routines

The cross-reference routines are contained in a separate, shareable image capable


of creating a cross-reference analysis of symbols. They accept cross-reference
data, summarize it, and format it for output. Two facilities that use the
cross-reference routines are the VMS Linker and the MACRO assembler. They
are sufficiently general, however, to be used by any native-mode utility.
Table 25–1 lists the entry points and functions of the cross-reference routines.

Table 25–1 Cross-Reference Routines


Entry Point Function
LIB$CRF_INS_KEY Inserts key information
LIB$CRF_INS_REF Inserts reference information
LIB$CRF_OUTPUT Summarizes and formats cross-reference information

The interface to the cross-reference routines is by way of a set of control blocks,


format definition tables, and a set of callable entry points. Macros are provided
for assembly language and BLISS initialization of the control blocks and format
definition tables.

25.1 How to Use the Cross-Reference Routines


Using the cross-reference routines involves the following steps:
1. Define a table of control information, using the $CRFCTLTABLE macro.
2. Define each field of the output line, using the $CRFFIELD macro.
3. Specify the end of each set of macros that define a field in the output line,
using the $CRFFIELDEND macro.
4. Provide data by calling one of the two following cross-reference entry points:

• LIB$CRF_INS_KEY inserts an entry for the specified key in the specified


symbol table.
• LIB$CRF_INS_REF inserts a reference to a key in the specified symbol
table.
5. Call LIB$CRF_OUTPUT, the cross-reference output routine, to summarize
and format the data.
6. Supply a routine that the output routine calls to print each line in the output
file. Because you supply this routine, you can control the number of lines per
page and the header lines.

Using Cross-Reference Routines 25–1


Using Cross-Reference Routines
25.1 How to Use the Cross-Reference Routines

Figure 25–1 Using Cross-Reference Routines

Step 1: Build the control blocks and the format


definition tables used for output.

Step 2: Call the cross−reference procedures


LIB$CRF_INS_KEY and LIB$CRF_INS_REF
to enter cross−reference data in the tables.

Step 3: Call the cross−reference procedure


LIB$CRF_OUTPUT when all data is accumulated
to summarize cross−reference output and
format the output lines. LIB$CRF_OUTPUT calls
the user−supplied print routine once for each line
of output.

ZK−1970−GE

Figure 25–1 illustrates the steps required in using the cross-reference routines.
The Run-Time Library provides three macros to initialize the data structures
used by the cross-reference routines:
1. $CRFCTLTABLE defines a table of control information.
2. $CRFFIELD defines each field of the output format definition table. Multiple
$CRFFIELD macro instructions can be issued in defining one particular field.
3. $CRFFIELDEND ends a set of $CRFFIELD macro instructions (a format
table).

25.2 $CRFCTLTABLE Macro


$CRFCTLTABLE initializes a cross-reference control table. Your program must
issue one $CRFCTLTABLE macro for each cross-reference table you build. You
can accumulate information for more than one cross-reference table at a time.
For this reason, you must define a table for each set of cross-references, and
include the address of that table each time you call a cross-reference routine to
insert data.
The $CRFCTLTABLE macro instruction has the following format:
label: $CRFCTLTABLE keytype, output, error, memexp, key1table,
key2table, val1table, val2table,
ref1table, ref2table

25–2 Using Cross-Reference Routines


Using Cross-Reference Routines
25.2 $CRFCTLTABLE Macro

label
The address of the control table. You must specify a control table address in all
calls to the cross-reference routines.

keytype
The type of key to enter into the table. The following key types are defined:
ASCIC Keys are counted ASCII strings, with a maximum of 31 characters (symbol
name).
BIN_U32 Keys are 32-bit unsigned binary values. The binary-to-ASCII conversion is
done by $FAO using the format string for the KEY1 field.

output
The address of the routine that you supply to print a formatted output line. The
output line is passed to the output routine by descriptor.

error
The address of an error routine to execute if the called cross-reference routine
encounters an error. The error code (longword) is passed to the error routine by
value. In other words, it is a copy of the constant on the stack. A value of zero
indicates that no error routine is supplied.

memexp
The number of pages by which to expand region when needed. The default is 50.

key1table
The address of the field descriptor table for the KEY1 field. A value of zero
indicates that the field is not to be included in the output line.
The remaining arguments provide the address of the field descriptor tables for
the KEY2, VAL1, VAL2, REF1, and REF2 fields, respectively, of the output line.
You can use these argument names as keywords in the macros. For example, you
can use KEYTYPE as a keyword when issuing the $CRFCTLTABLE macro.

25.3 $CRFFIELD Macro


For each field in the output line, you must issue a $CRFFIELD instruction to
identify the field, supply an $FAO command string to control the printing of the
field, and provide flag information. See the program example and the description
of $FAO (formatted ASCII output) in the OpenVMS System Services Reference
Manual. The $CRFFIELD macro has the following format:
label: $CRFFIELD bit_mask, fao_string, field_width, set_clear

label
The address of the field descriptor table generated as a result of this set of
$CRFFIELD macro instructions. The label field can be omitted after the first
macro of the set. These addresses correspond to the field descriptor table
addresses in the $CRFCTLTABLE macro.

bit_mask
A 16-bit mask. When the user enters a key or reference, the cross-reference
routine stores flag information with the entry. When preparing the output line,
LIB$CRF_OUTPUT performs an AND operation on the 16-bit mask in the field
descriptor table with the flag stored with the entry. Any number of bit masks can
be defined for a field. $CRFFIELD macro instructions are used to define multiple
bit patterns for a flag field. The high-order bit is reserved to the cross-reference
routines.

Using Cross-Reference Routines 25–3


Using Cross-Reference Routines
25.3 $CRFFIELD Macro

fao_string
The $FAO command string. LIB$CRF_OUTPUT uses this string to determine the
$FAO format when formatting this field for output.

field_width
The maximum width of the output field.

set_clear
The indicator used to determine whether the bit mask is to be tested as set or
clear when determining which flag to use. SET indicates test for set; CLEAR
indicates test for clear.
You can use the argument names shown here as keywords in your program.
In the following example, one bit pattern is defined twice; once indicating a string
that is to be printed if the pattern is set, and once indicating that spaces are to
appear if the pattern is clear.
$CRFFIELD BIT_MASK=SYM$M_REL, FAO_STRING=3_\##_\,-
SET_CLEAR=CLEAR, FIELD_WIDTH=2
$CRFFIELD BIT_MASK=SYM$M_REL, FAO_STRING=_\-R_\,-
SET_CLEAR=SET, FIELD_WIDTH=2
If more than one set of flags is defined for a field, each FAO string must print the
same number of characters; otherwise, the output is not aligned in columns.
The fields for the symbol name, symbol value, and references are always
formatted using the first descriptor in the corresponding table.

25.4 $CRFFIELDEND Macro


The $CRFFIELDEND macro instruction marks the end of a set of macros that
describe one field of the output line. It is used once to end each set of field
descriptors. It has the following format:
$CRFFIELDEND

25.5 Cross-Reference Output


LIB$CRF_OUTPUT can format output lines for three types of cross-reference
listings:
1. A summary of symbol names and their values, as illustrated in Figure 25–2.
2. A summary of symbol names, their values, and the names of modules that
refer to the symbol, as illustrated in Figure 25–3.
3. A summary of symbol names, their values, the name of the defining module,
and the names of those modules that refer to the symbol, as illustrated in
Figure 25–4.

25–4 Using Cross-Reference Routines


Using Cross-Reference Routines
25.5 Cross-Reference Output

Figure 25–2 Summary of Symbol Names and Values

Symbol Value Symbol Value


−−−−−− −−−−− −−−−−− −−−−−
BAS$INSTR 000020B0−RU BAS$SCRATCH 00002308−RU
BAS$IN_D_R 000021F0−RU BAS$STATUS 00002338−RU
BAS$IN_F_R 000021E8−RU BAS$STR_D 000020C0−RU
BAS$IN_L_R 000021E0−RU BAS$STR_F 000020B8−RU
BAS$IN_T_DX 000021F8−RU BAS$STR_L 000020C8−RU
BAS$IN_W_R 000021D8−RU BAS$UNLOCK 00002310−RU
BAS$IO_END 000021D0−RU BAS$UPDATE 000022E8−RU
BAS$LINKAGE 00001674−R BAS$UPDATE_COUN 000022F0−RU
BAS$LINPUT 000021A8−RU BAS$VAL_D 00002110−RU
BAS$MAT_INPUT 00002268−RU BAS$VAL_F 00002108−RU

ZK−1973−GE

Figure 25–3 Summary of Symbol Names, Values, and Name of Referring Modules

Symbol Value Referenced By ...


−−−−−− −−−−− −−−−−−−−−−−−−−−−−
BAS$K_DIVBY_ZER 0000003D ALLGBL BAS$ERROR
BAS$POWDJ BAS$POWII
BAS$POWRJ BAS$POWRR
BAS$K_DUPKEYDET 00000086 ALLGBL BAS$$SIGNAL_IO
BAS$K_ENDFILDEV 0000000B ALLGBL BAS$$REC_PROC
BAS$$UDF_RL
BAS$K_ENDOF_STA 0000006C ALLGBL
ZK−1974−GE

Figure 25–4 Summary Indicating Defining Module


Symbol Value Defined By Referenced By ...
−−−−−− −−−−− −−−−−−−−−− −−−−−−−−−−−−−−−−−
LIB$FREE_VM 0001E185−R LIB$VM ALLGBL
BAS$MARGIN
BAS$XLATE
FOR$VM
STR$APPEND
STR$DUPL_CHAR
STR$REPLACE
LIB$GET_COMMAND 0001E2B0−R LIB$GET_INPUT ALLGBL
LIB$GET_COMMON 0001E4D6−R LIB$COMMON ALLGBL

ZK−1971−GE

Regardless of the format of the output, LIB$CRF_OUTPUT considers the output


line to consist of the following six different field types:
1. KEY1 is the first field in the line. It contains a symbol name.
2. KEY2 is the second field in the line. It contains a set of flags (for example,–R)
providing information about the symbol.
3. VAL1 is the third field in the line. It contains the value of the symbol.
4. VAL2 is the fourth field in the line. It contains a set of flags describing VAL1.
5. REF1 and REF2 fields. Within each REF1 and REF2 pair, REF1 provides
a set of flags and REF2 provides the name of a module that references the
symbol.

Using Cross-Reference Routines 25–5


Using Cross-Reference Routines
25.5 Cross-Reference Output

Figure 25–5 shows that any of these fields can be omitted from the output.

Figure 25–5 Output Line for LIB$CRF_OUTPUT

Symbol Value Symbol Value


−−−−−− −−−−− −−−−−− −−−−−
BAS$INSTR 000020B0−RU BAS$SCRATCH 00002308−RU

KEY1 VAL1 VAL2 KEY1 VAL1 VAL2

Symbol Value Defined By Referenced By ...


−−−−−− −−−−− −−−−−−−−−− −−−−−−−−−−−−−−−−−
LIB$FREE_VM 0001E185−R LIB$VM ALLGBL

KEY1 VAL1 VAL2 REF2 REF2


(CRF$K_DEF) (CRF$K_REF)

ZK−1972−GE

25.6 Example
The VAX Linker uses the cross-reference routines to generate cross-reference
listings. This section uses the linker’s code as an example of using the cross-
reference routines in a MACRO program.

25.6.1 Defining Control Tables


Cross-reference routines use two control tables:
• The symbol-by-name table
• The symbol-by-value table
First, the linker uses the $CRFCTLTABLE macro to set up the characteristics
and fields of the symbol-by-name table. This table will list symbols by name and
provide a cross-reference synopsis. The table is set up as follows:
LNK$NAMTAB:
$CRFCTLTABLE KEYTYPE=ASCIC,ERROR=LNK$ERR_RTN,_
OUTPUT=LNK$MAPOUT,KEY1TABLE=LNK$KEY1,_
KEY2TABLE=LNK$KEY2,VAL1TABLE=LNK$VAL1,_
VAL2TABLE=LNK$VAL2,REF1TABLE=LNK$REF1,_
REF2TABLE=LNK$REF2

LNK$NAMTAB Names the address of the control table


KEYTYPE=ASCIC Specifies that the keys are counted ASCII strings (that is,
symbol names)
ERROR=LNK$ERR_RTN Indicates that LNK$ERR_RTN is the address of the
routine to be executed in case of error
OUTPUT=LNK$MAPOUT Names LNK$MAPOUT as the address of the user-
supplied routine that prints the formatted table
The remaining arguments provide the addresses of the field descriptor tables.

25–6 Using Cross-Reference Routines


Using Cross-Reference Routines
25.6 Example

After setting up the control tables, the linker defines each field of the cross-
reference output line, using the $CRFFIELD macro. After each set of definitions
for a field, it calls $CRFFIELDEND to mark the end of the field.
Note particularly the following two features of this set of definitions:
• The definition of LNK$VAL2 describes a flag to be associated with VAL1. The
definition contains alternative bit patterns, depending on the bit mask. When
an entry is made to the table, the entry contains flag information. Then,
when LIB$CRF_OUTPUT is called to format the data, the routine checks
each entry, matching the flags argument against the bit masks specified
in the control table. When LIB$CRF_OUTPUT finds a match, it uses that
definition to determine the format of the entry in the output table. For
example, BIT_MASK=SYM$M_DEF marks an entry as the defining reference.
The corresponding VAL1 entry is placed in the output table with an asterisk
in its flags field.
• The FAO control strings are defined to produce an output of the maximum
character size for each field. This ensures that the columns will line up
correctly in the output. For example, !15AC produces the variable symbol
name left-aligned and right-filled with spaces. Another example is the three
sets of characters to be printed for field VAL2. Each FAO control string
produces two characters, which is the maximum size of the field.
LNK$KEY1:
$CRFFIELD BIT_MASK=0, FAO_STRING=\!15AC\,-
SET_CLEAR=SET,FIELD_WIDTH=15
$CRFFIELDEND
LNK$KEY2:
$CRFFIELD BIT_MASK=0,FAO_STRING=\ \,-
SET_CLEAR=SET, FIELD_WIDTH=1
$CRFFIELDEND
LNK$VAL1:
$CRFFIELD BIT_MASK=0,FAO_STRING=\!XL\,-
SET_CLEAR=SET,FIELD_WIDTH=8
$CRFFIELDEND
LNK$VAL2:
$CRFFIELD BIT_MASK=0, FAO_STRING=\!2* \,-
SET_CLEAR=SET,FIELD_WIDTH=2
$CRFFIELD BIT_MASK=SYM$M_REL,FAO_STRING=\-R\,-
SET_CLEAR=SET,FIELD_WIDTH=2
$CRFFIELD BIT_MASK=SYM$M_DEF, FAO_STRING=\-*\,-
SET_CLEAR=CLEAR,FIELD_WIDTH=2
$CRFFIELDEND
LNK$REF1:
$CRFFIELD BIT_MASK=0,FAO_STRING=\!6* \,-
SET_CLEAR=SET,FIELD_WIDTH=6
$CRFFIELD BIT_MASK=SYM$M_WEAK,FAO_STRING=\!3* WK-\,-
SET_CLEAR=SET,FIELD_WIDTH=6
$CRFFIELDEND
LNK$REF2:
$CRFFIELD BIT_MASK=0,FAO_STRING=\!16AC\,-
SET_CLEAR=SET,FIELD_WIDTH=16
$CRFFIELDEND
After initializing the symbol-by-name table, the linker sets up a second control
table. This table defines the output for a symbol-by-value synopsis. For this
output, the value fields are eliminated. The symbols having this value are
entered as reference indicators. None is specified as the defining reference. The
control table uses the field descriptors set up previously. The following macro
instructions are used:

Using Cross-Reference Routines 25–7


Using Cross-Reference Routines
25.6 Example

LNK$VALTAB:
$CRFCTLTABLE KEYTYPE=BIN_U32, ERROR=LNK$ERR_RTN,-
OUTPUT=LNK$MAPOUT,KEY1TABLE=LNK$VAL1,-
KEY2TABLE=LNK$VAL2,VAL1TABLE=0,-
VAL2TABLE=0,REF1TABLE=LNK$REF1,-
REF2TABLE=LNK$REF2

25.6.2 Inserting Table Information


After initializing the format data for the symbol tables, the linker enters data
into the cross-reference tables by calling LIB$CRF_INS_KEY.
As the linker processes the first object module, MAPINITIAL, it encounters a
symbol definition for $MAPFLG. The following is an example of a call to enter the
symbol MAPINITIAL as a key in the cross-reference symbol table:
PUSHAB VALUE_FLAGS
PUSHAB VALUE_ADDR
PUSHAB SYMBOL_ADDR
PUSHAB LNK$NAMTAB
CALLS #4,G^LIB$CRF_INS_KEY

LNK$NAMTAB Is the address of the control table


SYMBOL_ADDR Is the address of the counted ASCII string $MAPFLG
VALUE_ADDR Is the address of the symbol value
VALUE_FLAGS Is the address of a word whose bits are used to select special
characters to print beside the value
The linker then calls LIB$CRF_INS_REF to process the defining reference
indicator:
DEF: .LONG CRF$K_DEF
PUSHAB DEF
PUSHAB REF_FLAGS
PUSHAB REF_ADDR
PUSHAB SYMBOL_ADDR
PUSHAB LNK$NAMTAB
CALLS #5,G^LIB$CRF_INS_REF

LNK$NAMTAB Is the address of the control table


SYMBOL_ADDR Is the address of the counted string $MAPFLG
REF_ADDR Is the address of the referrer’s counted ASCII string
REF_FLAGS Is the address of a word whose bits are used to select special
characters to print beside the reference
Further on in the input module, the linker encounters a global symbol reference
to CS$GBL. The call to store data for this reference is as follows:
REF: .LONG CRF$K_REF
PUSHAB REF
PUSHAB REF_FLAGS
PUSHAB REF_ADDR
PUSHAB SYMBOL_ADDR
PUSHAB LNK$NAMTAB
CALLS #5,G^LIB$CRF_INS_REF
The arguments are similar to the previous example, except for CRF$K_REF,
which indicates that this is not the defining reference.

25–8 Using Cross-Reference Routines


Using Cross-Reference Routines
25.6 Example

After it has performed symbol relocation for the module being linked, the linker
calls LIB$CRF_INS_REF to build a table ordered by value.
PUSHAB REF
PUSHAB REF_FLAGS
PUSHAB REF_ADDR
PUSHAB VAL_ADDR
PUSHAB LNK$VALTAB
CALLS #5,G^LIB$CRF_INS_REF

LNK$VALTAB Is the address of the control table for the symbol synopsis by value
VAL_ADDR Is the address of the value (binary longword key)
REF_ADDR Is the address of the symbol name having the value contained in
VAL_ADDR
REF_FLAGS Is the address of a word whose bits are used to select special
characters to print beside the value
CRF$K_REF Is the indicator that this is not a defining reference

25.6.3 Formatting Information for Output


After all input modules are processed, the linker requests the information for
the map. It calls LIB$CRF_OUTPUT once for each type of output. The following
MACRO example illustrates a call to list the symbols and their values. Three
calls are illustrated here.
LNWID: .LONG 132
LNSP1: .LONG LINES_PAGE1
LNSOP: .LONG LINES_OTHR_PAGE
SAVE: .LONG CRF$K_SAVE
VAL: .LONG CRF$K_VALUES
PUSHAB VAL
PUSHAB SAVE
PUSHAB LNSOP
PUSHAB LNSP1
PUSHAB LNWID
PUSHAB LNK$NAMTAB
CALLS #6,G^LIB$CRF_OUTPUT
In this example, CRF$K_VALUES means that no reference indicators are to be
printed, while CRF$K_SAVE means that the cross-reference table is to be saved.
It is also possible to list all cross-reference data. The type of output produced by
this call is shown in Section 25.5, Figure 25–2.
The following call produces such a summary and releases the storage at the same
time:
LNWID: .LONG 132
LNSP1: .LONG LINES_PAGE1
LNSOP: .LONG LINES_OTHR_PAGE
DELETE: .LONG CRF$K_DELETE
DEFREF: .LONG CRF$K_DEF_REF
PUSHAB DELETE
PUSHAB DEFREF
PUSHAB LNSOP
PUSHAB LNSP1
PUSHAB LNWID
PUSHAB LNK$NAMTAB
CALLS #6,G^LIB$CRF_OUTPUT
The type of output produced by this call is shown in Section 25.5, Figure 25–4.
CRF$K_DEFS_REFS indicates that the first two reference fields are used for the
defining references, and CRF$K_DELETE indicates that the table is deleted.

Using Cross-Reference Routines 25–9


Using Cross-Reference Routines
25.6 Example

Another call is made to list the symbol by value synopsis, as follows:


LNWID: .LONG 132
LNSP1: .LONG LINES_PAGE1
LNSOP: .LONG LINES_OTHR_PAGE
VALREF: .LONG CRF$K_VALS_REF
DELETE: .LONG CRF$K_DELETE
PUSHAB DELETE
PUSHAB VALREF
PUSHAB LNSOP
PUSHAB LNSP1
PUSHAB LNWID
PUSHAB LNK$VALTAB
CALLS #6,G^LIB$CRF_OUTPUT
This is similar to the previous call in that it produces a complete cross-reference
output by value, but it does not have the defining reference fields.

25.7 How to Link to the Cross-Reference Shareable Image


The cross-reference routines are located in a shareable image CRFSHR.EXE.
This shareable image is part of the default system shareable image library,
SYS$LIBRARY:IMAGELIB.OLB. For this reason, the cross-reference routines
are automatically included in your image, unless you specify /NOSYSHR in
the LINK command. If you have specified /NOSYSHR and you want to include
CRFSHR.EXE, your LINK command must include the following:
SYS$LIBRARY:IMAGELIB/INCLUDE=CRFSHR

25–10 Using Cross-Reference Routines


26
Shareable Resources

This chapter describes the techniques available for sharing data and program
code among programs. It contains the following sections:
Section 26.1 describes how to share code among programs.
Section 26.2 describes shareable images.
Section 26.3 defines and describes how to use local and global symbols to share
images.
The operating system provides the following techniques for sharing data and
program code among programs:
• DCL symbols and logical names
• Libraries
• Shareable images
• Global sections
• Common blocks installed in a shareable image
• OpenVMS Record Management Services (RMS) shared files
Symbols and logical names are also used for intraprocess and interprocess
communication; therefore, they are discussed in Chapter 32.
Libraries and shareable images are used for sharing program code.
Global sections, common blocks stored in shareable images, and RMS shared
files are used for sharing data. You can also use common blocks for interprocess
communication. For more information, refer to Chapter 3.

26.1 Sharing Program Code


To share code among programs, you can use the following operating system
resources:
• Text, macro, or object libraries that store sections of code. Text and macro
libraries store source code; object libraries store object code. You can create
and manage libraries using the Librarian utility (LIBRARIAN). Refer to the
OpenVMS Command Definition, Librarian, and Message Utilities Manual for
complete information about using the Librarian utility.
• Shareable images, which are images that have been compiled and linked but
cannot be run independently. These images can also be stored in libraries.

Shareable Resources 26–1


Shareable Resources
26.1 Sharing Program Code

26.1.1 Object Libraries


You can use object libraries to store frequently used routines, thereby avoiding
repeated recompiling, which allows you to minimize the number of files you
must maintain, and simplify the linking process. The source code for the object
modules can be in any VAX supported language, and the object modules can be
linked with any other modules written in any VAX supported language.
Use the .OLB file extension for any object library. All modules stored in an object
library must have the file extension .OBJ.
26.1.1.1 System- and User-Defined Default Object Libraries
The operating system provides a default system object library, STARLET.OLB.
You can also define one or more default object libraries to be automatically
searched before the system object library. The logical names for the default object
libraries are LNK$LIBRARY and LNK$LIBRARY_1 through LNK$LIBRARY_
999. To use one of these default libraries, first define the logical name. The
libraries are searched sequentially starting at LNK$LIBRARY. Do not skip any
numbers. If you store object modules in the default libraries, you do not have to
specify them at link time. However, you do have to maintain and manage them
as you would any library.
The following example defines the library in the file PROCEDURES.OLB (the file
type defaults to .OLB, meaning object library) in $DISK1:[DEV] as a default user
library:
$ DEFINE LNK$LIBRARY $DISK1:[DEV]PROCEDURES
26.1.1.2 How the Linker Searches Libraries
When the linker is resolving global symbol references, it searches user default
libraries at the process level first, then libraries at the group and system level.
Within levels, the library defined as LNK$LIBRARY is searched first, then
LNK$LIBRARY_1, LNK$LIBRARY_2, and so on.
26.1.1.3 Creating an Object Library
To create an object library, invoke the Librarian utility by entering the LIBRARY
command with the /CREATE qualifier and the name you are assigning the library.
The following example creates a library in a file named INCOME.OLB (.OLB is
the default file type):
$ LIBRARY/CREATE INCOME
26.1.1.4 Managing an Object Library
To add or replace modules in a library, enter the LIBRARY command with the
/REPLACE qualifier followed by the name of the library (first parameter) and
the names of the files containing the (second parameter). After you put object
modules in a library, you can delete the object file. The following example adds
or replaces the modules from the object file named GETSTATS.OBJ to the object
library named INCOME.OLB and then deletes the object file:
$ LIBRARY/REPLACE INCOME GETSTATS
$ DELETE GETSTATS.OBJ;*
You can examine the contents of an object library with the /LIST qualifier. Use
the /ONLY qualifier to limit the display. The following command displays all the
modules in INCOME.OLB that start with GET:
$ LIBRARY/LIST/ONLY=GET* INCOME

26–2 Shareable Resources


Shareable Resources
26.1 Sharing Program Code

Use the /DELETE qualifier to delete a library module and the /EXTRACT
qualifier to recreate an object file. If you delete many modules, you should
also compress (/COMPRESS qualifier) and purge (PURGE command) the library.
Note that the /ONLY, /DELETE, and /EXTRACT qualifiers require the names of
modules—not file names—and that the names are specified as qualifier values,
not parameter values.

26.1.2 Text and Macro Libraries


Any frequently used routine can be stored in libraries as source code. Then, when
you need the routine, it can be called in from your source program.
Source code modules are stored in text libraries. The file extension for a text
library is .TLB.
When using VAX MACRO assembly language, any source code module can be
stored in a macro library. The file extension for a macro library is .MLB. Any
source code module stored in a macro library must have the file extension .MAR.
You also use LIBRARIAN to create and manage text and macro libraries. Refer
to Section 26.1.1.3 and Section 26.1.1.4 for a summary of LIBRARIAN commands.

26.2 Shareable Images


A shareable image is a nonexecutable image that can be linked with executable
images. If you have a program unit that is invoked by more than one program,
linking it as a shareable image provides the following benefits:
• Saves disk space—The executable images to which the shareable image is
linked do not physically include the shareable image. Only one copy of the
shareable image exists.
• Simplifies maintenance—If you use transfer vectors and the GSMATCH
(on VAX systems) or symbol vectors (on Alpha systems) option, you can
modify, recompile, and relink a shareable image without having to relink any
executable image that is linked with it.
Shareable images can also save memory, provided that they are installed as
shared images. See the OpenVMS Linker Utility Manual for more information
about creating shareable images and shareable image libraries.

26.3 Symbols
Symbols are names that represent locations (addresses) in virtual memory. More
precisely, a symbol’s value is the address of the first, or low-order, byte of a
defined area of virtual memory, while the characteristics of the defined area
provide the number of bytes referred to. For example, if you define TOTAL_
HOUSES as an integer, the symbol TOTAL_HOUSES is assigned the address of
the low-order byte of a 4-byte area in virtual memory. Some system components
(for example, the debugger) permit you to refer to areas of virtual memory by
their actual addresses, but symbolic references are always recommended.

26.3.1 Defining Symbols


A symbolic name can consist of up to 31 letters, digits, underscores ( _ ), and
dollar signs ( $ ). Uppercase and lowercase letters are equivalent. By convention,
dollar signs are restricted to symbols used in system components. (If you do not
use the dollar sign in your symbolic names, you will never accidentally duplicate
a system-defined symbol.)

Shareable Resources 26–3


Shareable Resources
26.3 Symbols

26.3.2 Local and Global Symbols


Symbols are either local or global in scope. A local symbol can only be
referenced within the program unit in which it is defined. Local symbol names
must be unique among all other local symbols within the program unit but not
within other program units in the program. References to local symbols are
resolved at compile time.
A global symbol can be referenced outside the program unit in which it is
defined. Global symbol names must be unique among all other global symbols
within the program. References to global symbols are not resolved until link time.
References to global symbols in the executable portion of a program unit are
usually invocations of subprograms. If you reference a global symbol in any other
capacity (as an argument or data value—see the following paragraph), you must
define the symbol as external or intrinsic in the definition portion of the program
unit.
System facilities, such as the Message utility and the VAX MACRO assembler,
use global symbols to define data values.
The following program segment shows how to define and reference a global
symbol, RMS$_EOF (a condition code that may be returned by LIB$GET_
INPUT):
CHARACTER*255 NEW_TEXT
INTEGER STATUS
INTEGER*2 NT_SIZ
INTEGER LIB$GET_INPUT
EXTERNAL RMS$_EOF
STATUS = LIB$GET_INPUT (NEW_TEXT,
2 ’New text: ’,
2 NT_SIZ)
IF ((.NOT. STATUS) .AND.
2 (STATUS .NE. %LOC (RMS$_EOF))) THEN
CALL LIB$SIGNAL (RETURN_STATUS BY VALUE)
END IF

26.3.3 Resolving Global Symbols


References to global symbols are resolved by including the module that defines
the symbol in the link operation. When the linker encounters a global symbol, it
uses the following search method to find the defining module:
1. Explicitly named modules and libraries—Generally used to resolve user-
defined global symbols, such as subprogram names and condition codes.
These modules and libraries are searched in the order in which they are
specified.
2. System default libraries—Generally used to resolve system-defined global
symbols, such as procedure names and condition codes.
3. User default libraries—Generally used to avoid explicitly naming libraries,
thereby simplifying linking.
If the linker cannot find the symbol, the symbol is said to be unresolved and
a warning results. You can run an image containing unresolved symbols. The
image runs successfully as long as it does not access any unresolved symbol. For
example, if your code calls a subroutine but the subroutine call is not executed,
the image runs successfully.

26–4 Shareable Resources


Shareable Resources
26.3 Symbols

If an image accesses an unresolved global symbol, results are unpredictable.


Usually the image fails with an access violation (attempting to access a physical
memory location outside those assigned to the program’s virtual memory
addresses).
26.3.3.1 Explicitly Named Modules and Libraries
You can resolve a global symbol reference by naming the defining object module
in the link command. For example, if the program unit INCOME references the
subprogram GET_STATS, you can resolve the global symbol reference when you
link INCOME by including the file containing the object module for GET_STATS,
as follows:
$ LINK INCOME, GETSTATS
If the modules that define the symbols are in an object library, name the library
in the link operation. In the following example, the GET_STATS module resides
in the object module library INCOME.OLB:
$ LINK INCOME,INCOME/LIBRARY
26.3.3.2 System Default Libraries
Link operations automatically check the system object and shareable image
libraries for any references to global symbols not resolved by your explicitly
named object modules and libraries. The system object and shareable image
libraries include the entry points for the RTL routines and system services,
condition codes, and other system-defined values. Invocations of these modules do
not require any explicit action by you at link time.
26.3.3.3 User Default Libraries
If you write general-purpose procedures or define general-purpose symbols, you
can place them in a user default library. (You can also make your development
library a user default library.) In this way, you can link to the modules containing
these procedures and symbols without explicitly naming the library in the DCL
LINK command. To name a single-user library, equate the file name of the
library to the logical name LNK$LIBRARY. For subsequent default libraries, use
the logical names LNK$LIBRARY_1 through LNK$LIBRARY_999, as described
in Section 26.1.1.
26.3.3.4 Making a Library Available for Systemwide Use
To make a library available to everyone using the system, define it at the system
level. To restrict use of a library or to override a system library, define the library
at the process or group level. The following command line defines the default
user library at the system level:
$ DEFINE/SYSTEM LNK$LIBRARY $DISK1:[DEV]PROCEDURES
26.3.3.5 Macro Libraries
Some system symbols are not defined in the system object and shareable image
libraries. In such cases, the OpenVMS System Services Reference Manual notes
that the symbols are defined in the system macro library and tells you the name
of the macro containing the symbols. To access these symbols, you must first
assemble a macro routine with the following source code. The keyword GLOBAL
must be in uppercase. The .TITLE directive is optional but recommended.

Shareable Resources 26–5


Shareable Resources
26.3 Symbols

.TITLE macro-name
macro-name GLOBAL
.
.
.
.END
The following example is a macro program that includes two system macros:
LBRDEF.MAR
.TITLE $LBRDEF
$LBRDEF GLOBAL
$LHIDEF GLOBAL
.END
Assemble the routine containing the macros with the MACRO command. You can
place the resultant object modules in a default library or in a library that you
specify in the LINK command, or you can specify the object modules in the LINK
command. The following example places the $LBRDEF and $LHIDEF modules in
a library before performing a link operation:
$ MACRO LBRDEF
$ LIBRARY/REPLACE INCOME LBRDEF
$ DELETE LBRDEF.OBJ;*
$ LINK INCOME,INCOME/LIBRARY
The following LINK command uses the object file directly:
$ LINK INCOME,LBRDEF,INCOME/LIBRARY

26.3.4 Sharing Data


Typically, you use an installed common block either to facilitate interprocess
communication or to allow two or more processes to access the same data
simultaneously. However, you must have the CMKRNL privilege to install the
common block. If you do not have the CMKRNL privilege, global sections allow
you to perform the same operations.
26.3.4.1 Installed Common Blocks
To share data among processes by using a common block, you must install the
common block as a shared shareable image and link each program that references
the common block against that shareable image.
To install a common block as a shared image:
1. Define a common block—Write a program that declares the variables in
the common block and defines the common block. This program should not
contain executable code. The following Compaq Fortran program defines a
common block:
INC_COMMON.FOR
INTEGER TOTAL_HOUSES
REAL PERSONS_HOUSE (2048),
2 ADULTS_HOUSE (2048),
2 INCOME_HOUSE (2048)
COMMON /INCOME_DATA/ TOTAL_HOUSES,
2 PERSONS_HOUSE,
2 ADULTS_HOUSE,
2 INCOME_HOUSE
END

26–6 Shareable Resources


Shareable Resources
26.3 Symbols

2. Create the shareable image—Compile the program containing the common


block. Use the LINK/SHAREABLE command to create a shareable image
containing the common block.
$ FORTRAN INC_COMMON
$ LINK/SHAREABLE INC_COMMON
For Alpha only, you need to specify a Linker options file (shown here as
SYS$INPUT to allow typed input) to specify the PSECT attributes of the
COMMON block PSECT and include it in the global symbol table:
$ LINK/SHAREABLE INC_COMMON ,SYS$INPUT/OPTION
_ SYMBOL_VECTOR=(WORK_AREA=PSECT)
_ PSECT_ATTR=WORK_AREA,SHR
With Compaq Fortran 90 on OpenVMS Alpha systems, the default PSECT
attribute for a common block is NOSHR. To use a shared installed common
block, you must specify one of the following:
• The SHR attribute in a cDEC$ PSECT directive in the source file
• The SHR attribute in the Linker options file for the shareable image to
be installed and for each executable image that references the installed
common block
If the !DEC$ PSECT (same as cDEC$ PSECT) directive specified the SHR
attribute, the LINK command is as follows:
$ LINK/SHAREABLE INC_COMMON ,SYS$INPUT/OPTION
_ SYMBOL_VECTOR=(WORK_AREA=PSECT)
For Alpha only, copy the shareable image. Once created, you should copy the
shareable image into SYS$SHARE before it is installed. The file protection
of the .EXE file must allow write access for the processes running programs
that will access the shareable image (shown for Group access in the following
COPY command):
$ COPY/LOG DISK$:[INCOME.DEV]INC_COMMON.EXE SYS$SHARE:*.*
_ /PROTECTION=G:RWE
On Alpha systems, if you do not copy the installed shareable image to
SYS$SHARE, before running executable images that reference the installed
shareable common image, you must define a logical name that specifies the
location of that image.
On Alpha systems, when compiling the program that contains the
common block declarations, consistently use the same /ALIGNMENT
and /GRANULARITY qualifiers used to compile the common block data
declaration program that has been installed as a shareable image. For more
information, see Section 26.3.4.3.
3. Install the shareable image—Use the DCL command SET PROCESS
/PRIVILEGE to give yourself CMKRNL privilege (required for use of the
Install utility). Use the DCL command INSTALL to invoke the interactive
Install utility. When the INSTALL prompt appears, enter CREATE, followed
by the complete file specification of the shareable image that contains the
common block (the file type defaults to .EXE) and the qualifiers /WRITEABLE
and /SHARED. The Install utility installs your shareable image and
reissues the INSTALL prompt. Enter EXIT to exit. Remember to remove
CMKRNL privilege. (For complete documentation of the Install utility, see
the OpenVMS System Management Utilities Reference Manual.)

Shareable Resources 26–7


Shareable Resources
26.3 Symbols

The following example shows how to install a shareable image:


$ SET PROCESS/PRIVILEGE=CMKRNL
$ INSTALL
INSTALL> CREATE DISK$USER:[INCOME.DEV]INC_COMMON -
_INSTALL> /WRITEABLE/SHARED
INSTALL> EXIT
$ SET PROCESS/PRIVILEGE=NOCMKRNL

Note
A disk containing an installed image cannot be dismounted. To remove an
installed image, invoke the Install utility and enter DELETE followed by
the complete file specification of the image. The DELETE subcommand
does not delete the file from the disk; it removes the file from the list of
known installed images.

Perform the following steps to write or read the data in an installed common
block from within any program:
1. Include the same variable and common block definitions in the program.
2. Compile the program.
For Alpha only, when compiling the program that contains the common block
declarations, consistently use the same /ALIGNMENT and /GRANULARITY
qualifiers used to compile the common block data declaration program
that has been installed as a shareable image. For more information, see
Section 26.3.4.3.
3. Link the program against the shareable image that contains the common
block. (Linking against a shareable image requires an options file.)
$ LINK INCOME, DATA/OPTION
$ LINK REPORT, DATA/OPTION
DATA.OPT
INC_COMMON/SHAREABLE
For Alpha only, linking is as follows:
INC_COMMON/SHAREABLE
PSECT_ATTR=WORK_AREA, SHR
If a !DEC$ PSECT (cDEC$ PSECT) directive specified the SHR PSECT
attribute, the linker options file INCOME.OPT would contain the following
line:
INC_COMMON/SHAREABLE
The source line containing the !DEC$ PSECT directive would be as follows:
!DEC$ PSECT /INC_COMMON/ SHR

4. Execute the program.


For Alpha only, if the installed image is not located in SYS$SHARE, you must
define a logical name that specifies the location of that image. The logical
name (in this example INC_COMMON) is the name of the installed base.

26–8 Shareable Resources


Shareable Resources
26.3 Symbols

In the previous series of examples, the two programs INCOME and REPORT
access the same area of memory through the installed common block INCOME_
DATA (defined in INC_COMMON.FOR).
Typically, programs that access shared data use common event flag clusters
to synchronize read and write access to the data. Refer to Chapter 7 for more
information about using event flags for program synchronization.
26.3.4.2 Using Global Sections
To share data by using global sections, each process that plans to access the data
includes a common block of the same name, which contains the variables for
the data. The first process to reference the data declares the common block as a
global section and, optionally, maps data to the section. (Data in global sections,
as in private sections, must be page aligned.)
To create a global section, invoke SYS$CRMPSC and add the following:
• Additional argument—Specify the name of the global section (argument 5). A
program uses this name to access a global section.
• Additional flag—Set the SEC$V_GBL bit of the flags argument to indicate
that the section is a global section.
As other programs need to reference the data, each can use either SYS$CRMPSC
or SYS$MGBLSC to map data into the global section. If you know that the global
section exists, the best practice is to use the SYS$MGBLSC system service.
The format for SYS$MGBLSC is as follows:
SYS$MGBLSC (inadr ,[retadr] ,[acmode] ,[flags] ,gsdnam ,[ident] ,[relpag])
Refer to the OpenVMS System Services Reference Manual for complete
information about this system service.
In Example 26–1, one image, DEVICE.FOR, passes device names to another
image, GETDEVINF.FOR. GETDEVINF.FOR returns the process name and
the terminal associated with the process that allocated each device. The two
processes use the global section GLOBAL_SEC to communicate. GLOBAL_SEC is
mapped to the common block named DATA, which is page aligned by the options
file DATA.OPT. Event flags are used to synchronize the exchange of information.
UFO_CREATE.FOR, DATA.OPT, and DEVICE.FOR are included here for easy
reference. Refer to Section 28.4 for additional information about global sections.

Example 26–1 Interprocess Communication Using Global Sections


!UFO_CREATE.FOR
.
.
.
INTEGER FUNCTION UFO_CREATE (FAB,
2 RAB,
2 LUN)
! Include RMS definitions
INCLUDE ’($FABDEF)’
INCLUDE ’($RABDEF)’

(continued on next page)

Shareable Resources 26–9


Shareable Resources
26.3 Symbols

Example 26–1 (Cont.) Interprocess Communication Using Global Sections


! Declare dummy arguments
RECORD /FABDEF/ FAB
RECORD /RABDEF/ RAB
INTEGER LUN
! Declare channel
INTEGER*4 CHAN
COMMON /CHANNEL/ CHAN
! Declare status variable
INTEGER STATUS
! Declare system procedures
INTEGER SYS$CREATE
! Set useropen bit in the FAB options longword
FAB.FAB$L_FOP = FAB.FAB$L_FOP .OR. FAB$M_UFO
! Open file
STATUS = SYS$CREATE (FAB)
! Read channel from FAB status word
CHAN = FAB.FAB$L_STV
! Return status of open operation
UFO_CREATE = STATUS
END
DATA.OPT
PSECT_ATTR = DATA, PAGE
DEVICE.FOR
! Define global section flags
INCLUDE ’($SECDEF)’
! Mask for section flags
INTEGER SEC_MASK
! Logical unit number for section file
INTEGER INFO_LUN
! Channel number for section file
INTEGER SEC_CHAN
COMMON /CHANNEL/ SEC_CHAN
! Length for the section file
INTEGER SEC_LEN
! Data for the section file
CHARACTER*12 DEVICE,
2 PROCESS
CHARACTER*6 TERMINAL
COMMON /DATA/ DEVICE,
2 PROCESS,
2 TERMINAL
! Location of data
INTEGER PASS_ADDR (2),
2 RET_ADDR (2)
! Two common event flags
INTEGER REQUEST_FLAG,
2 INFO_FLAG
DATA REQUEST_FLAG /70/
DATA INFO_FLAG /71/

(continued on next page)

26–10 Shareable Resources


Shareable Resources
26.3 Symbols

Example 26–1 (Cont.) Interprocess Communication Using Global Sections


! User-open routines
INTEGER UFO_CREATE
EXTERNAL UFO_CREATE
.
.
.
! Open the section file
STATUS = LIB$GET_LUN (INFO_LUN)
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
SEC_MASK = SEC$M_WRT .OR. SEC$M_DZRO .OR. SEC$M_GBL
! (last address -- first address + length of last element + 511)/512
SEC_LEN = ( (%LOC(TERMINAL) - %LOC(DEVICE) + 6 + 511)/512 )
OPEN (UNIT=INFO_LUN,
2 FILE=’INFO.TMP’,
2 STATUS=’NEW’,
2 INITIALSIZE = SEC_LEN,
2 USEROPEN = UFO_CREATE)
! Free logical unit number and map section
CLOSE (INFO_LUN)
! Get location of data
PASS_ADDR (1) = %LOC (DEVICE)
PASS_ADDR (2) = %LOC (TERMINAL)
STATUS = SYS$CRMPSC (PASS_ADDR, ! Address of section
2 RET_ADDR, ! Addresses mapped
2 ,
2 %VAL(SEC_MASK), ! Section mask
2 ’GLOBAL_SEC’, ! Section name
2 ,,
2 %VAL(SEC_CHAN), ! I/O channel
2 ,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
! Create the subprocess
STATUS = SYS$CREPRC (,
2 ’GETDEVINF’, ! Image
2 ,,,,,
2 ’GET_DEVICE’, ! Process name
2 %VAL(4),,,) ! Priority
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
! Write data to section
DEVICE = ’$FLOPPY1’
! Get common event flag cluster and set flag
STATUS = SYS$ASCEFC (%VAL(REQUEST_FLAG),
2 ’CLUSTER’,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
STATUS = SYS$SETEF (%VAL(REQUEST_FLAG))
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
! When GETDEVINF has the information, INFO_FLAG is set
STATUS = SYS$WAITFR (%VAL(INFO_FLAG))
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
.
.
.

(continued on next page)

Shareable Resources 26–11


Shareable Resources
26.3 Symbols

Example 26–1 (Cont.) Interprocess Communication Using Global Sections


GETDEVINF.FOR
! Define section flags
INCLUDE ’($SECDEF)’
! Mask for section flags
INTEGER SEC_MASK
! Data for the section file
CHARACTER*12 DEVICE,
2 PROCESS
CHARACTER*6 TERMINAL
COMMON /DATA/ DEVICE,
2 PROCESS,
2 TERMINAL
! Location of data
INTEGER PASS_ADDR (2),
2 RET_ADDR (2)
! Two common event flags
INTEGER REQUEST_FLAG,
2 INFO_FLAG
DATA REQUEST_FLAG /70/
DATA INFO_FLAG /71/
.
.
.
! Get common event flag cluster and wait
! for GBL1.FOR to set REQUEST_FLAG
STATUS = SYS$ASCEFC (%VAL(REQUEST_FLAG),
2 ’CLUSTER’,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
STATUS = SYS$WAITFR (%VAL(REQUEST_FLAG))
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Get location of data
PASS_ADDR (1) = %LOC (DEVICE)
PASS_ADDR (2) = %LOC (TERMINAL)
! Set write flag
SEC_MASK = SEC$M_WRT
! Map the section
STATUS = SYS$MGBLSC (PASS_ADDR, ! Address of section
2 RET_ADDR, ! Address mapped
2 ,
2 %VAL(SEC_MASK), ! Section mask
2 ’GLOBAL_SEC’,,) ! Section name
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Call GETDVI to get the process ID of the
! process that allocated the device, then
! call GETJPI to get the process name and terminal
! name associated with that process ID.
! Set PROCESS equal to the process name and
! set TERMINAL equal to the terminal name.
.
.
.
! After information is in GLOBAL_SEC
STATUS = SYS$SETEF (%VAL(INFO_FLAG))
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
END

26–12 Shareable Resources


Shareable Resources
26.3 Symbols

By default, a global section is deleted when no image is mapped to it. Such global
sections are called temporary global sections. If you have the PRMGBL privilege,
you can create a permanent global section (set the SEC$V_PERM bit of the flags
argument when you invoke SYS$CRMPSC). A permanent global section is not
deleted until after it is marked for deletion with the SYS$DGBLSC system service
(requires PRMGBL). Once a permanent section is marked for deletion, it is like a
temporary section; when no image is mapped to it, the section is deleted.
26.3.4.3 Synchronizing Access to Global Sections
On Alpha systems, if more than one process or thread will write to a shared
global section containing COMMON block data, the user program may need to
synchronize access to COMMON block variables.
On Alpha systems, compile all programs referencing the shared common area
with the same value for the /ALIGNMENT and /GRANULARITY qualifiers, as
shown in the following:
$ F90 /ALIGN=COMMONS=NATURAL /GRANULARITY=LONGWORD INC_COMMON
On Alpha systems, using /GRANULARITY=LONGWORD for 4-byte variables
or /GRANULARITY=QUADWORD for 8-byte variables ensures that adjacent
data is not accidentally effected. To ensure access to 1-byte variables, specify
/GRANULARITY=BYTE. Because accessing data items less than four bytes slows
run-time performance, you might want to considering synchronizing read and
write access to the data on the same node.
One way for programs accessing shared data is to use common event flag clusters
to synchronize read and write access to the data on the same node. In the
simplest case, one event flag in a common event flag cluster might indicate that
a program is writing data, and a second event flag in the cluster might indicate
that a program is reading data. Before accessing the shared data, a program
must examine the common event flag cluster to ensure that accessing the data
does not conflict with an operation already in progress.
Other ways of synchronizing access on a single node include using the following
OpenVMS system services:
• The lock manager system services (SYS$ENQ and SYS$DEQ)
• The hibernate and wake system services (SYS$HIBER and SYS$WAKE)
You could also use Assembler code for synchronization.
26.3.4.4 RMS Shared Files
RMS allows concurrent access to a file. Shared files can be one of the following
formats:
• Indexed files
• Relative files
• Sequential files with 512-byte fixed-length records
To coordinate access to a file, RMS uses the lock manager. You can override the
RMS lock manager by controlling access yourself. Refer to Chapter 7 for more
information about synchronizing access to resources.

Shareable Resources 26–13


27
System Time Operations

This chapter describes the types of system time operations performed by the
operating system and contains the following sections:
Section 27.1 describes the system time format.
Section 27.2 describes time conversion and date/time manipulation.
Section 27.3 describes how to get the current date and time and set the current
time.
Section 27.4 describes how to set and cancel timer requests and how to schedule
and cancel wakeups.
Section 27.5 describes using run-time library (RTL) routines to collect timer
statistics.
Section 27.6 describes using date/time formatting routines.
Section 27.7 describes the Coordinated Universal Time (UTC) system.

27.1 System Time Format


The operating system maintains the current date and time in 64-bit format.
The time value is a binary number in 100-nanosecond (ns) units offset from
the system base date and time, which is 00:00 o’clock, November 17, 1858 (the
Smithsonian base date and time for the astronomic calendar). Time values must
be passed to or returned from system services as the address of a quadword
containing the time in 64-bit format. A time value can be expressed as either of
the following:
• An absolute time that is a specific date or time of day, or both. Absolute times
are always positive values (or 0).
• A delta time that is an offset from the current time to a time or date in the
future. Delta times are always expressed as negative values.
If you specify 0 as the address of a time value, the operating system supplies the
current date and time.

27.1.1 Absolute Time Format


The operating system uses the following format for absolute time. The full date
and time require a character string of 23 characters. The punctuation is required.
dd-MMM-yyyy hh:mm:ss.cc

dd Day of the month (2 characters)


MMM Month (first 3 characters of the month in uppercase)
yyyy Year (4 characters)

System Time Operations 27–1


System Time Operations
27.1 System Time Format

hh Hours of the day in 24-hour format (2 characters)


mm Minutes (2 characters)
ss.cc Seconds and hundredths of a second (5 characters)

27.1.2 Delta Time Format


The operating system uses the following format for delta time. The full date and
time require a character string of 16 characters. The punctuation is required.
dddd hh:mm:ss.cc

dddd Day of the month (4 characters)


hh Hour of the day (2 characters)
mm Minutes (2 characters)
ss.cc Seconds and hundredths of a second (5 characters)
A delta time is maintained as an integer value representing an amount of time in
100-ns units.

27.2 Time Conversion and Date/Time Manipulation


This section presents information about time conversion and date/time
manipulation features, and the routines available to implement them.

27.2.1 Time Conversion Routines


Since the timer system services require you to specify the time in a 64-bit format,
you can use time conversion run-time library and system service routines to work
with time in a different format. Run-time library and system services do the
following:
• Obtain the current date and time in an ASCII string or in system format
• Convert an ASCII string into the system time format
• Convert a system time value into an ASCII string
• Convert the time from system format to integer values
Table 27–1 shows time conversion run-time and system service routines.

27–2 System Time Operations


System Time Operations
27.2 Time Conversion and Date/Time Manipulation

Table 27–1 Time Conversion Routines and System Services


Routine Function
Time Conversion Run-Time Library (LIB$) Routines
LIB$CONVERT_DATE_STRING Converts an input date/time string to an
operating system internal time.
LIB$CVT_FROM_INTERNAL_TIME Converts an operating system standard
internal binary time value to an external
integer value. The value is converted
according to a selected unit of time
operation.
LIB$CVTF_FROM_INTERNAL_TIME Converts an operating system standard
internal binary time to an external
F-floating point value. The value is
converted according to a selected unit of
time operation.
LIB$CVT_TO_INTERNAL_TIME Converts an external integer time value
to an operating system standard internal
binary time value. The value is converted
according to a selected unit of time
operation.
LIB$CVTF_TO_INTERNAL_TIME Converts an F-floating-point time value
to an internal binary time value.
LIB$CVT_VECTIM Converts a seven-word array (as returned
by the SYS$NUMTIM system service)
to an operating system standard format
internal time.
LIB$FORMAT_DATE_TIME Allows you to select at run time a specific
output language and format for a date or
time, or both.
LIB$SYS_ASCTIM Provides a simplified interface between
higher-level languages and the $ASCTIM
system service.
(continued on next page)

System Time Operations 27–3


System Time Operations
27.2 Time Conversion and Date/Time Manipulation

Table 27–1 (Cont.) Time Conversion Routines and System Services


Routine Function
Time Conversion System Service Routines
SYS$ASCTIM Converts an absolute or delta time from
64-bit binary time format to an ASCII
string.
SYS$ASCUTC Converts an absolute time from 128-
bit Coordinated Universal Time (UTC)
format to an ASCII string.
SYS$BINTIM Converts an ASCII string to an absolute
or delta time value in a binary time
format.
SYS$BINUTC Converts an ASCII string to an absolute
time value in the 128-bit UTC format.
SYS$FAO Converts a binary value into an ASCII
character string in decimal, hexadecimal,
or octal notation and returns the
character string in an output string.
SYS$GETUTC Returns the current time in 128-bit UTC
format.
SYS$NUMTIM Converts an absolute or delta time from
64-bit system time format to binary
integer date and time values.
SYS$NUMUTC Converts an absolute 128-bit binary
time into its numeric components. The
numeric components are returned in local
time.
SYS$TIMCON Converts 128-bit UTC to 64-bit system
format or 64-bit system format to 128-bit
UTC based on the value of the convert
flag.

You can use the SYS$GETTIM system service to get the current time in internal
format, or you can use SYS$BINTIM to convert a formatted time to an internal
time, as shown in Section 27.3.2. You can also use the LIB$DATE_TIME routine
to obtain the time, LIB$CVT_FROM_INTERNAL_TIME to convert an internal
time to an external time, and LIB$CVT_TO_INTERNAL to convert from an
external time to an internal time.
27.2.1.1 Calculating and Displaying Time with SYS$GETTIM and LIB$SUBX
Example 27–1 calculates differences between the current time and a time input
in absolute format, and then displays the result as delta time. If the input time
is later than the current time, the difference is a negative value (delta time) and
can be displayed directly. If the input time is an earlier time, the difference is a
positive value (absolute time) and must be converted to delta time before being
displayed. To change an absolute time to a delta time, negate the time array
by subtracting it from 0 (specified as an integer array) using the LIB$SUBX
routine, which performs subtraction on signed two’s complement integers of
arbitrary length. For the absolute or delta time format, see Section 27.1.1 and
Section 27.1.2.

27–4 System Time Operations


System Time Operations
27.2 Time Conversion and Date/Time Manipulation

Example 27–1 Calculating and Displaying the Time


.
.
.
! Internal times
! Input time in absolute format, dd-mmm-yyyy hh:mm:ss.ss
!
INTEGER*4 CURRENT_TIME (2),
2 PAST_TIME (2),
2 TIME_DIFFERENCE (2),
2 ZERO (2)
DATA ZERO /0,0/
! Formatted times
CHARACTER*23 PAST_TIME_F
CHARACTER*16 TIME_DIFFERENCE_F
! Status
INTEGER*4 STATUS
! Integer functions
INTEGER*4 SYS$GETTIM,
2 LIB$GET_INPUT,
2 SYS$BINTIM,
2 LIB$SUBX,
2 SYS$ASCTIM
! Get current time
STATUS = SYS$GETTIM (CURRENT_TIME)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Get past time and convert to internal format
STATUS = LIB$GET_INPUT (PAST_TIME_F,
2 ’Past time (in absolute format): ’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
STATUS = SYS$BINTIM (PAST_TIME_F,
2 PAST_TIME)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Subtract past time from current time
STATUS = LIB$SUBX (CURRENT_TIME,
2 PAST_TIME,
2 TIME_DIFFERENCE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! If resultant time is in absolute format (positive value means
! most significant bit is not set), convert it to delta time
IF (.NOT. (BTEST (TIME_DIFFERENCE(2),31))) THEN
STATUS = LIB$SUBX (ZERO,
2 TIME_DIFFERENCE,
2 TIME_DIFFERENCE)
END IF
! Format time difference and display
STATUS = SYS$ASCTIM (, TIME_DIFFERENCE_F,
2 TIME_DIFFERENCE,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
TYPE *, ’Time difference = ’, TIME_DIFFERENCE_F
END

If you are ignoring the time portion of date/time (that is, working just at the date
level), the LIB$DAY routine might simplify your calculations. LIB$DAY returns
to you the number of days from the base system date to a given date.

System Time Operations 27–5


System Time Operations
27.2 Time Conversion and Date/Time Manipulation

27.2.1.2 Obtaining Absolute Time with SYS$ASCTIM and SYS$BINTIM


The Convert Binary Time to ASCII String (SYS$ASCTIM) system service is the
converse of the Convert ASCII String to Binary Time (SYS$BINTIM) system
service. You provide the service with the time in the ASCII format shown in
Section 27.3.2. The service then converts the string to a time value in 64-bit
format. You can use this returned value as input to a timer scheduling service.
When you specify the ASCII string buffer, you can omit any of the fields, and
the service uses the current date or time value for the field. Thus, if you want a
timer request to be date independent, you could format the input buffer for the
SYS$BINTIM service as shown in the following example. The two hyphens that
are normally embedded in the date field must be included, and at least one blank
must precede the time field.
#include <stdio.h>
#include <descrip.h>
/* Buffer to receive binary time */
struct {
unsigned int buff1, buff2;
}binary_noon;
main() {
unsigned int status;
$DESCRIPTOR(ascii_noon,"-- 12:00:00.00"); /* noon (absolute time) */
/* Convert time */
status = SYS$BINTIM(&ascii_noon, /* timbuf - ASCII time */
&binary_noon); /* timadr - binary time */
}
When the SYS$BINTIM service completes, a 64-bit time value representing ‘‘noon
today’’ is returned in the quadword at BINARY_NOON.
27.2.1.3 Obtaining Delta Time with SYS$BINTIM
The SYS$BINTIM system service also converts ASCII strings to delta time values
to be used as input to timer services. The buffer for delta time ASCII strings has
the following format:
dddd hh:mm:ss.cc
The first field, indicating the number of days, must be specified as 0 if you are
specifying a delta time for the current day.
The following example shows how to use the SYS$BINTIM service to obtain a
delta time in system format:
#include <stdio.h>
#include <descrip.h>
/* Buffer to receive binary time */
struct {
unsigned int buff1, buff2;
}btenmin;
main() {
unsigned int status;
$DESCRIPTOR(atenmin,"0 00:10:00.00"); /* 10-min delta */
/* Convert time from ASCII to binary */
status = SYS$BINTIM(&atenmin, /* timbuf - time in ASCII */
&btenmin); /* timadr - binary time */
}

27–6 System Time Operations


System Time Operations
27.2 Time Conversion and Date/Time Manipulation

If you are programming in VAX MACRO, you can also specify approximate
delta time values when you assemble a program, using two MACRO .LONG
directives to represent a time value in 100-ns units. The arithmetic is based on
the following formula:
1 second = 10 million * 100 ns
For example, the following statement defines a delta time value of 5 seconds:
FIVESEC: .LONG -10*1000*1000*5,-1 ; Five seconds
The value 10 million is expressed as 10*1000*1000 for readability. Note that the
delta time value is negative.
If you use this notation, however, you are limited to the maximum number of
100-ns units that can be expressed in a longword. In time values this is slightly
more than 7 minutes.
27.2.1.4 Obtaining Numeric and ASCII Time with SYS$NUMTIM
The Convert Binary Time to Numeric Time (SYS$NUMTIM) system service
converts a time in the system format into binary integer values. The service
returns each of the components of the time (year, month, day, hour, and so on)
into a separate word of a 7-word buffer. The SYS$NUMTIM system service and
the format of the information returned are described in the OpenVMS System
Services Reference Manual.
You use the SYS$ASCTIM system service to format the time in ASCII for
inclusion in an output string. The SYS$ASCTIM service accepts as an argument
the address of a quadword that contains the time in system format and returns
the date and time in ASCII format.
If you want to include the date and time in a character string that contains
additional data, you can format the output string with the Formatted ASCII
Output (SYS$FAO) system service. The SYS$FAO system service converts binary
values to ASCII representations, and substitutes the results in character strings
according to directives supplied in an input control string. Among these directives
are !%T and !%D, which convert a quadword time value to an ASCII string and
substitute the result in an output string. For examples of how to do this, see the
discussion of $FAO in the OpenVMS System Services Reference Manual.

27.2.2 Date/Time Manipulation Routines


The run-time LIB$ facility provides several date/time manipulation routines.
These routines let you add, subtract, and multiply dates and times. Use the
LIB$ADDX and LIB$SUBX routines to add and subtract times, since the times
are defined in integer arrays. Use LIB$ADD_TIMES and LIB$SUB_TIMES
to add and subtract two quadword times. When manipulating delta times,
remember that they are stored as negative numbers. For example, to add a delta
time to an absolute time, you must subtract the delta time from the absolute time.
Use LIB$MULT_DELTA_TIME and LIB$MULTF_DELTA_TIME to multiply delta
times by scalar and floating scalar.
Table 27–2 lists all the LIB$ routines that perform date/time manipulation.

System Time Operations 27–7


System Time Operations
27.2 Time Conversion and Date/Time Manipulation

Table 27–2 Date/Time Manipulation Routines


Routine Function
LIB$ADD_TIMES Adds two quadword times
LIB$FORMAT_DATE_TIME Formats a date and/or time for output
LIB$FREE_DATE_TIME_CONTEXT Frees the date/time context
LIB$GET_MAXIMUM_DATE_LENGTH Returns the maximum possible length of
an output date/time string
LIB$GET_USERS_LANGUAGE Returns the user’s selected language
LIB$INIT_DATE_TIME_CONTEXT Initializes the date/time context with a
user-specified format
LIB$MULT_DELTA_TIME Multiplies a delta time value by an
integer scalar value
LIB$MULTF_DELTA_TIME Multiplies a delta time value by an
F-floating point scalar value
LIB$SUB_TIMES Subtracts two quadword times

27.3 Timer Routines Used to Obtain and Set Current Time


This section presents information about obtaining the current date and time,
and setting current time. The run-time library (LIB$) facility provides date/time
utility routines for languages that do not have built-in time and date functions.
These routines return information about the current date and time or a date/time
specified by the user. You can obtain the current time by using the LIB$DATE_
TIME routine or by implementing the SYS$GETTIM system service. To set the
current time, use the SYS$SETTIME system service.
Table 27–3 describes the date/time routines.

Table 27–3 Timer RTLs and System Services


Routine Function
Timer Run-Time Library (LIB$) Routines
LIB$DATE_TIME Returns, using a string descriptor, the
operating system date and time in the
semantics of a string that the user provides.
(continued on next page)

27–8 System Time Operations


System Time Operations
27.3 Timer Routines Used to Obtain and Set Current Time

Table 27–3 (Cont.) Timer RTLs and System Services


Routine Function
Timer Run-Time Library (LIB$) Routines

LIB$DAY Returns the number of days since the system


zero date of November 17, 1858. This routine
takes one required argument and two optional
arguments:
• The address of a longword to contain the
number of days since the system zero date
(required)
• A quadword passed by reference
containing a time in system time format
to be used instead of the current system
time (optional)
• A longword integer to contain the number
of 10-millisecond units since midnight
(optional)

LIB$DAY_OF_WEEK Returns the numeric day of the week for an


input time value. If the input time value is 0,
the current day of the week is returned. The
days are numbered 1 through 7: Monday is
day 1 and Sunday is day 7.

System Service Routine


SYS$SETIME Changes the value of or recalibrates the
system time.

27.3.1 Obtaining Current Time and Date with LIB$DATE_TIME


The LIB$DATE_TIME routine returns a character string containing the current
date and time in absolute time format. The full string requires a declaration of 23
characters. If you specify a shorter string, the value is truncated. A declaration of
16 characters obtains only the date. The following example displays the current
date and time:
! Formatted date and time
CHARACTER*23 DATETIME
! Status and library procedures
INTEGER*4 STATUS,
2 LIB$DATE_TIME
EXTERNAL LIB$DATE_TIME
STATUS = LIB$DATE_TIME (DATETIME)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
TYPE *, DATETIME

System Time Operations 27–9


System Time Operations
27.3 Timer Routines Used to Obtain and Set Current Time

27.3.2 Obtaining Current Time and Date with SYS$GETTIM


You can obtain the current date and time in internal format with the
SYS$GETTIM system service. You can convert from internal to character
format with the SYS$ASCTIM system service or a directive to the SYS$FAO
system service and convert back to internal format with the SYS$BINTIM system
service. The Get Time (SYS$GETTIM) system service places the time into a
quadword buffer. For example:

/* Buffer to receive the binary time */


struct {
unsigned int buff1, buff2;
}time;
.
.
.
main() {
unsigned status;
This call to SYS$GETTIM returns the current date and time in system format in
the quadword buffer TIME.
The Convert Binary Time to ASCII String (SYS$ASCTIM) system service converts
a time in system format to an ASCII string and returns the string in a 23-byte
buffer. You call the SYS$ASCTIM system service as follows:

#include <stdio.h>
#include <descrip.h>
struct {
unsigned int buff1, buff2;
}time_value;
main() {
unsigned int status;
char timestr[23];
$DESCRIPTOR(atimenow, timestr);
/* Get binary time */
status = SYS$GETTIM(&time_value);
if ((status & 1) != 1)
LIB$SIGNAL( status );
/* Convert binary time to ASCII */
status = SYS$ASCTIM(0, /* timlen - Length of ASCII string */
&atimenow, /* timbuf - ASCII time buffer */
&time_value, /* timadr - Binary time */
0); /* cvtflags - Conversion indicator */
if ((status & 1) != 1)
LIB$SIGNAL( status );

Because the address of a 64-bit time value is not supplied, the default value, 0, is
used.
The string the service returns has the following format:
dd-MMM-yyyy hh:mm:ss.cc

27–10 System Time Operations


System Time Operations
27.3 Timer Routines Used to Obtain and Set Current Time

dd Day of the month


MMM Month (a 3-character alphabetic abbreviation)
yyyy Year
hh:mm:ss.cc Time in hours, minutes, seconds, and hundredths of a second

27.3.3 Setting the Current Time with SYS$SETIME


The Set System Time (SYS$SETIME) system service allows a user with the
operator (OPER) and logical I/O (LOG_IO) privileges to set the current system
time. You can specify a new system time (using the timadr argument), or you
can recalibrate the current system time using the processor’s hardware time-of-
year clock (omitting the timadr argument). If you specify a time, it must be an
absolute time value; a delta time (negative) value is invalid.
The system time is set whenever the system is bootstrapped. Normally you do not
need to change the system time between system bootstrap operations; however, in
certain circumstances you may want to change the system time without rebooting.
For example, you might specify a new system time to synchronize two processors,
or to adjust for changes between standard time and Daylight Savings Time. Also,
you may want to recalibrate the time to ensure that the system time matches the
hardware clock time (the hardware clock is more accurate than the system clock).
The DCL command SET TIME calls the SYS$SETIME system service.
If a process issues a delta time request and then the system time is changed, the
interval remaining for the request does not change; the request executes after the
specified time has elapsed. If a process issues an absolute time request and the
system time is changed, the request executes at the specified time, relative to the
new system time.
The following example shows the effect of changing the system time on an
existing timer request. In this example, two set timer requests are scheduled:
one is to execute after a delta time of 5 minutes and the other specifies an
absolute time of 9:00.

#include <stdio.h>
#include <descrip.h>
#include <ssdef.h>
#include <stdlib.h>
void gemini (int x);
unsigned int status;
/* Buffers to receive binary times */
struct {
unsigned int buff1, buff2;
}abs_binary, delta_binary;

main() {
$DESCRIPTOR(abs_time,"-- 19:37:00.00"); /* 9 am absolute time */
$DESCRIPTOR(delta_time,"0 :00:30"); /* 5-min delta time */
/* Convert ASCII absolute time to binary format */
status = SYS$BINTIM( &abs_time, /* ASCII absolute time */
&abs_binary); /* Converted to binary */

System Time Operations 27–11


System Time Operations
27.3 Timer Routines Used to Obtain and Set Current Time

if (status == SS$_NORMAL)
{
status = SYS$SETIMR(0, /* efn - event flag */
&abs_binary, /* daytim - expiration time */
&gemini, /* astadr - AST routine */
1, /* reqidt - timer request id */
0); /* flags */
if (status == SS$_NORMAL)
printf("Setting system timer A\n");
}
else
LIB$SIGNAL( status );
/* Convert ASCII delta time to binary format */
status = SYS$BINTIM( &delta_time, /* ASCII delta time */
&delta_binary); /* Converted to binary */
if (status == SS$_NORMAL)
{
printf("Converting delta time to binary format\n");
status = SYS$SETIMR(0, /* efn - event flag */
&delta_binary, /* daytim - expiration time */
&gemini, /* astadr - AST routine */
2, /* reqidt - timer request id */
0); /* flags */
if (status == SS$_NORMAL)
printf("Setting system timer B\n");
else
LIB$SIGNAL( status );
}
else
LIB$SIGNAL( status );
status = SYS$HIBER();
}

void gemini (int reqidt) {


unsigned short outlen;
unsigned int cvtflg=1;
char timenow[12];
char fao_str[80];
$DESCRIPTOR(nowdesc, timenow);
$DESCRIPTOR(fao_in, "Request ID !UB answered at !AS");
$DESCRIPTOR(fao_out, fao_str);
/* Returns and converts the current time */
status = SYS$ASCTIM( 0, /* timlen - length of ASCII string */
&nowdesc, /* timbuf - receives ASCII string */
0, /* timadr - time value to convert */
cvtflg); /* cvtflg - conversion flags */
if ((status & 1) != 1)
LIB$SIGNAL( status );
/* Receives the formatted output string */
status = SYS$FAO(&fao_in, /* srcstr - control FAO string */
&outlen, /* outlen - length in bytes */
&fao_out, /* outbuf - output buffer */
reqidt, /* p1 - param needed for 1st FAO dir */
&nowdesc); /* p2 - param needed for 2nd FAO dir */
if ((status & 1) != 1)
LIB$SIGNAL( status );
status = LIB$PUT_OUTPUT( &fao_out );
return;
}

27–12 System Time Operations


System Time Operations
27.3 Timer Routines Used to Obtain and Set Current Time

The following example shows the output received from the preceding program.
Assume the program starts execution at 8:45. Seconds later, the system time is
set to 9:15. The timer request that specified an absolute time of 9:00 executes
immediately, because 9:00 has passed. The request that specified a delta time of
5 minutes times out at 9:20.
$ SHOW TIME
30-DEC-1993 8:45:04.56 +----------------------+
$ RUN SCORPIO | operator sets system |
<-----------------------------------------------| time to 9:15 |
Request ID number 1 executed at 09:15:00.00 +----------------------+
Request ID number 2 executed at 09:20:00.02
$

27.4 Routines Used for Timer Requests


This section presents information about setting and canceling timer requests,
and scheduling and canceling wakeups. Since many applications require the
scheduling of program activities based on clock time, the operating system allows
an image to schedule events for a specific time of day or after a specified time
interval. For example, you can use timer system services to schedule, convert,
or cancel events. For example, you can use the timer system services to do the
following:
• Schedule the setting of an event flag or the queuing of an asynchronous
system trap (AST) for the current process, or cancel a pending request that
has not yet been processed
• Schedule a wakeup request for a hibernating process, or cancel a pending
wakeup request that has not yet been processed
• Set or recalibrate the current system time, if the caller has the proper user
privileges
Table 27–4 describes system services that set, cancel, and schedule timer
requests.

Table 27–4 Timer System Services


Timer System Service Routine Function
SYS$SETIMR Sets the timer to expire at a specified time. This
service sets a per-thread timer.
SYS$CANTIM Cancels all or a selected subset of the Set Timer
requests previously issued by the current image
executing in a process. This service cancels all
timers associated with the process.
SYS$SCHDWK Schedules the awakening (restarting) of a
kernel thread that has placed itself in a state
of hibernation with the Hibernate (SYS$HIBER)
service.
SYS$CANWAK Removes all scheduled wakeup requests for a
process from the timer queue, including those
made by the caller or by other processes. The
Schedule Wakeup ($SCHDWK) service makes
scheduled wakeup requests.

System Time Operations 27–13


System Time Operations
27.4 Routines Used for Timer Requests

27.4.1 Setting Timer Requests with SYS$SETIMR


Timer requests made with the Set Timer (SYS$SETIMR) system service are
queued; that is, they are ordered for processing according to their expiration
times. The quota for timer queue entries (TQELM quota) controls the number of
entries a process can have pending in this timer queue.
When you call the SYS$SETIMR system service, you can specify either an
absolute time or a delta time value. Depending on how you want the request
processed, you can specify either or both of the following:
• The number of an event flag to be set when the time expires. If you do not
specify an event flag, the system sets event flag 0.
• The address of an AST service routine to be executed when the time expires.
Optionally, you can specify a request identification for the timer request. You
can use this identification to cancel the request, if necessary. The request
identification is also passed as the AST parameter to the AST service routine, if
one is specified, so that the AST service routine can identify the timer request.
Example 27–2 and Example 27–3 show timer requests using event flags and
ASTs, respectively. Event flags, event flag services, and ASTs are described in
more detail in Chapter 8.

Example 27–2 Setting an Event Flag


#include <stdio.h>
#include <ssdef.h>
#include <descrip.h>
/* Buffer to receive binary time */
struct {
unsigned int buff1, buff2;
}b30sec;
main() {
unsigned int efn = 4,status;
$DESCRIPTOR(a30sec,"0 00:00:30.00");
/* Convert time to binary format */
status = SYS$BINTIM( &a30sec, /* timbuf - ASCII time */
&b30sec);/* timadr - binary time */
if ((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Converting ASCII to binary time...\n");
/* Set timer to wait */
status = SYS$SETIMR( efn, /* efn - event flag */
&b30sec,/* daytim - binary time */
0, /* astadr - AST routine */
0, /* reqidt - timer request */
0); /* flags */ !
if ((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Request event flag be set in 30 seconds...\n");

(continued on next page)

27–14 System Time Operations


System Time Operations
27.4 Routines Used for Timer Requests

Example 27–2 (Cont.) Setting an Event Flag

/* Wait 30 seconds */
status = SYS$WAITFR( efn ); "
if ((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Timer expires...\n");
}

! The call to SYS$SETIMR requests that event flag 4 be set in 30 seconds


(expressed in the quadword B30SEC).
" The Wait for Single Event Flag (SYS$WAITFR) system service places the
process in a wait state until the event flag is set. When the timer expires, the
flag is set and the process continues execution.

Example 27–3 Specifying an AST Service Routine


#include <stdio.h>
#include <descrip.h>
#define NOON 12
struct {
unsigned int buff1, buff2;
}bnoon;
/* Define the AST routine */
void astserv( int );
main() {
unsigned int status, reqidt=12;
$DESCRIPTOR(anoon,"-- 12:00:00.00");
/* Convert ASCII time to binary */
status = SYS$BINTIM(&anoon, /* timbuf - ASCII time */ !
&bnoon); /* timadr - binary time buffer */
if((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Converting ASCII to binary...\n");
/* Set timer */
status = SYS$SETIMR(0, /* efn - event flag */ "
&bnoon, /* daytim - timer expiration */
&astserv, /* astadr - AST routine */
reqidt, /* reqidt - timer request id */
0); /* cvtflg - conversion flags */
if((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Setting timer expiration...\n");
status = SYS$HIBER();
}
void astserv( int astprm ) { #

(continued on next page)

System Time Operations 27–15


System Time Operations
27.4 Routines Used for Timer Requests

Example 27–3 (Cont.) Specifying an AST Service Routine

/* Do something if it’s a "noon" request */


if (astprm == NOON)
printf("This is a noon AST request\n");
else
printf("Handling some other request\n");
status = SYS$SCHDWK(0, /* pidadr - process id */
0);/* prcnam - process name */
return;
}

! The call to SYS$BINTIM converts the ASCII string representing 12:00


noon to format. The value returned in BNOON is used as input to the
SYS$SETIMR system service.
" The AST routine specified in the SYS$SETIMR request will be called when
the timer expires, at 12:00 noon. The reqidt argument identifies the timer
request. (This argument is passed as the AST parameter and is stored
at offset 4 in the argument list. See Chapter 8.) The process continues
execution; when the timer expires, it is interrupted by the delivery of the
AST. Note that if the current time of day is past noon, the timer expires
immediately.
# This AST service routine checks the parameter passed by the reqidt
argument to determine whether it must service the 12:00 noon timer request
or another type of request (identified by a different reqidt value). When the
AST service routine completes, the process continues execution at the point of
interruption.

27.4.2 Canceling a Timer Request with SYS$CANTIM


The Cancel Timer Request (SYS$CANTIM) system service cancels timer requests
that have not been processed. The SYS$CANTIM system service removes the
entries from the timer queue. Cancellation is based on the request identification
given in the timer request. For example, to cancel the request illustrated in
Example 27–3, you would use the following call to SYS$CANTIM:
unsigned int status, reqidt=12;
.
.
.
status = SYS$CANTIM( reqidt, 0);
If you assign the same identification to more than one timer request, all requests
with that identification are canceled. If you do not specify the reqidt argument,
all your requests are canceled.

27.4.3 Scheduling Wakeups with SYS$WAKE


Example 27–2 shows a process placing itself in a wait state using the
SYS$SETIMR and SYS$WAITFR services. A process can also make itself inactive
by hibernating. A process hibernates by issuing the Hibernate (SYS$HIBER)
system service. Hibernation is reversed by a wakeup request, which can be put
into effect immediately with the SYS$WAKE system service or scheduled with the
Schedule Wakeup (SYS$SCHDWK) system service. For more information about
the SYS$HIBER and SYS$WAKE system services, see Chapter 4.

27–16 System Time Operations


System Time Operations
27.4 Routines Used for Timer Requests

The following example shows a process scheduling a wakeup for itself prior to
hibernating:
#include <stdio.h>
#include <descrip.h>
struct {
unsigned int buff1, buff2;
}btensec;
main() {
unsigned int status;
$DESCRIPTOR(atensec,"0 00:00:10.00");
/* Convert time */
status = SYS$BINTIM(&atensec, /* timbuf - ASCII time */
&btensec);/* timadr - binary time */
if ((status & 1 ) != 1)
LIB$SIGNAL( status );
/* Schedule wakeup */
status = SYS$SCHDWK(0, /* pidadr - process id */
0, /* prcnam - process name */
&btensec, /* daytim - wake up time */
0); /* reptim - repeat interval */
if ((status & 1 ) != 1)
LIB$SIGNAL( status );
/* Sleep ten seconds */
status = SYS$HIBER();
if ((status & 1 ) != 1)
LIB$SIGNAL( status );
}
Note that a suitably privileged process can wake or schedule a wakeup request
for another process; thus, cooperating processes can synchronize activity using
hibernation and scheduled wakeups. Moreover, when you use the SYS$SCHDWK
system service in a program, you can specify that the wakeup request be repeated
at fixed time intervals. See Chapter 4 for more information on hibernation and
wakeup.

27.4.4 Canceling a Scheduled Wakeup with SYS$CANWAK


You can cancel scheduled wakeup requests that are pending but have not yet
been processed with the Cancel Wakeup (SYS$CANWAK) system service. This
service cancels a wakeup request for a specific kernel thread, if a process ID is
specified. If a process name is specified, then the initial thread’s wakeup request
is canceled.
The following example shows the scheduling of wakeup requests for the process
CYGNUS and the subsequent cancellation of the wakeups. The SYS$SCHDWK
system service in this example specifies a delta time of 1 minute and an interval
time of 1 minute; the wakeup is repeated every minute until the requests are
canceled.
#include <stdio.h>
#include <descrip.h>
/* Buffer to hold one minute */
struct {
unsigned int buff1, buff2;
}interval;
main() {

System Time Operations 27–17


System Time Operations
27.4 Routines Used for Timer Requests

unsigned int status;


$DESCRIPTOR(one_min,"0 00:01:00.00"); /* One minute delta */
$DESCRIPTOR(cygnus, "CYGNUS"); /* Process name */
/* Convert time to binary */
status = SYS$BINTIM(&one_min, /* timbuf - ASCII delta time */
&interval); /* timadr - Buffer to hold binary time */
if((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Converting time to binary format...\n");
/* Schedule wakeup */
status = SYS$SCHDWK(0, /* pidadr - process id */
&cygnus, /* prcnam - process name */
&interval, /* daytim - time to be awakened */
&interval); /* reptim - repeat interval */
if((status & 1) != 1)
LIB$SIGNAL( status );
}
else
printf("Scheduling wakeup...\n");
/* Cancel wakeups */
status = SYS$CANWAK(0, /* pidadr - process id */
&cygnus); /* prcnam - process name */
}

27.4.5 Executing a Program at Timed Intervals


To execute a program at timed intervals, you can use either the LIB$SPAWN
routine or the SYS$CREPRC system service. With LIB$SPAWN, you can create
a subprocess that executes a command procedure containing three commands:
the DCL command WAIT, the command that invokes the desired program, and a
GOTO command that directs control back to the WAIT command. To prevent the
parent process from remaining in hibernation until the subprocess executes, you
should execute the subprocess concurrently; that is, you should specify CLI$M_
NOWAIT.
For more information about using LIB$SPAWN and SYS$CREPRC, see Chapter
4.

27.5 Routines Used for Timer Statistics


This section presents information about the LIB$INIT_TIMER, LIB$SHOW_
TIMER, LIB$STAT_TIMER, and LIB$FREE_TIMER routines. By calling these
run-time library routines, you can collect the following timer statistics from the
system:
• Elapsed time—Actual time that has passed since setting a timer
• CPU time—CPU time that has passed since setting a timer
• Buffered I/O—Number of buffered I/O operations that have occurred since
setting a timer
• Direct I/O—Number of direct I/O operations that have occurred since setting
a timer
• Page faults—Number of page faults that have occurred since setting a timer

27–18 System Time Operations


System Time Operations
27.5 Routines Used for Timer Statistics

Following are descriptions of each routine:


• LIB$INIT_TIMER—Allocates and initializes space for collecting the statistics.
You should specify the handle-adr argument as a variable with a value of 0
to ensure the modularity of your program. When you specify the argument,
the system collects the information in a specially allocated area in dynamic
storage. This prevents conflicts with other timers used by the application.
• LIB$SHOW_TIMER—Obtains one or all of five statistics (elapsed time, CPU
time, buffered I/O, direct I/O, and page faults); the statistics are formatted for
output. The handle-adr argument must be the same value as specified for
LIB$INIT_TIMER (do not modify this variable). Specify the code argument
to obtain one particular statistic rather than all the statistics.
You can let the system write the statistics to SYS$OUTPUT (the default), or
you can process the statistics with your own routine. To process the statistics
yourself, specify the name of your routine in the action-rtn argument.
You can pass one argument to your routine by naming it in the user-arg
argument. If you use your own routine, it must be written as an integer
function and return an error code (return a value of 1 for success). This error
code becomes the error code returned by LIB$SHOW_TIMER. Two arguments
are passed to your routine: the first is a passed-length character string
containing the formatted statistics, and the second is the value of the fourth
argument (if any) specified to LIB$SHOW_TIMER.
• LIB$STAT_TIMER—Obtains one of five unformatted statistics. Specify the
statistic you want in the code argument. Specify a storage area for the
statistic in value. The handle-adr argument must be the same value as you
specified for LIB$INIT_TIMER.
• LIB$FREE_TIMER—Ensures the modularity of your program. Invoke this
procedure when you are done with the timer. The value in the handle-adr
argument must be the same as that specified for LIB$INIT_TIMER.
You must invoke LIB$INIT_TIMER to allocate storage for the timer. You should
invoke LIB$FREE_TIMER before you exit from your program unit. In between,
you can invoke LIB$SHOW_TIMER or LIB$STAT_TIMER, or both, as often as
you want. Example 27–4 invokes LIB$SHOW_TIMER and uses a user-written
subprogram either to display the statistics or to write them to a file.

Example 27–4 Displaying and Writing Timer Statistics


.
.
.
! Timer arguments
INTEGER*4 TIMER_ADDR,
2 TIMER_DATA,
2 TIMER_ROUTINE
EXTERNAL TIMER_ROUTINE
! Declare library procedures as functions
INTEGER*4 LIB$INIT_TIMER,
2 LIB$SHOW_TIMER
EXTERNAL LIB$INIT_TIMER,
2 LIB$SHOW_TIMER

(continued on next page)

System Time Operations 27–19


System Time Operations
27.5 Routines Used for Timer Statistics

Example 27–4 (Cont.) Displaying and Writing Timer Statistics


! Work variables
CHARACTER*5 REQUEST
INTEGER*4 STATUS
! User request - either WRITE or FILE
INTEGER*4 WRITE,
2 FILE
PARAMETER (WRITE = 1,
2 FILE = 2)
! Get user request
WRITE (UNIT=*, FMT=’($,A)’) ’ Request: ’
ACCEPT *, REQUEST
IF (REQUEST .EQ. ’WRITE’) TIMER_DATA = WRITE
IF (REQUEST .EQ. ’FILE’) TIMER_DATA = FILE
! Set timer
STATUS = LIB$INIT_TIMER (TIMER_ADDR)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
! Get statistics
STATUS = LIB$SHOW_TIMER (TIMER_ADDR,,
2 TIMER_ROUTINE,
2 TIMER_DATA)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
! Free timer
STATUS = LIB$FREE_TIMER (TIMER_ADDR)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
INTEGER FUNCTION TIMER_ROUTINE (STATS,
2 TIMER_DATA)
! Dummy arguments
CHARACTER*(*) STATS
INTEGER TIMER_DATA
! Logical unit number for file
INTEGER STATS_FILE
! User request
INTEGER WRITE,
2 FILE
PARAMETER (WRITE = 1,
2 FILE = 2)
! Return code
INTEGER SUCCESS,
2 FAILURE
PARAMETER (SUCCESS = 1,
2 FAILURE = 0)

(continued on next page)

27–20 System Time Operations


System Time Operations
27.5 Routines Used for Timer Statistics

Example 27–4 (Cont.) Displaying and Writing Timer Statistics


! Set return status to success
TIMER_ROUTINE = SUCCESS
! Write statistics or file them in STATS.DAT
IF (TIMER_DATA .EQ. WRITE) THEN
TYPE *, STATS
ELSE IF (TIMER_DATA .EQ. FILE) THEN
CALL LIB$GET_LUN (STATS_FILE)
OPEN (UNIT=STATS_FILE,
2 FILE=’STATS.DAT’)
WRITE (UNIT=STATS_FILE,
2 FMT=’(A)’) STATS
ELSE
TIMER_ROUTINE = FAILURE
END IF
END

You can use the SYS$GETSYI system service to obtain more detailed system
information about boot time, the cluster, processor type, emulated instructions,
nodes, paging files, swapping files, and hardware and software versions. With
SYS$GETQUI and LIB$GETQUI, you can obtain queue information.

27.6 Date/Time Formatting Routines


This section provides information about using date/time formatting routines that
allow you to specify input and output formats other than the standard operating
system format for dates and times. These include international formats with
appropriate language spellings for days and months.
If the desired language is English (the default language) and the desired format
is the standard operating system format, then initialization of logical names is
not required in order to use the date/time input and output routines. However,
if the desired language and format are not the defaults, the system manager (or
any user having CMEXEC, SYSNAM, and SYSPRV privileges) must initialize the
required logical names.

27.6.1 Performing Date/Time Logical Initialization


Note
You must complete the initialization steps outlined in this section
before you can use any of the date/time input and output routines with
languages and formats other than the defaults.

As an alternative to the standard operating system format, the command


procedure SYS$MANAGER:LIB$DT_STARTUP.COM defines several output
formats for dates and times. This command procedure must be executed by the
system manager before using any of the run-time library date/time routines for
input or output formats other than the default. Ideally, this command procedure
should be executed from a site-specific startup procedure.
In addition to defining the date/time formats, the LIB$DT_STARTUP.COM
command procedure also defines spellings for date and time elements in
languages other than English. If different language spellings are required,
the system manager must define the logical name SYS$LANGUAGES before

System Time Operations 27–21


System Time Operations
27.6 Date/Time Formatting Routines

invoking LIB$DT_STARTUP.COM. The translation of SYS$LANGUAGES is then


used to select which languages are defined.
Table 27–5 shows the available languages and their logical names.

Table 27–5 Available Languages for Date/Time Formatting


Language Logical Name
Austrian AUSTRIAN
Danish DANISH
Dutch DUTCH
Finnish FINNISH
French FRENCH
French Canadian CANADIAN
German GERMAN
Hebrew HEBREW
Italian ITALIAN
Norwegian NORWEGIAN
Portuguese PORTUGUESE
Spanish SPANISH
Swedish SWEDISH
Swiss French SWISS_FRENCH
Swiss German SWISS_GERMAN

For example, if the system managers want the spellings for French, German, and
Italian languages to be defined, they must define SYS$LANGUAGES as shown,
prior to invoking LIB$DT_STARTUP.COM:
$ DEFINE SYS$LANGUAGES FRENCH, GERMAN, ITALIAN
If the user requires an additional language, for example FINNISH, then the
system manager must add FINNISH to the definition of SYS$LANGUAGES and
reexecute the command procedure.
Date/Time Manipulation Option
The Date/Time Manipulation option provides date/time spelling support for
four new languages. Users or application programmers can select the desired
language by defining the logical name SYS$LANGUAGES. The new languages
and their equivalent names are as follows:

Language Equivalent Name


Chinese (simplified character) Hanzi
Chinese (traditional character) Hanyu
Korean Hangul
Thai Thai

27–22 System Time Operations


System Time Operations
27.6 Date/Time Formatting Routines

Defining Date/Time Spelling


To define the spelling for Hanzi and Hanyu, define SYS$LANGUAGES as shown
below, prior to invoking LIB$DT_STARTUP.COM:
$ DEFINE SYS$LANGUAGES HANZI, HANYU
$ @SYS$MANAGER:LIB$DT_STARTUP
Predefined Output Formats
Figure 27–1 lists the new predefined date format logical names in the first
column, their formats in the second column, and examples of the output generated
using these formats in the third column.

Figure 27–1 Predefined Output Date Formats

LIB$DATE_FORMAT_042 !Y4 !MNB !DB !WAU 1994 3 7 ( )


LIB$DATE_FORMAT_043 !Y4 !MNB !DB !WU 1994 3 7
LIB$DATE_FORMAT_044 !Y4 !MNB !DB !WAU 1994 3 7 ( )
LIB$DATE_FORMAT_045 !Y4 !MNB !DB !WU 1994 3 7
LIB$DATE_FORMAT_046 !Y4 !MNB !DB !WAU 1994 3 7 ( )
LIB$DATE_FORMAT_047 !Y4 !MNB !DB !WU 1994 3 7
ZK-7263A-AI

Note
LIB$DATE_FORMAT_042 and LIB$DATE_FORMAT_043 support the
DEC Hanzi coded character set.
LIB$DATE_FORMAT_044 and LIB$DATE_FORMAT_045 support the
DEC Hanyu coded character set.
LIB$DATE_FORMAT_046 and LIB$DATE_FORMAT_047 support the
DEC Hangul coded character set.

Figure 27–2 lists the new predefined time format logical names in the first
column, their formats in the second column, and examples of the output generated
using these formats in the third column.

Figure 27–2 Predefined Output Time Formats

LIB$TIME_FORMAT_021 !MIU!HB2 !MB !SB 3 3 6


LIB$TIME_FORMAT_022 !MB !SB
!MIU!HB2 !MB !SB 3 3 6
LIB$TIME_FORMAT_023 !MIU !HB2 !MB !SB 3 3 6
ZK-7262A-AI

System Time Operations 27–23


System Time Operations
27.6 Date/Time Formatting Routines

Note
LIB$TIME_FORMAT_021 supports the DEC Hanzi coded character set.
LIB$TIME_FORMAT_022 supports the DEC Hanyu coded character set.
LIB$TIME_FORMAT_023 supports the DEC Hangul coded character set.

Thus, to select a particular format for a date or time, or both, you can define the
LIB$DT_FORMAT logical name using the following logicals:
• LIB$DATE_FORMAT_nnn, where nnn can range from 001 to 047
• LIB$TIME_FORMAT_nnn, where nnn can range from 001 to 023

27.6.2 Selecting a Format


There are two methods by which date/time input and output formats can be
selected:
• The language and format are determined at run time through the translation
of the logical names SYS$LANGUAGE, LIB$DT_FORMAT, and LIB$DT_
INPUT_FORMAT.
• The language and format are programmable at compile time through the use
of the LIB$INIT_DATE_TIME_CONTEXT routine.
In general, if an application accepts text from a user or formats text for
presentation to a user, you should use the logical name method of specifying
language and format. With this method, the user assigns equivalence names to
the logical names SYS$LANGUAGE, LIB$DT_FORMAT, and LIB$DT_INPUT_
FORMAT, thereby selecting the language and input or output format of the date
and time at run time.
If an application reads text from internal storage or formats text for internal
storage or transmission, the language and format should be specified at compile
time. If this is the case, the routine LIB$INIT_DATE_TIME_CONTEXT specifies
the language and format of choice.
27.6.2.1 Formatting Run-Time Mnemonics
The format mnemonics listed in Table 27–6 define both input and output formats
at run time.

Table 27–6 Format Mnemonics


Date Explanation
!D0 Day; zero-filled
!DD Day; no fill
!DB Day; blank-filled
!WU Weekday; uppercase
!WAU Weekday; abbreviated, uppercase
!WC Weekday; capitalized
(continued on next page)

27–24 System Time Operations


System Time Operations
27.6 Date/Time Formatting Routines

Table 27–6 (Cont.) Format Mnemonics


Date Explanation

!WAC Weekday; abbreviated, capitalized


!WL Weekday; lowercase
!WAL Weekday; abbreviated, lowercase
!MAU Month; alphabetic, uppercase
!MAAU Month; alphabetic, abbreviated, uppercase
!MAC Month; alphabetic, capitalized
!MAAC Month; alphabetic, abbreviated, capitalized
!MAL Month; alphabetic, lowercase
!MAAL Month; alphabetic, abbreviated, lowercase
!MN0 Month; numeric, zero-filled
!MNM Month; numeric, no fill
!MNB Month; numeric, blank-filled
!Y4 Year; 4 digits
!Y3 Year; 3 digits
!Y2 Year; 2 digits
!Y1 Year; 1 digit
!Z4 Year; 4 digits
!Z3 Year; 3 digits
!Z2 Year; 2 digits (see LIB$CONVERT_DATE_STRING)
!Z1 Year; 1 digit

Time Explanation
!H04 Hours; zero-filled, 24-hour clock
!HH4 Hours; no fill, 24-hour clock
!HB4 Hours; blank-filled, 24-hour clock
!H02 Hours; zero-filled, 12-hour clock
!HH2 Hours; no fill, 12-hour clock
!HB2 Hours; blank-filled, 12-hour clock
!M0 Minutes; zero-filled
!MM Minutes; no fill
!MB Minutes; blank-filled
!S0 Seconds; zero-filled
!SS Seconds; no fill
!SB Seconds; blank-filled
!C7 Fractional seconds; 7 digits
!C6 Fractional seconds; 6 digits
!C5 Fractional seconds; 5 digits
!C4 Fractional seconds; 4 digits
(continued on next page)

System Time Operations 27–25


System Time Operations
27.6 Date/Time Formatting Routines

Table 27–6 (Cont.) Format Mnemonics


Time Explanation

!C3 Fractional seconds; 3 digits


!C2 Fractional seconds; 2 digits
!C1 Fractional seconds; 1 digit
!MIU Meridiem indicator; uppercase
!MIC Meridiem indicator; capitalized (mixed case)
!MIL Meridiem indicator; lowercase

27.6.2.2 Specifying Formats at Run Time


If an application accepts text from a user or formats text for presentation to a
user, you should use the logical name method of specifying language and format.
With this method, the user assigns equivalence names to the logical names
SYS$LANGUAGE, LIB$DT_FORMAT, and LIB$DT_INPUT_FORMAT, thereby
selecting the language and format of the date and time at run time. LIB$DT_
INPUT_FORMAT must be defined using the mnemonics listed in Table 27–6. The
possible choices for SYS$LANGUAGE and LIB$DT_FORMAT are defined in the
SYS$MANAGER:LIB$DT_STARTUP.COM command procedure that is executed
by the system manager before using these routines.
The following actions occur when any translation of a logical name fails:
• If the translation of SYS$LANGUAGE or any logical name relating to text
fails, then English is used and a status of LIB$_ENGLUSED is returned.
• If the translation of LIB$DT_FORMAT, LIB$DT_INPUT_FORMAT, or
any logical name relating to format fails, the operating system standard
(SYS$ASCTIM) representation of the date and time is used, that is, dd-
MMM-yyyy hh:mm:ss.cc, and a status of LIB$_DEFFORUSE is returned.
Since English is the default language and must therefore always be available,
English spellings are not taken from logical name translations, but rather are
looked up in an internal table.
27.6.2.3 Specifying Input Formats at Run Time
Using the logical name LIB$DT_INPUT_FORMAT, you can define your own input
format at run time using the mnemonics listed in Table 27–6. Once an input
format is defined, any dates or times that are input to the application are parsed
against this format. For example:
$ DEFINE LIB$DT_INPUT_FORMAT -
_$ "!MAU !DD, !Y4 !H02:!M0:!S0:!C2 !MIU"
A valid input date string would be as follows:
JUNE 15, 1993 08:45:06:50 PM
If the user has selected a language other than English, then the translation
of SYS$LANGUAGE is used by the parser to recognize alphabetic months and
meridiem indicators in the selected language.

27–26 System Time Operations


System Time Operations
27.6 Date/Time Formatting Routines

Input Format String


The input format string used to define the input date/time format must contain
at least the first seven of the following eight fields:
• Month (either alphabetic or numeric)
• Day of the month (numeric)
• Year (from 1 to 4 digits)
• Hour (12- or 24-hour clock)
• Minute of the hour
• Second of the minute
• Fractional seconds
• Meridiem indicator (required for 12-hour clock; illegal for 24-hour clock)
If the input format string specifies a 24-hour clock, the string contains only the
first seven fields in the preceding list. If a 12-hour clock is specified, the eighth
field (the meridiem indicator) is required.
The format string fields must appear in two groups: one for date and one for time
(date and time fields cannot be intermixed within a group). For the input format,
alphabetic case distinctions and abbreviation-specific codes have no significance.
For example, the following format string specifies that the month name will be
uppercase and spelled out in full:
!MAU !DD, !Y4 !H02:!M0:!S0:!C2 !MIU
If the input string corresponding to this format string contains a month name
that is abbreviated and lowercase, the parse of the input string still works
correctly. For example:
feb 25, 1988 04:39:02:55 am
If this input string is entered, the parse still recognizes ‘‘feb’’ as the month name
and ‘‘am’’ as the meridiem indicator, even though the format string specified both
of these fields as uppercase, and the month name as unabbreviated.
Punctuation in the Format and Input Strings
One important aspect to consider when formatting date/time input strings is
punctuation. The punctuation referred to here is the characters that separate the
various date/time fields or the date and time groups. Punctuation in these strings
is important because it is used as an outline for the parser, allowing the parser to
synchronize the input fields to the format fields.
There are three distinct classes of punctuation:
• None
Although it is common for no punctuation to begin or end an input format
string, you can specify a date/time format that also has no punctuation
between the fields or groups of the format string. If this is the case, the
corresponding input string must not have any punctuation between the
respective fields or groups, although white space (see the next item in this
list) may appear at the beginning or end of the input string.

System Time Operations 27–27


System Time Operations
27.6 Date/Time Formatting Routines

• White space
White space includes any combination of spaces and tabs. In the
interpretation of the format string, any white space is condensed to a single
space. When parsing an input string, white space is generally noted as
synchronizing punctuation and is skipped; however, white space is significant
in some situations, such as with blank-filled numbers.
• Explicit
Explicit punctuation refers to any string of one or more characters that is
used as punctuation and is not solely comprised of white space. Any white
space appearing within an explicit punctuation string is interpreted literally;
in other words, the white space is not compressed. In the format string, you
can use explicit punctuation to denote a particular format and to guide the
parser in parsing the input string. In the input string, you can use explicit
punctuation to synchronize the parse of the input string against the format
string. The explicit punctuation used should not be a subset of the valid input
of any field that it precedes or follows it.
Punctuation is especially important in providing guidelines for the parser to
translate the input date/time string properly.
Default Date/Time Fields
Punctuation in a date/time string is also useful for specifying which fields you
want to omit in order to accept the default values. That is, you can control the
parsing of the input string by supplying punctuation without the appropriate
field values. If only the punctuation is supplied and a user-supplied default is not
specified, the value of the omitted field defaults according to the following rules:
• For the date group, the default is the current date.
• For the time group, the default is 00:00:00.00.
Table 27–7 gives some examples of input strings (using punctuation to indicate
defaulted fields) and their full translations (assuming a current date of 25-FEB-
1993 and using the default input format).

Table 27–7 Input String Punctuation and Defaults


Input Full Date/Time Input String
31 31-FEB-1993 00:00:00.00
-MAR 25-MAR-1993 00:00:00.00
-SEPTEMBER 25-SEP-1993 00:00:00.00
-1993 25-FEB-1993 00:00:00.00
23: 25-FEB-1993 23:00:00.00
:45: 25-FEB-1993 00:45:00.00
::23 25-FEB-1993 00:00:23.00
.01 25-FEB-1993 00:00:00.01

Note on the Changing Century


Because the default is the current date for the date group, if you specify a value
of 00 with the !Y2 format, the year is interpreted as 1900. After January 1, 2000,
the value 00 will be interpreted as 2000.

27–28 System Time Operations


System Time Operations
27.6 Date/Time Formatting Routines

For example, 02/29/00 is interpreted as 29-FEB-1900, which results in LIB$_


INVTIME because 1900 is not a leap year. After the turn of the century (the year
2000), 02/29/00 will be 29-FEB-2000, which is a valid date because 2000 is a leap
year.
27.6.2.4 Specifying Output Formats at Run Time
If the logical name method is used to specify an output format at run time, the
translations of the logical names SYS$LANGUAGE and LIB$DT_FORMAT
specify one or more executive mode logical names which in turn must be
translated to determine the actual format string. These additional logical names
supply such things as the names of the days of the week and the months in the
selected language (as determined by SYS$LANGUAGE). All of these logicals are
predefined, so that a nonprivileged user can select any one of these languages and
formats. In addition, a user can create his or her own languages and formats;
however, the CMEXEC, SYSNAM and SYSPRV privileges are required.
To select a particular format for a date or time, or both, you must define the
LIB$DT_FORMAT logical name using the following:
• LIB$DATE_FORMAT_nnn, where nnn ranges from 001 to 040
• LIB$TIME_FORMAT_nnn, where nnn ranges from 001 to 020
The order in which these logical names appear in the definition of LIB$DT_
FORMAT determines the order in which they are output. A single space is
inserted into the output string between the two elements, if the definition
specifies that both are output. For example:
$ DEFINE LIB$DT_FORMAT LIB$DATE_FORMAT_006, LIB$TIME_FORMAT_012
This definition causes the date to be output in the specified format, followed by a
space and the time in the specified format, as follows:
13 JAN 93 9:13 AM
Table 27–8 lists all predefined date format logical names, their formats, and
examples of the output generated using those formats. (The mnemonics used to
specify the formats are listed in Table 27–6.)

Table 27–8 Predefined Output Date Formats


Date Format Logical Name Format Example
LIB$DATE_FORMAT_001 !DB-!MAAU-!Y4 13-JAN-1993
LIB$DATE_FORMAT_002 !DB !MAU !Y4 13 JANUARY 1993
LIB$DATE_FORMAT_003 !DB.!MAU !Y4 13.JANUARY 1993
LIB$DATE_FORMAT_004 !DB.!MAU.!Y4 13.JANUARY.1993
LIB$DATE_FORMAT_005 !DB !MAU !Y2 13 JANUARY 93
LIB$DATE_FORMAT_006 !DB !MAAU !Y2 13 JAN 93
LIB$DATE_FORMAT_007 !DB.!MAAU !Y2 13.JAN 93
LIB$DATE_FORMAT_008 !DB.!MAAU.!Y2 13.JAN.93
LIB$DATE_FORMAT_009 !DB !MAAU !Y4 13 JAN 1993
LIB$DATE_FORMAT_010 !DB.!MAAU !Y4 13.JAN 1993
(continued on next page)

System Time Operations 27–29


System Time Operations
27.6 Date/Time Formatting Routines

Table 27–8 (Cont.) Predefined Output Date Formats


Date Format Logical Name Format Example

LIB$DATE_FORMAT_011 !DB.!MAAU.!Y4 13.JAN.1993


LIB$DATE_FORMAT_012 !MAU !DD, !Y4 JANUARY 13, 1993
LIB$DATE_FORMAT_013 !MN0/!D0/!Y2 01/13/93
LIB$DATE_FORMAT_014 !MN0-!D0-!Y2 01-13-93
LIB$DATE_FORMAT_015 !MN0.!D0.!Y2 01.13.93
LIB$DATE_FORMAT_016 !MN0 !D0 !Y2 01 13 93
LIB$DATE_FORMAT_017 !D0/!MN0/!Y2 13/01/93
LIB$DATE_FORMAT_018 !D0/!MN0-!Y2 13/01-93
LIB$DATE_FORMAT_019 !D0-!MN0-!Y2 13-01-93
LIB$DATE_FORMAT_020 !D0.!MN0.!Y2 13.01.93
LIB$DATE_FORMAT_021 !D0 !MN0 !Y2 13 01 93
LIB$DATE_FORMAT_022 !Y2/!MN0/!D0 93/01/13
LIB$DATE_FORMAT_023 !Y2-!MN0-!D0 93-01-13
LIB$DATE_FORMAT_024 !Y2.!MN0.!D0 93.01.13
LIB$DATE_FORMAT_025 !Y2 !MN0 !D0 93 01 13
LIB$DATE_FORMAT_026 !Y2!MN0!D0 930113
LIB$DATE_FORMAT_027 /!Y2.!MN0.!D0 /93.01.13
LIB$DATE_FORMAT_028 !MN0/!D0/!Y4 01/13/1993
LIB$DATE_FORMAT_029 !MN0-!D0-!Y4 01-13-1993
LIB$DATE_FORMAT_030 !MN0.!D0.!Y4 01.13.1993
LIB$DATE_FORMAT_031 !MN0 !D0 !Y4 01 13 1993
LIB$DATE_FORMAT_032 !D0/!MN0/!Y4 13/01/1993
LIB$DATE_FORMAT_033 !D0-!MN0-!Y4 13-01-1993
LIB$DATE_FORMAT_034 !D0.!MN0.!Y4 13.01.1993
LIB$DATE_FORMAT_035 !D0 !MN0 !Y4 13 01 1993
LIB$DATE_FORMAT_036 !Y4/!MN0/!D0 1993/01/13
LIB$DATE_FORMAT_037 !Y4-!MN0-!D0 1993-01-13
LIB$DATE_FORMAT_038 !Y4.!MN0.!D0 1993.01.13
LIB$DATE_FORMAT_039 !Y4 !MN0 !D0 1993 01 13
LIB$DATE_FORMAT_040 !Y4!MN0!D0 19930113

Table 27–9 lists all predefined time format logical names, their formats, and
examples of the output generated using those formats.

Table 27–9 Predefined Output Time Formats


Time Format Logical Format Example
LIB$TIME_FORMAT_001 !H04:!M0:!S0.!C2 09:13:25.14
LIB$TIME_FORMAT_002 !H04:!M0:!S0 09:13:25
(continued on next page)

27–30 System Time Operations


System Time Operations
27.6 Date/Time Formatting Routines

Table 27–9 (Cont.) Predefined Output Time Formats


Time Format Logical Format Example

LIB$TIME_FORMAT_003 !H04.!M0.!S0 09.13.25


LIB$TIME_FORMAT_004 !H04 !M0 !S0 09 13 25
LIB$TIME_FORMAT_005 !H04:!M0 09:13
LIB$TIME_FORMAT_006 !H04.!M0 09.13
LIB$TIME_FORMAT_007 !H04 !M0 09 13
LIB$TIME_FORMAT_008 !HH4:!M0 9:13
LIB$TIME_FORMAT_009 !HH4.!M0 9.13
LIB$TIME_FORMAT_010 !HH4 !M0 9 13
LIB$TIME_FORMAT_011 !H02:!M0 !MIU 09:13 AM
LIB$TIME_FORMAT_012 !HH2:!M0 !MIU 9:13 AM
LIB$TIME_FORMAT_013 !H04!M0 0913
LIB$TIME_FORMAT_014 !H04H!M0m 09H13m
LIB$TIME_FORMAT_015 kl !H04.!M0 kl 09.13
LIB$TIME_FORMAT_016 !H04H!M0’ 09H13’
LIB$TIME_FORMAT_017 !H04.!M0 h 09.13 h
LIB$TIME_FORMAT_018 h !H04.!M0 h 09.13
LIB$TIME_FORMAT_019 !HH4 h !MM 9 h 13
LIB$TIME_FORMAT_020 !HH4 h !MM min !SS s 9 h 13 min 25 s

27.6.2.5 Specifying Formats at Compile Time


If an application reads text from internal storage or formats text for internal
storage or transmission, you should specify the language and format at compile
time. The routine LIB$INIT_DATE_TIME_CONTEXT allows the user to specify
the language and format at compile time by initializing the context area used by
LIB$FORMAT_DATE_TIME for output or LIB$CONVERT_DATE_STRING for
input with specific strings, instead of through logical name translations. Note
that when the text will be parsed by another program, LIB$INIT_DATE_TIME_
CONTEXT expects all required context information (including spellings) to be
specified. For applications where the context specifies a user’s preferred format
style, the spellings can be looked up from the logical name tables.
Only one context component can be initialized per call to LIB$INIT_DATE_
TIME_CONTEXT. Table 27–10 lists the available components and their number
of elements. (_ABB indicates an abbreviated version of the month and weekday
names.)

Table 27–10 Available Components for Specifying Formats at Compile Time


Available Component Number of Elements
LIB$K_MONTH_NAME 12
LIB$K_MONTH_NAME_ABB 12
LIB$K_FORMAT_MNEMONICS 9
(continued on next page)

System Time Operations 27–31


System Time Operations
27.6 Date/Time Formatting Routines

Table 27–10 (Cont.) Available Components for Specifying Formats at Compile


Time
Available Component Number of Elements

LIB$K_WEEKDAY_NAME 7
LIB$K_WEEKDAY_NAME_ABB 7
LIB$K_RELATIVE_DAY_NAME 3
LIB$K_MERIDIEM_INDICATOR 2
LIB$K_OUTPUT_FORMAT 2
LIB$K_INPUT_FORMAT 1
LIB$K_LANGUAGE 1

To specify the actual values for these elements, you must use an initialization
string in the following format:
"[delim][string-1][delim][string-2][delim]...[delim][string-n][delim]"
In this format, [-] is a delimiting character that is not in any of the strings, and
[string-n] is the spelling of the nth instance of the component.
For example, a string passed to this routine to specify the English spellings of the
abbreviated month names might be as follows:
"|JAN|FEB|MAR|APR|MAY|JUN
|JUL|AUG|SEP|OCT|NOV|DEC|"
The string must contain the exact number of elements for the associated
component; otherwise the error LIB$_NUMELEMENTS is returned. Note that
the string begins and ends with a delimiter. Thus, there is one more delimiter
than the number of string elements in the initialization string.
27.6.2.6 Specifying Input Format Mnemonics at Compile Time
To specify the input format mnemonics at compile time, the user must initialize
the component LIB$K_FORMAT_MNEMONICS with the appropriate values.
Table 27–11 lists the nine fields that must be initialized, in the appropriate order,
along with their default (English) values.

Table 27–11 Legible Format Mnemonics


Order Format Field Legible Mnemonic (Default)
1 Year YYYY
2 Numeric month MM
3 Numeric day DD
4 Hours (12- or 24-hour) HH
5 Minutes MM
6 Seconds SS
7 Fractional seconds CC
8 Meridiem indicator AM/PM
9 Alphabetic month MONTH

For example, the following is a valid definition of the component LIB$K_


FORMAT_MNEMONICS, using English as the natural language:

27–32 System Time Operations


System Time Operations
27.6 Date/Time Formatting Routines

|YYYY|MM|DD|HH|MM|SS|CC|AM/PM|MONTH|
If the user were entering the same string using Austrian as the natural language,
the definition of the component LIB$K_FORMAT_MNEMONICS would be as
follows:
|JJJJ|MM|TT|SS|MM|SS|HH| |MONAT|
27.6.2.7 Specifying Output Formats at Compile Time
To specify an output format at compile time, the user must preinitialize the
component LIB$K_OUTPUT_FORMAT. Two elements are associated with this
output format string. One describes the date format fields, the other the time
format fields. The order in which they appear in the string determines the order
in which they are output. A single space is inserted into the output stream
between the two elements, if the call to LIB$FORMAT_DATE_TIME specifies
that both be output. For example:
" | !DB-!MAAU-!Y4 | !H04:!M0:!S0.!C2 | "
(These mnemonics are listed in Table 27–6.) This format string represents the
format used by the $ASCTIM system service for outputting times. Note that the
middle delimiter is replaced by a space in the resultant output.
13-JAN-1993 14:54:09:24

27.6.3 Converting with the LIB$CONVERT_DATE_STRING Routine


The LIB$CONVERT_DATE_STRING routine converts an absolute date/time
string into an operating system internal format date/time quadword. You can
optionally specify which fields of the input string can be defaulted (using the
input-flags argument), and what the default values should be (using the
defaults argument). By default, the time fields can be defaulted but the date
fields cannot. Table 27–7 gives some examples of these default values.
You can use the optional defaulted-fields argument to LIB$CONVERT_
DATE_STRING to determine which input fields were defaulted. That is, the
defaulted-fields argument is a bit mask in which each set bit indicates that the
corresponding field was defaulted in the input date/time string.
If you want to use LIB$CONVERT_DATE_STRING to return the current time as
well as the current date, you can call the $NUMTIM system service and pass the
timbuf argument, which contains the current date and time, to LIB$CONVERT_
DATE_STRING as the defaults argument. This tells the LIB$CONVERT_
DATE_STRING routine to take the default values for the date and time fields
from the 7-word array returned by $NUMTIM.
LIV$CONVERT_DATE_STRING specifies 2-digit years from input by selecting
the current century as the default for the century portion of the date. This is true
when the !Y2 format is used. This selection may not be desirable for you since 00
would be interpreted as 1900 (and as 2000 on 1/1/2000).
A new format has been added so that you can select a new behavior for
LIB$CONVERT_DATE_STRING. You can use the Z format in every place the Y
format is used to represent years. The Z format acts exactly like the Y format
except for !Z2. Using !Z2 causes LIB$CONVERT_DATE_STRING to interpret a
2-digit year of 99 as 1999 and a 2-digit year of 01 as 2001. The transition year
is on a sliding scale determined by the current year minus 43. So if the current
year is 1999, the transition year is 56. A 2-digit year greater or equal to this
has a century of 1900 and a 2-digit year less than this has a century of 2000.
Thus, the year 60 would be 1960 and the year 50 would be 2050. You can use the

System Time Operations 27–33


System Time Operations
27.6 Date/Time Formatting Routines

!Z2 format either in the logical LIB$DT_INPUT_FORMAT, or in the init-string


parameter for a call to LIB$INIT_DATE_TIME_CONTEXT to establish the input
format for LIB$CONVERT_DATE_STRING. Below is a list of the new Z formats:

Date Explanation
!Z4 Year; 4 digits
!Z3 Year; 3 digits
!Z2 Year; 2 digits (New behavior for the LIB$CONVERT_DATE_STRING routine)
!Z1 Year; 1 digit

27.6.4 Retrieving with LIB$GET_DATE_FORMAT Routine


The LIB$GET_DATE_FORMAT routine enables you to retrieve information about
the currently selected input format. The string returned by LIB$GET_DATE_
FORMAT parallels the currently defined input format string, consisting of the
format punctuation (with most white space compressed) and legible mnemonics
representing the various format fields.
Based on the currently defined input date/time format, LIB$GET_DATE_
FORMAT returns a string comprised of the mnemonics that represent the current
format. These mnemonics are listed in Table 27–11.
Table 27–12 gives some examples of input format strings and their resultant
mnemonic strings (using English as the default language).

Table 27–12 Sample Input Format Strings


Sample Format String LIB$GET_DATE_FORMAT Value
!MAU !DD, !Y4 !H04:!M0:!S0:!C2 MONTH DD, YYYY4 HH:MM:SS:CC2
!MN0-!D0-!Y2 !H04:!M0:!S0.!C2 MM-DD-YYYY2 HH:MM:SS.CC2
!MN0/!D0/!Y2 !H02:!M0:!S0.!C2 !MIU MM/DD/YYYY2 HH:MM:SS.CC2 AM/PM

27.6.4.1 Using User-Defined Output Formats


In addition to the 40 date output formats and 20 time output formats, users
can define their own date and time output formats using the logical names
LIB$DATE_FORMAT_nnn and LIB$TIME_FORMAT_nnn, where nnn ranges
from 501 to 999. (That is, values of nnn from 001 to 500 are reserved for use by
Compaq Computer Corporation.) The mnemonics used to define output formats
are listed in Table 27–6.
User-defined output formats must be defined as executive-mode logicals, and
they must be defined in the table LNM$DT_FORMAT_TABLE. These formats are
normally defined from the site-specific startup command procedure. The following
example illustrates the steps the system manager must use to create a particular
output format using French as the language:
$ DEFINE/EXEC/TABLE=LNM$DT_FORMAT_TABLE LIB$DATE_FORMAT_501 -
_$ "!WL, le !DD !MAL !Y4"
$ DEFINE/EXEC/TABLE=LNM$DT_FORMAT_TABLE LIB$TIME_FORMAT_501 -
_$ "!H04 heures et !M0 minutes"

27–34 System Time Operations


System Time Operations
27.6 Date/Time Formatting Routines

After the system manager defines the desired formats, the user can access them
by using the following commands:
$ DEFINE SYS$LANGUAGE FRENCH
$ DEFINE LIB$DT_FORMAT LIB$DATE_FORMAT_501, LIB$TIME_FORMAT_501
After completing these steps, a program outputting the date and time provides
the following results:
mardi, le 20 janvier 1993 13 heures et 50 minutes
In addition to creating their own date and time formats, users can also define
their own language tables (provided they have the SYSNAM, SYSPRV and
CMEXEC privileges). To create a language table, a user must define all the
logical names required.
The following example defines a portion of the Dutch language table. This table
is included in its entirety in the set of predefined languages provided with the
international date/time formatting routines.
$ CREATE/NAME/PARENT=LNM$SYSTEM_DIRECTORY/EXEC/PROT=(S:RWED,G:R,W:R) -
_$ LNM$LANGUAGE_DUTCH
$ DEFINE/EXEC/TABLE=LNM$LANGUAGE_DUTCH LIB$WEEKDAYS_L -
_$ "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", -
_$ "zaterdag", "zondag"
$ DEFINE/EXEC/TABLE=LNM$LANGUAGE_DUTCH LIB$WEEKDAY_ABBREVIATIONS_L -
_$ "maa", "din", "woe", "don", "vri", "zat", "zon"
$ DEFINE/EXEC/TABLE=LNM$LANGUAGE_DUTCH LIB$MONTHS_L "januari", -
_$ "februari", "maart", "april", "mei", "juni", "juli", "augustus", -
_$ "september", "oktober", "november", "december"
$ DEFINE/EXEC/TABLE=LNM$LANGUAGE_DUTCH LIB$MONTH_ABBREVIATIONS_L -
_$ "jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", -
_$ "okt", "nov", "dec"
$ DEFINE/EXEC/TABLE=LNM$LANGUAGE_AUSTRIAN LIB$RELATIVE_DAYS_L -
_$ "gisteren", "vandaag", "morgen"
All logical names that are used to build a language are as follows:

LIB$WEEKDAYS_[U | L | C]
These logical names supply the names of the weekdays, spelled out in full
(uppercase, lowercase, or mixed case). Weekdays must be defined in order,
starting with Monday.

LIB$WEEKDAY_ABBREVIATIONS_[U | L | C]
These logical names supply the abbreviated names of the weekdays (uppercase,
lowercase, or mixed case). Weekday abbreviations must be defined in order,
starting with Monday.

LIB$MONTHS_[U | L | C]
These logical names supply the names of the months, spelled out in full
(uppercase, lowercase, or mixed case). Months must be defined in order, starting
with January.

LIB$MONTH_ABBREVIATIONS_[U | L | C]
These logical names supply the abbreviated names of the months (uppercase,
lowercase, or mixed case). Month abbreviations must be defined in order, starting
with January.

System Time Operations 27–35


System Time Operations
27.6 Date/Time Formatting Routines

LIB$MI_[U | L | C]
These logical names supply the spellings for the meridiem indicators (uppercase,
lowercase, or mixed case). Meridiem indicators must be defined in order; the first
indicator represents the hours 0:00:0.0 to 11:59:59.99, and the second indicator
represents the hours 12:00:00.00 to 23:59:59.99.

LIB$RELATIVE_DAYS_[U | L | C]
These logical names supply the spellings for the relative days (uppercase,
lowercase, or mixed case). Relative days must be defined in order: yesterday,
today, and tomorrow, respectively.

LIB$FORMAT_MNEMONICS
This logical name supplies the abbreviations for the appropriate format
mnemonics. That is, the information supplied in this logical name is used
to specify a desired input format in the user-defined language. The format
mnemonics, along with their English values, are listed in the order in which they
must be defined.
1. Year (YYYY)
2. Numeric month (MM)
3. Day of the month (DD)
4. Hour of the day (HH)
5. Minutes of the hour (MM)
6. Seconds of the minute (SS)
7. Parts of the second (CC)
8. Meridiem indicator (AM/PM)
9. Alphabetic month (MONTH)
The English definition of LIB$FORMAT_MNEMONIC is therefore as follows:
$ DEFINE/EXEC/TABLE=LNM$LANGUAGE_ENGLISH LIB$FORMAT_MNEMONICS -
_$ "YYYY", "MM", "DD", "HH", "MM", "SS", "CC", "AM/PM ", "MONTH"

27.7 Coordinated Universal Time Format


This section provides information about VAX systems that supply system base
date and time format other than the Smithsonian base date and time system.
The other base date and time format system is the Coordinated Universal Time
(UTC) system. UTC time is determined by a network of atomic clocks that are
maintained by standard bodies in several countries. Formerly, applications that
spanned time zones often used Greenwich Mean Time (GMT) as a time reference.
UTC binary timestamps are opaque octawords of 128-bits that contain several
fields. Important fields of the UTC format are an absolute time value, a time
differential factor (TDF) that contains the offset of the host node’s clock from
UTC, and an inaccuracy, or tolerance, that can be applied to the absolute time
value. Unlike UTC, the operating system binary date and timestamps in the
Smithsonian base date and time format represent only the local time of the host
node; they do not contain TDF values or inaccuracy values.

27–36 System Time Operations


System Time Operations
27.7 Coordinated Universal Time Format

The UTC system services allow applications to gain the benefits of a Coordinated
Universal Time reference. The UTC system services enable applications to
reference a common time standard independent of the host’s location and local
date and time value.
By calling the UTC system services, applications can perform the following
functions:
• Obtain binary representations of UTC in the binary UTC format
• Convert the binary operating system format date and time to binary
UTC-format date and time
• Convert binary UTC-format date and time to the binary operating system
date and time
• Convert ASCII-format date and time to binary UTC-format date and time
• Convert binary UTC-format date and time to ASCII-format date and time
System services that implement the UTC-format date and time are:
• SYS$ASCUTC—Convert UTC to ASCII
• SYS$BINUTC—Convert ASCII String to UTC Binary Time
• SYS$GETUTC—Get UTC Time
• SYS$NUMUTC—Convert UTC Time to Numeric Components
• SYS$TIMCON—Time Converter
For specific implementation information about the UTC system services, see the
OpenVMS System Services Reference Manual.

System Time Operations 27–37


28
File Operations

This chapter describes file operations that support file input/output (I/O) and
file I/O instructions of the operating system’s high-level languages. This chapter
contains the following sections:
Section 28.1 describes file attributes.
Section 28.2 describes strategies to access files.
Section 28.3 describes protection and access of files.
Section 28.4 describes file mapping.
Section 28.5 describes how to open and update a sequential file.
Section 28.6 describes using the Fortran user-open routines.
I/O statements transfer data between records in files and variables in your
program. The I/O statement determines the operation to be performed; the
I/O control list specifies the file, record, and format attributes; and the I/O list
contains the variables to be acted upon.

Note
Some confusion might arise between records in a file and record variables.
Where this chapter refers to a record variable, the term record variable is
used; otherwise, record refers to a record in a file.

28.1 File Attributes


Before writing a program that accesses a data file, you must know the attributes
of the file and the order of the data. To determine this information, see your
language-specific programming manual.
File attributes (organization, record structure, and so on) determine how data is
stored and accessed. Typically, the attributes are specified by keywords when you
open the data file.
Ordering of the data within a file is not important mechanically. However, if you
attempt to read data without knowing how it is ordered within the file, you are
likely to read the wrong data; if you attempt to write data without knowing how
it is ordered within the file, you are likely to corrupt existing data.

File Operations 28–1


File Operations
28.1 File Attributes

28.1.1 Specifying File Attributes


You can specify large sets of attributes using the File Definition Language utility
(FDL). You can specify all of the file attributes using OpenVMS RMS in a user-
open routine (see Section 28.6). Typically, you need only programming language
file specifiers. Use FDL only when language specifiers are unavailable.
Refer to the appropriate programming language reference manual for information
about the use of language specifiers.
For complete information about how to use FDL, see the OpenVMS Record
Management Utilities Reference Manual.

28.1.2 Using Extended File Specifications (Alpha Only)


On Alpha systems running OpenVMS V7.2, extended file specifications support
disk file specifications of greater length, a larger character set, and deeper
directories than was supported on previous versions of Alpha OpenVMS. For
information about extended file specifications, see the OpenVMS Guide to
Extended File Specifications and the Guide to OpenVMS File Applications for a
description of these features.

28.2 File Access Strategies


When determining the file attributes and order of your data file, consider how you
plan to access that data. File access strategies fall into the following categories:
• Complete access
If your program processes all or most of the data in the file and especially if
many references are made to the data, you should read the entire file into
memory. Put each record in its own variable or set of variables.
If your program is larger than the amount of virtual memory available
(including the additional memory you get by using memory allocation
routines), you must declare fewer variables and process your file in pieces. To
determine the size of your program, add the number of bytes in each program
section. The DCL command LINK/MAP produces a listing that includes the
length of each program section (PSECT).
• Record-by-record access
If your program accesses records one after another, or if you cannot fit the
entire file into memory, you should read one record into memory at a time.
• Discrete records access
If your program processes only a selection of the file’s records, you should
read only the necessary records into memory.
• Sequential and indexed file access
If your program demands speed and needs to conserve disk space, use an
unformatted sequential file. Use indexed files either to process selected
sets of records or to access records directly. Use either a sequential file
with fixed-length records, a relative file, or an indexed file to access records
directly.

28–2 File Operations


File Operations
28.3 File Protection and Access

28.3 File Protection and Access


Files are owned by the process that creates them and receive the default
protection of the creating process. To create a file with ownership and protection
other than the default, use the File Definition Language (FDL) attributes
OWNER and PROTECTION in the file.

28.3.1 Read-Only Access


By default, the user of your program must have write access to a file in order
for your program to open that file. However, if you specify use of the Fortran
READONLY specifier when opening the file, the user needs only read access to
the file to open it. The READONLY specifier does not set the protection on a file.
The user cannot write to a file opened with the READONLY specifier.

28.3.2 Shared Access


The Fortran specifier READONLY and the SHARED specifier allow multiple
processes to open the same file simultaneously, provided that each process uses
one of these specifiers when opening the file. The READONLY specifier allows
the process read access to the file; the SHARED specifier allows other processes
read and write access to the file. If a process opens the file without specifying
READONLY or SHARED, no other process can open that file even by specifying
READONLY or SHARED.
In the following Fortran segment, if the read operation indicates that the record
is locked, the read operation is repeated. You should not attempt to read a locked
record without providing a delay (in this example, the call to ERRSNS) to allow
the other process time to complete its operation and unlock the record.
! Status variables and values
INTEGER STATUS,
2 IOSTAT,
2 IO_OK
PARAMETER (IO_OK = 0)
INCLUDE ’($FORDEF)’
! Logical unit number
INTEGER LUN /1/
! Record variables
INTEGER LEN
CHARACTER*80 RECORD
.
.
.
READ (UNIT = LUN,
2 FMT = ’(Q,A)’
2 IOSTAT = IOSTAT) LEN, RECORD (1:LEN)
IF (IOSTAT .NE. IO_OK) THEN
CALL ERRSNS (,,,,STATUS)
IF (STATUS .EQ. FOR$_SPERECLOC) THEN
DO WHILE (STATUS .EQ. FOR$_SPERECLOC)
READ (UNIT = LUN,
2 FMT = ’(Q,A)’
2 IOSTAT = IOSTAT) LEN, RECORD(1:LEN)
IF (IOSTAT .NE. IO_OK) THEN
CALL ERRSNS (,,,,STATUS)
IF (STATUS .NE. FOR$_SPERECLOC) THEN
CALL LIB$SIGNAL(%VAL(STATUS))
END IF
END IF
END DO
ELSE
CALL LIB$SIGNAL (%VAL(STATUS))

File Operations 28–3


File Operations
28.3 File Protection and Access

END IF
END IF
.
.
.
In Fortran, each time you access a record in a shared file, that record is
automatically locked either until you perform another I/O operation on the
same logical unit, or until you explicitly unlock the record using the UNLOCK
statement. If you plan to modify a record, you should do so before unlocking it;
otherwise, you should unlock the record as soon as possible.

28.4 File Access and Mapping


To copy an entire data file from the disk to program variables and back again,
either use language I/O statements to read and write the data or use the Create
and Map Section (SYS$CRMPSC) system service to map the data. Often times,
mapping the file is faster than reading it. However, a mapped file usually uses
more virtual memory than one that is read using language I/O statements. Using
I/O statements, you have to store only the data that you have entered. Using
SYS$CRMPSC, you have to initialize the database and store the entire structure
in virtual memory including the parts that do not yet contain data.

28.4.1 Using SYS$CRMPSC


Mapping a file means associating each byte of the file with a byte of program
storage. You access data in a mapped file by referencing the program storage;
your program does not use I/O statements.

Note
Files created using OpenVMS RMS typically contain control information.
Unless you are familiar with the structure of these files, do not attempt
to map one. The best practice is to map only those files that have been
created as the result of mapping.

To map a file, perform the following operations:


1. Place the program variables for the data in a common block. Page align
the common block at link time by specifying an options file containing the
following link option for VAX and Alpha systems:
For VAX systems, specify the following:
PSECT_ATTR = name, PAGE

For Alpha systems, specify the following:


PSECT_ATTR = name, solitary

The variable name is the name of the common block.


Within the common block, you should specify the data in order from most
complex to least complex (high to low rank), with character data last. This
naturally aligns the data, thus preventing troublesome page breaks in virtual
memory.

28–4 File Operations


File Operations
28.4 File Access and Mapping

2. Open the data file using a user-open routine. The user-open routine must
open the file for user I/O (as opposed to OpenVMS RMS I/O) and return the
channel number on which the file is opened.
3. Map the data file to the common block.
4. Process the records using the program variables in the common block.
5. Free the memory used by the common block, forcing modified data to be
written back to the disk file.
Do not initialize variables in a common block that you plan to map; the initial
values will be lost when SYS$CRMPSC maps the common block.
28.4.1.1 Mapping a File
The format for SYS$CRMPSC is as follows:
SYS$CRMPSC [inadr],[retadr],[acmode],[flags],[gsdnam],[ident],[relpag],
[chan], [pagcnt],[vbn],[prot],[pfc]
For a complete description of the SYS$CRMPSC system service, see the
OpenVMS System Services Reference Manual.
Starting and Ending Addresses of the Mapped Section
On VAX systems, specify the location of the first variable in the common block as
the value of the first array element of the array passed by the inadr argument.
Specify the location of the last variable in the common block as the value of the
second array element.
On Alpha systems, specify the location of the first variable in the common block
as the value of the first array element of the array passed by the inadr argument;
the second array element must be the address of the last variable in the common
block, which is derived by performing a logical OR with the value of the size of a
memory page minus 1. The size of the memory page can be retrieved by a call to
the SYS$GETSYI system service.
If the first variable in the common block is an array or string, the first variable in
the common block is the first element of that array or string. If the last variable
in the common block is an array or string, the last variable in the common block
is the last element in that array or string.
Returning the Location of the Mapped Section
On VAX systems, SYS$CRMPSC returns the location of the first and last
elements mapped in the retadr argument. The value returned as the starting
virtual address should be the same as the starting address passed to the inadr
argument. The value returned as the ending virtual address should be equal to
or slightly more than (within 512 bytes, or 1 block) the value of the ending virtual
address passed to the inadr argument.
On Alpha systems, SYS$CRMPSC returns the location of the first and last
elements mapped in the retadr argument. The value returned as the starting
virtual address should be the same as the starting address passed to the inadr
argument. The value returned as the ending virtual address should be equal to
or slightly less than (within a single page size) the value of the ending virtual
address passed to the inadr argument.
If the first element is in error, you probably forgot to page-align the common block
containing the mapped data.
If the second element is in error, you were probably creating a new data file and
forgot to specify the size of the file in your program (see Section 28.4.1.3).

File Operations 28–5


File Operations
28.4 File Access and Mapping

Using Private Sections


Specify SEC$M_WRT for the flags to indicate that the section is writable. If
the file is new, also specify SEC$M_DZRO to indicate that the section should be
initialized to zero.
Obtaining the Channel Number
You must use a user-open routine to get the channel number (see
Section 28.4.1.2). Pass the channel number to the chan argument.
On VAX systems, Example 28–1 maps a data file consisting of one longword and
three real arrays to the INC_DATA common block. The options file INCOME.OPT
page-aligns the INC_DATA common block.
If SYS$CRMPSC returns a status of SS$_IVSECFLG and you have correctly
specified the flags in the mask argument, check to see if you are passing a
channel number of 0.

Example 28–1 Mapping a Data File to the Common Block on a VAX System
!INCOME.OPT
PSECT_ATTR = INC_DATA, PAGE
INCOME.FOR
! Declare variables to hold statistics
REAL PERSONS_HOUSE (2048),
2 ADULTS_HOUSE (2048),
2 INCOME_HOUSE (2048)
INTEGER TOTAL_HOUSES
! Declare section information
! Data area
COMMON /INC_DATA/ PERSONS_HOUSE,
2 ADULTS_HOUSE,
2 INCOME_HOUSE,
2 TOTAL_HOUSES
! Addresses
INTEGER ADDR(2),
2 RET_ADDR(2)
! Section length
INTEGER SEC_LEN
! Channel
INTEGER*2 CHAN,
2 GARBAGE
COMMON /CHANNEL/ CHAN,
2 GARBAGE
! Mask values
INTEGER MASK
INCLUDE ’($SECDEF)’
! User-open routines
INTEGER UFO_OPEN,
2 UFO_CREATE
EXTERNAL UFO_OPEN,
2 UFO_CREATE
! Declare logical unit number
INTEGER STATS_LUN
! Declare status variables and values
INTEGER STATUS,
2 IOSTAT,
2 IO_OK
PARAMETER (IO_OK = 0)
INCLUDE ’($FORDEF)’
EXTERNAL INCOME_BADMAP
! Declare logical for INQUIRE statement
LOGICAL EXIST

(continued on next page)

28–6 File Operations


File Operations
28.4 File Access and Mapping

Example 28–1 (Cont.) Mapping a Data File to the Common Block on a VAX
System
! Declare subprograms invoked as functions
INTEGER LIB$GET_LUN,
2 SYS$CRMPSC,
2 SYS$DELTVA,
2 SYS$DASSGN
! Get logical unit number for STATS.SAV
STATUS = LIB$GET_LUN (STATS_LUN)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
INQUIRE (FILE = ’STATS.SAV’,
2 EXIST = EXIST)
IF (EXIST) THEN
OPEN (UNIT=STATS_LUN,
2 FILE=’STATS.SAV’,
2 STATUS=’OLD’,
2 USEROPEN = UFO_OPEN)
MASK = SEC$M_WRT
ELSE
! If STATS.SAV does not exist, create new database
MASK = SEC$M_WRT .OR. SEC$M_DZRO
SEC_LEN =
! (address of last - address of first + size of last + 511)/512
2 ( (%LOC(TOTAL_HOUSES) - %LOC(PERSONS_HOUSE(1)) + 4 + 511)/512 )
OPEN (UNIT=STATS_LUN,
2 FILE=’STATS.SAV’,
2 STATUS=’NEW’,
2 INITIALSIZE = SEC_LEN,
2 USEROPEN = UFO_CREATE)
END IF
! Free logical unit number and map section
CLOSE (STATS_LUN)
! ********
! MAP DATA
! ********
! Specify first and last address of section
ADDR(1) = %LOC(PERSONS_HOUSE(1))
ADDR(2) = %LOC(TOTAL_HOUSES)
! Map the section
STATUS = SYS$CRMPSC (ADDR,
2 RET_ADDR,
2 ,
2 %VAL(MASK),
2 ,,,
2 %VAL(CHAN),
2 ,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
! Check for correct mapping
IF (ADDR(1) .NE. RET_ADDR (1))
2 CALL LIB$SIGNAL (%VAL (%LOC(INCOME_BADMAP)))
.
.
.
! Reference data using the
! data structures listed
! in the common block
.
.
.
! Close and update STATS.SAV
STATUS = SYS$DELTVA (RET_ADDR,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
STATUS = SYS$DASSGN (%VAL(CHAN))
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
END

(continued on next page)

File Operations 28–7


File Operations
28.4 File Access and Mapping

Example 28–1 (Cont.) Mapping a Data File to the Common Block on a VAX
System

Example 28–2 shows the code for performing the same functions as Example 28–1
but in an Alpha system’s environment.

Example 28–2 Mapping a Data File to the Common Block on an Alpha System
!INCOME.OPT
PSECT_ATTR = INC_DATA, SOLITARY, SHR, WRT
INCOME.FOR
! Declare variables to hold statistics
REAL PERSONS_HOUSE (2048),
2 ADULTS_HOUSE (2048),
2 INCOME_HOUSE (2048)
INTEGER TOTAL_HOUSES, STATUS
! Declare section information
! Data area
COMMON /INC_DATA/ PERSONS_HOUSE,
2 ADULTS_HOUSE,
2 INCOME_HOUSE,
2 TOTAL_HOUSES
! Addresses
INTEGER ADDR(2),
2 RET_ADDR(2)
! Section length
INTEGER SEC_LEN
! Channel
INTEGER*2 CHAN,
2 GARBAGE
COMMON /CHANNEL/ CHAN,
2 GARBAGE
! Mask values
INTEGER MASK
INCLUDE ’($SECDEF)’
! User-open routines
INTEGER UFO_OPEN,
2 UFO_CREATE
EXTERNAL UFO_OPEN,
2 UFO_CREATE
! Declare logical unit number
INTEGER STATS_LUN
! Declare status variables and values
INTEGER STATUS,
2 IOSTAT,
2 IO_OK
PARAMETER (IO_OK = 0)
INCLUDE ’($FORDEF)’
EXTERNAL INCOME_BADMAP
! Declare logical for INQUIRE statement
LOGICAL EXIST
! Declare subprograms invoked as functions
INTEGER LIB$GET_LUN,
2 SYS$CRMPSC,
2 SYS$DELTVA,
2 SYS$DASSGN
! Get logical unit number for STATS.SAV
STATUS = LIB$GET_LUN (STATS_LUN)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

(continued on next page)

28–8 File Operations


File Operations
28.4 File Access and Mapping

Example 28–2 (Cont.) Mapping a Data File to the Common Block on an Alpha
System
INQUIRE (FILE = ’STATS.SAV’,
2 EXIST = EXIST)
IF (EXIST) THEN
OPEN (UNIT=STATS_LUN,
2 FILE=’STATS.SAV’,
2 STATUS=’OLD’,
2 USEROPEN = UFO_OPEN)
MASK = SEC$M_WRT
ELSE
! If STATS.SAV does not exist, create new database
MASK = SEC$M_WRT .OR. SEC$M_DZRO
SEC_LEN =
! (address of last - address of first + size of last + 511)/512
2 ( (%LOC(TOTAL_HOUSES) - %LOC(PERSONS_HOUSE(1)) + 4 + 511)/512 )
OPEN (UNIT=STATS_LUN,
2 FILE=’STATS.SAV’,
2 STATUS=’NEW’,
2 INITIALSIZE = SEC_LEN,
2 USEROPEN = UFO_CREATE)
END IF
! Free logical unit number and map section
CLOSE (STATS_LUN)
! ********
! MAP DATA
! ********
STATUS = LIB$GETSYI(SYI$_PAGE_SIZE, PAGE_MAX,,,,)
IF (.NOT. STATUS) CALL LIB$STOP (%VAL (STATUS))
! Specify first and last address of section
ADDR(1) = %LOC(PERSONS_HOUSE(1))
! Section will always be smaller than page_max bytes
ADDR(2) = ADDR(1) + PAGE_MAX -1
! Map the section
STATUS = SYS$CRMPSC (ADDR,
2 RET_ADDR,
2 ,
2 %VAL(MASK),
2 ,,,
2 %VAL(CHAN),
2 ,,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
! Check for correct mapping
IF (ADDR(1) .NE. RET_ADDR (1))
2 CALL LIB$SIGNAL (%VAL (%LOC(INCOME_BADMAP)))
.
.
.
! Reference data using the
! data structures listed
! in the common block
.
.
.
! Close and update STATS.SAV
STATUS = SYS$DELTVA (RET_ADDR,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
STATUS = SYS$DASSGN (%VAL(CHAN))
IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
END

File Operations 28–9


File Operations
28.4 File Access and Mapping

28.4.1.2 Using the User-Open Routine


When you open a file for mapping in Fortran, for example, you must specify
a user-open routine (Section 28.6 discusses user-open routines) to perform the
following operations:
1. Set the user-file open bit (FAB$V_UFO) in the file access block (FAB) options
mask.
2. Open the file using SYS$OPEN for an existing file or SYS$CREATE for a new
file. (Do not invoke SYS$CONNECT if you have set the user-file open bit.)
3. Return the channel number to the program unit that started the OPEN
operation. The channel number is in the additional status longword of the
FAB (FAB$L_STV) and must be returned in a common block.
4. Return the status of the open operation (SYS$OPEN or SYS$CREATE) as the
value of the user-open routine.
After setting the user-file open bit in the FAB options mask, you cannot use
language I/O statements to access data in that file. Therefore, you should free the
logical unit number associated with the file. The file is still open. You access the
file with the channel number.
Example 28–3 shows a user-open routine invoked by the sample program in
Section 28.4.1.1 if the file STATS.SAV exists. (If STATS.SAV does not exist, the
user-open routine must invoke SYS$CREATE rather than SYS$OPEN.)

Example 28–3 Using a User-Open Routine


!UFO_OPEN.FOR
INTEGER FUNCTION UFO_OPEN (FAB,
2 RAB,
2 LUN)
! Include Open VMS RMS definitions
INCLUDE ’($FABDEF)’
INCLUDE ’($RABDEF)’
! Declare dummy arguments
RECORD /FABDEF/ FAB
RECORD /RABDEF/ RAB
INTEGER LUN
! Declare channel
INTEGER*4 CHAN
COMMON /CHANNEL/ CHAN
! Declare status variable
INTEGER STATUS
! Declare system procedures
INTEGER SYS$OPEN
! Set useropen bit in the FAB options longword
FAB.FAB$L_FOP = FAB.FAB$L_FOP .OR. FAB$M_UFO
! Open file
STATUS = SYS$OPEN (FAB)
! Read channel from FAB status word
CHAN = FAB.FAB$L_STV
! Return status of open operation
UFO_OPEN = STATUS
END

28–10 File Operations


File Operations
28.4 File Access and Mapping

28.4.1.3 Initializing a Mapped Database


The first time you map a file you must perform the following operations in
addition to those listed at the beginning of Section 28.4.1:
1. Specify the size of the file—SYS$CRMPSC maps data based on the size of the
file. Therefore, when creating a file that is to be mapped, you must specify in
your program a file large enough to contain all of the expected data. Figure
the size of your database as follows:
• Find the size of the common block (in bytes)—Subtract the location of the
first variable in the common block from the location of the last variable in
the common block and then add the size of the last element.
• Find the number of blocks in the common block—Add 511 to the size and
divide the result by 512 (512 bytes = 1 block).
2. Initialize the file when you map it—The blocks allocated to a file might not be
initialized and therefore contain random data. When you first map the file,
you should initialize the mapped area to zeros by setting the SEC$V_DZRO
bit in the mask argument of SYS$CRMPSC.
The user-open routine for creating a file is the same as the user-open routine for
opening a file except that SYS$OPEN is replaced by SYS$CREATE.
28.4.1.4 Saving a Mapped File
To close a data file that was opened for user I/O, you must deassign the I/O
channel assigned to that file. Before you can deassign a channel assigned to a
mapped file, you must delete the virtual memory associated with the file (the
memory used by the common block). When you delete the virtual memory used
by a mapped file, any changes made while the file was mapped are written back
to the disk file. Use the Delete Virtual Address Space (SYS$DELTVA) system
service to delete the virtual memory used by a mapped file. Use the Deassign I/O
Channel (SYS$DASSGN) system service to deassign the I/O channel assigned to
a file.
The program segment shown in Example 28–4 closes a mapped file, automatically
writing any modifications back to the disk. To ensure that the proper locations
are deleted, pass SYS$DELTVA the addresses returned to your program by
SYS$CRMPSC rather than the addresses you passed to SYS$CRMPSC. If you
want to save modifications made to the mapped section without closing the
file, use the Update Section File on Disk (SYS$UPDSEC) system service. To
ensure that the proper locations are updated, pass SYS$UPDSEC the addresses
returned to your program by SYS$CRMPSC rather than the addresses you
passed to SYS$CRMPSC. Typically, you want to wait until the update operation
completes before continuing program execution. Therefore, use the efn argument
of SYS$UPDSEC to specify an event flag to be set when the update is complete,
and wait for the system service to complete before continuing. For a complete
description of the SYS$DELTVA, SYS$DASSGN, and SYS$UPDSEC system
services, see the OpenVMS System Services Reference Manual.

File Operations 28–11


File Operations
28.4 File Access and Mapping

Example 28–4 Closing a Mapped File


! Section address
INTEGER*4 ADDR(2),
2 RET_ADDR(2)
! Event flag
INTEGER*4 FLAG
! Status block
STRUCTURE /IO_BLOCK/
INTEGER*2 IOSTAT,
2 HARDWARE
INTEGER*4 BAD_PAGE
END STRUCTURE
RECORD /IO_BLOCK/ IOSTATUS
.
.
.
! Get an event flag
STATUS = LIB$GET_EF (FLAG)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Update the section
STATUS = SYS$UPDSEC (RET_ADDR,
2 ,,,
2 %VAL(FLAG)
2 ,
2 IOSTATUS,,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Wait for section to be updated
STATUS = SYS$SYNCH (%VAL(FLAG),
2 IOSTATUS)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
.
.
.

28.5 Opening and Updating a Sequential File


This section provides an example, written in Compaq Fortran, of how to open and
update a sequential file on a VAX system. A sequential file consists of records
arranged one after the other in the order in which they are written to the file.
Records can only be added to the end of the file. Typically, sequential files are
accessed sequentially.
Creating a Sequential File
To create a sequential file, use the OPEN statement and specify the following
keywords and keyword values:
• STATUS =’NEW’
• ACCESS = ’SEQUENTIAL’
• ORGANIZATION = ’SEQUENTIAL’
The file structure keyword ORGANIZATION also accepts the value ’INDEXED’
or ’RELATIVE’.

28–12 File Operations


File Operations
28.5 Opening and Updating a Sequential File

Example 28–5 creates a sequential file of fixed-length records.

Example 28–5 Creating a Sequential File of Fixed-Length Records


.
.
.
INTEGER STATUS,
2 LUN,
2 LIB$GET_INPUT,
2 LIB$GET_LUN,
2 STR$UPCASE
INTEGER*2 FN_SIZE,
2 REC_SIZE
CHARACTER*256 FILENAME
CHARACTER*80 RECORD
! Get file name
STATUS = LIB$GET_INPUT (FILENAME,
2 ’File name: ’,
2 FN_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Get free unit number
STATUS = LIB$GET_LUN (LUN)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Open the file
OPEN (UNIT = LUN,
2 FILE = FILENAME (1:FN_SIZE),
2 ORGANIZATION = ’SEQUENTIAL’,
2 ACCESS = ’SEQUENTIAL’,
2 RECORDTYPE = ’FIXED’,
2 FORM = ’UNFORMATTED’,
2 RECL = 20,
2 STATUS = ’NEW’)
! Get the record input
STATUS = LIB$GET_INPUT (RECORD,
2 ’Input: ’,
2 REC_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
DO WHILE (REC_SIZE .NE. 0)
! Convert to uppercase
STATUS = STR$UPCASE (RECORD,RECORD)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
WRITE (UNIT=LUN) RECORD(1:REC_SIZE)
! Get more record input
STATUS = LIB$GET_INPUT (RECORD,
2 ’Input: ’,
2 REC_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
END DO
END

Updating a Sequential File


To update a sequential file, read each record from the file, update it, and write it
to a new sequential file. Updated records cannot be written back as replacement
records for the same sequential file from which they were read.
Example 28–6 updates a sequential file, giving the user the option of modifying
a record before writing it to the new file. The same file name is used for both
files; because the new update file was opened after the old file, the new file has a
higher version number.

File Operations 28–13


File Operations
28.5 Opening and Updating a Sequential File

Example 28–6 Updating a Sequential File


.
.
.
INTEGER STATUS,
2 LUN1,
2 LUN2,
2 IOSTAT
INTEGER*2 FN_SIZE
CHARACTER*256 FILENAME
CHARACTER*80 RECORD
CHARACTER*80 NEW_RECORD
INCLUDE ’($FORDEF)’
INTEGER*4 LIB$GET_INPUT,
2 LIB$GET_LUN,
2 STR$UPCASE
! Get file name
STATUS = LIB$GET_INPUT (FILENAME,
2 ’File name: ’,
2 FN_SIZE)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Get free unit number
STATUS = LIB$GET_LUN (LUN1)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Open the old file
OPEN (UNIT=LUN1,
2 FILE=FILENAME (1:FN_SIZE),
2 ORGANIZATION=’SEQUENTIAL’,
2 ACCESS=’SEQUENTIAL’,
2 RECORDTYPE=’FIXED’,
2 FORM=’UNFORMATTED’,
2 RECL=20,
2 STATUS=’OLD’)
! Get free unit number
STATUS = LIB$GET_LUN (LUN2)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Open the new file
OPEN (UNIT=LUN2,
2 FILE=FILENAME (1:FN_SIZE),
2 ORGANIZATION=’SEQUENTIAL’,
2 ACCESS=’SEQUENTIAL’,
2 RECORDTYPE=’FIXED’,
2 FORM=’UNFORMATTED’,
2 RECL=20,
2 STATUS=’NEW’)
! Read a record from the old file
READ (UNIT=LUN1,
2 IOSTAT=IOSTAT) RECORD
IF (IOSTAT .NE. IOSTAT_OK) THEN
CALL ERRSNS (,,,,STATUS)
IF (STATUS .NE. FOR$_ENDDURREA) THEN
CALL LIB$SIGNAL (%VAL(STATUS))
END IF
END IF
DO WHILE (STATUS .NE. FOR$_ENDDURREA)
TYPE *, RECORD

(continued on next page)

28–14 File Operations


File Operations
28.5 Opening and Updating a Sequential File

Example 28–6 (Cont.) Updating a Sequential File

! Get record update


STATUS = LIB$GET_INPUT (NEW_RECORD,
2 ’Update: ’)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Convert to uppercase
STATUS = STR$UPCASE (NEW_RECORD,
2 NEW_RECORD)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
! Write unchanged record or updated record
IF (NEW_RECORD .EQ. ’ ’ ) THEN
WRITE (UNIT=LUN2) RECORD
ELSE
WRITE (UNIT=LUN2) NEW_RECORD
END IF
! Read the next record
READ (UNIT=LUN1,
2 IOSTAT=IOSTAT) RECORD
IF (IOSTAT .NE. IOSTAT_OK) THEN
CALL ERRSNS (,,,,STATUS)
IF (STATUS .NE. FOR$_ENDDURREA) THEN
CALL LIB$SIGNAL (%VAL(STATUS))
END IF
END IF
END DO
END

28.6 User-Open Routines


A user-open routine in Fortran, for example, gives you direct access to the
file access block (FAB) and record access block (RAB) (the OpenVMS RMS
structures that define file characteristics). Use a user-open routine to specify file
characteristics that are otherwise unavailable from your programming language.
When you specify a user-open routine, you open the file rather than allow the
program to open the file for you. Before passing the FAB and RAB to your
user-open routine, any default file characteristics and characteristics that can
be specified by keywords in the programming language are set. Your user-open
routine should not set or modify such file characteristics because the language
might not be aware that you have set the characteristics and might not perform
as expected.

28.6.1 Opening a File


Section 28.4.1.2 provides guidelines on opening a file with a user-open routine.
This section provides an example of a Fortran user-open routine.
28.6.1.1 Specifying USEROPEN
To open a file with a user-open routine, include the USEROPEN specifier in the
Fortran OPEN statement. The value of the USEROPEN specifier is the name
of the routine (not a character string containing the name). Declare the user-
open routine as an INTEGER*4 function. Because the user-open routine name is
specified as an argument, it must be declared in an EXTERNAL statement.

File Operations 28–15


File Operations
28.6 User-Open Routines

The following statement instructs Fortran to open SECTION.DAT using the


routine UFO_OPEN:
! Logical unit number
INTEGER LUN
! Declare user-open routine
INTEGER UFO_OPEN
EXTERNAL UFO_OPEN
.
.
.
OPEN (UNIT = LUN,
2 FILE = ’SECTION.DAT’,
2 STATUS = ’OLD’,
2 USEROPEN = UFO_OPEN)
.
.
.
28.6.1.2 Writing the User-Open Routine
Write a user-open routine as an INTEGER function that accepts three dummy
arguments:
• FAB address—Declare this argument as a RECORD variable. Use
the record structure FABDEF defined in the $FABDEF module of
SYS$LIBRARY:FORSYSDEF.TLB.
• RAB address—Declare this argument as a RECORD variable. Use
the record structure RABDEF defined in the $RABDEF module of
SYS$LIBRARY:FORSYSDEF.TLB.
• Logical unit number—Declare this argument as an INTEGER.
A user-open routine must perform at least the following operations. In addition,
before opening the file, a user-open routine usually adjusts one or more fields in
the FAB or the RAB or in both.
• Opens the file—To open the file, invoke the SYS$OPEN system service if the
file already exists, or the SYS$CREATE system service if the file is being
created.
• Connects the file—Invoke the SYS$CONNECT system service to establish a
record stream for I/O.
• Returns the status—To return the status, equate the return status of the
SYS$OPEN or SYS$CREATE system service to the function value of the
user-open routine.
The following user-open routine opens an existing file. The file to be opened is
specified in the OPEN statement of the invoking program unit.
UFO_OPEN.FOR
INTEGER FUNCTION UFO_OPEN (FAB,
2 RAB,
2 LUN)
! Include Open VMS RMS definitions
INCLUDE ’($FABDEF)’
INCLUDE ’($RABDEF)’
! Declare dummy arguments
RECORD /FABDEF/ FAB
RECORD /RABDEF/ RAB
INTEGER LUN

28–16 File Operations


File Operations
28.6 User-Open Routines

! Declare status variable


INTEGER STATUS
! Declare system routines
INTEGER SYS$CREATE,
2 SYS$OPEN,
2 SYS$CONNECT
! Optional FAB and/or RAB modifications
.
.
.
! Open file
STATUS = SYS$OPEN (FAB)
IF (STATUS)
2 STATUS = SYS$CONNECT (RAB)
! Return status of $OPEN or $CONNECT
UFO_OPEN = STATUS
END
28.6.1.3 Setting FAB and RAB Fields
Each field in the FAB and RAB is identified by a symbolic name, such as FAB$L_
FOP. Where separate bits in a field represent different attributes, each bit offset
is identified by a similar symbolic name, such as FAB$V_CTG. The first three
letters identify the structure containing the field. The letter following the dollar
sign indicates either the length of the field (B for byte, W for word, or L for
longword) or that the name is a bit offset (V for bit) rather than a field. The
letters following the underscore identify the attribute associated with the field or
bit. The symbol FAB$L_FOP identifies the FAB options field, which is a longword
in length; the symbol FAB$V_CTG identifies the contiguity bit within the options
field.
The STRUCTURE definitions for the FAB and RAB are in the $FABDEF and
$RABDEF modules of the library SYS$LIBRARY:FORSYSDEF.TLB. To use these
definitions, do the following:
1. Include the modules in your program unit.
2. Declare RECORD variables for the FAB and the RAB.
3. Reference the various fields of the FAB and RAB using the symbolic name of
the field.
The following user-open routine specifies that the blocks allocated for the file
must be contiguous. To specify contiguity, you clear the best-try-contiguous bit
(FAB$V_CBT) of the FAB$L_FOP field and set the contiguous bit (FAB$V_CTG)
of the same field.
UFO_CONTIG.FOR
INTEGER FUNCTION UFO_CONTIG (FAB,
2 RAB,
2 LUN)
! Include Open VMS RMS definitions
INCLUDE ’($FABDEF)’
INCLUDE ’($RABDEF)’
! Declare dummy arguments
RECORD /FABDEF/ FAB
RECORD /RABDEF/ RAB
INTEGER LUN
! Declare status variable
INTEGER STATUS

File Operations 28–17


File Operations
28.6 User-Open Routines

! Declare system procedures


INTEGER SYS$CREATE,
2 SYS$CONNECT
! Clear contiguous-best-try bit and
! set contiguous bit in FAB options
FAB.FAB$L_FOP = IBCLR (FAB.FAB$L_FOP, FAB$V_CBT)
FAB.FAB$L_FOP = IBSET (FAB.FAB$L_FOP, FAB$V_CTG)
! Open file
STATUS = SYS$CREATE (FAB)
IF (STATUS) STATUS = SYS$CONNECT (RAB)
! Return status of open or connect
UFO_CONTIG = STATUS
END

28–18 File Operations


29
Using the Distributed Transaction Manager

This chapter describes how to use the distributed transaction manager. It shows
you how to use DECdtm services to bind together operations on several databases
or files into a single transaction. To use DECdtm services, the resource managers
taking part in the transaction must support DECdtm. DEC Rdb for OpenVMS
Alpha, DEC Rdb for OpenVMS VAX, DEC DBMS for OpenVMS Alpha, DEC
DBMS for OpenVMS VAX, and OpenVMS RMS Journaling support DECdtm.
This chapter is divided into the following sections:
Section 29.1 gives an introduction to DECdtm services.
Section 29.2 discusses how to call DECdtm services.
Section 29.3 gives an example that shows how to use DECdtm services.

29.1 Introduction to DECdtm Services


A transaction performs operations on resources. Examples of resources are
databases and files. A transaction often needs to use more than one resource on
one or more nodes. This type of transaction is called a distributed transaction.
Maintaining the integrity and consistency of the resources used by a distributed
transaction can be complex. To help with this, DECdtm manages distributed
transactions and reduces the amount of coding required in your applications.
DECdtm uses an optimized version of the standard two-phase commit protocol.
This ensures that transactions are atomic. If a transaction is atomic, either all
the transaction operations take effect (the transaction is committed), or none of
the operations take effect (the transaction is aborted).
The two-phase commit protocol makes sure that all the operations can take effect
before the transaction is committed. If any operation cannot take effect, for
example if a network link is lost, then the transaction is aborted, and none of the
operations take effect.

29.1.1 Sample Atomic Transaction


Edward Jessup, an employee of a computer company in Italy, is transferring to
a subsidiary of the company in Japan. An application must remove his personal
information from an Italian DBMS database and add them to a Japanese Rdb
database. Both of these operations must happen, otherwise Edward may either
end up ‘‘in limbo’’ (the application might remove him from the Italian database
but then lose a network link while trying to add him to the Japanese database),
or find that he is in both databases at the same time. Either way, the two
databases would be out of step.
If the application used DECdtm to execute both operations as an atomic
transaction, then this error could never happen; DECdtm would automatically
detect the network link failure and abort the transaction. Neither of the
databases would be updated, and the application could then try again.

Using the Distributed Transaction Manager 29–1


Using the Distributed Transaction Manager
29.1 Introduction to DECdtm Services

29.1.2 Transaction Participants


A DECdtm transaction involves the following participants:
• Application: Defines the operations that the transaction will perform.
• Resource manager: Performs the operations on the resources. A resource
manager must support DECdtm. Examples of those that do are Rdb, DBMS,
and OpenVMS RMS Journaling.
• Transaction manager: Coordinates the actions of the resource managers on
its node. Transaction managers are provided by DECdtm.
Figure 29–1 shows the participants in the distributed transaction discussed in
Section 29.1.1. The application is on node ITALY.

Figure 29–1 Participants in a Distributed Transaction

Resource Resource
Manager Application Manager
(DBMS) (Rdb/VMS)

Transaction Transaction
Resource Manager Manager Resource

node ITALY node JAPAN

ZK−4771A−GE

29.1.3 DECdtm System Services


The DECdtm system services are:
• SYS$START_TRANSW: Starts a new transaction and returns the transaction
identifier
• SYS$END_TRANSW: Ends a transaction by attempting to commit it; returns
the outcome of the transaction (either commit or abort)
• SYS$ABORT_TRANSW: Aborts a transaction
These are all synchronous system service calls. There are also asynchronous
versions (SYS$START_TRANS, SYS$END_TRANS, and SYS$ABORT_TRANS).
For a full description of all the DECdtm system services, see the OpenVMS
System Services Reference Manual.

29–2 Using the Distributed Transaction Manager


Using the Distributed Transaction Manager
29.1 Introduction to DECdtm Services

29.1.4 Default Transactions


Some resource managers (such as OpenVMS RMS Journaling) support the
concept of default transactions. This means that the application does not need
to specify the transaction identifier when executing transaction operations. The
resource manager checks whether the calling process has a default transaction;
if it has, the resource manager assumes that the operation is part of the default
transaction.

29.2 Calling DECdtm System Services


An application using the DECdtm system services follows these steps:
1. Calls SYS$START_TRANSW. This starts a new transaction and returns the
transaction identifier.
2. Instructs the resource managers to perform the required operations on their
resources.
3. Ends the transaction in one of two ways:
• Commit: To attempt to perform, or commit, the transaction, the
application calls SYS$END_TRANSW. This checks whether all the
participants can commit their operations. If any participant cannot
commit an operation, the transaction is aborted.
When SYS$END_TRANSW returns, the application finds out the outcome
of the transaction by reading the completion status in the I/O status
block.
• Abort: To abort the transaction, the application calls
SYS$ABORT_TRANSW. Typically, an application aborts a transaction
if a resource manager returns an error or if the user enters invalid
information during the transaction.

29.3 Using DECdtm Services: An Example


The following is a sample Fortran application that uses DECdtm system services.
It can be found in SYS$EXAMPLES:DECDTM$EXAMPLE1.
The application opens two files, sets a counter, then enters a loop to perform the
following steps:
• Increments the counter by 1
• Calls SYS$START_TRANSW to start a new transaction
• Writes the counter value to the two files
• Either calls SYS$END_TRANSW to attempt to commit the transaction, or
calls SYS$ABORT_TRANSW to abort the transaction
The application repeats these steps until either an error occurs or the user
requests an interrupt. Because DECdtm services are used, the two files will
always be in step with each other. If DECdtm services were not used, one file
could have been updated while the other was not. This would result in the files’
being out of step.

Using the Distributed Transaction Manager 29–3


Using the Distributed Transaction Manager
29.3 Using DECdtm Services: An Example

This example contains numbered callouts, which are explained after the program
listing.
C
C This program assumes that the files DECDTM$EXAMPLE1.FILE_1 and
C DECDTM$EXAMPLE1.FILE_2 are created and marked for recovery unit
C journaling using the command file SYS$EXAMPLES:DECDTM$EXAMPLE1.COM
C
C To run this example, enter the following:
C $ FORTRAN SYS$EXAMPLES:DECDTM$EXAMPLE1
C $ LINK DECDTM$EXAMPLE1
C $ @SYS$EXAMPLES:DECDTM$EXAMPLE1
C $ RUN DECDTM$EXAMPLE1
C
C SYS$EXAMPLES also contains an example C application, DECDTM$EXAMPLE2.C
C The C application performs the same operations as this Fortran example.
C
IMPLICIT NONE
INCLUDE ’($SSDEF)’
INCLUDE ’($FORIOSDEF)’
CHARACTER*12 STRING
INTEGER*2 IOSB(4)
INTEGER*4 STATUS,COUNT,TID(4)
INTEGER*4 SYS$START_TRANSW,SYS$END_TRANSW,SYS$ABORT_TRANSW
EXTERNAL SYS$START_TRANSW,SYS$END_TRANSW,SYS$ABORT_TRANSW
EXTERNAL JOURNAL_OPEN
C
C Open the two files
C
! OPEN (UNIT = 10, FILE = ’DECDTM$EXAMPLE1.FILE_1’, STATUS = ’OLD’,
1 ACCESS = ’DIRECT’, RECL = 3, USEROPEN = JOURNAL_OPEN)
OPEN (UNIT = 11, FILE = ’DECDTM$EXAMPLE1.FILE_2’, STATUS = ’OLD’,
1 ACCESS = ’DIRECT’, RECL = 3, USEROPEN = JOURNAL_OPEN)
COUNT = 0
TYPE *, ’Running DECdtm example program’
TYPE *, ’Press CTRL-Y to interrupt’
C
C Loop forever, updating both files under transaction control
C
DO WHILE (.TRUE.)
C
C Update the count and convert it to ASCII
C
" COUNT = COUNT + 1
ENCODE (12,8000,STRING) COUNT
8000 FORMAT (I12)
C
C Start the transaction
C
# STATUS = SYS$START_TRANSW (%VAL(1),,IOSB,,,TID)
IF (STATUS .NE. SS$_NORMAL .OR. IOSB(1) .NE. SS$_NORMAL) GO TO 9040
C
C Update the record in each file
C
$ WRITE (UNIT = 10, REC = 1, ERR = 9000, IOSTAT = STATUS) STRING
WRITE (UNIT = 11, REC = 1, ERR = 9010, IOSTAT = STATUS) STRING
C
C Attempt to commit the transaction
C
% STATUS = SYS$END_TRANSW (%VAL(1),,IOSB,,,TID)
IF (STATUS .NE. SS$_NORMAL .OR. IOSB(1) .NE. SS$_NORMAL) GO TO 9050

29–4 Using the Distributed Transaction Manager


Using the Distributed Transaction Manager
29.3 Using DECdtm Services: An Example

END DO
C
C Errors that should cause the transaction to abort
C
&
9000 TYPE *, ’Failed to update DECDTM$EXAMPLE1.FILE_1’
GO TO 9020
9010 TYPE *, ’Failed to update DECDTM$EXAMPLE1.FILE_2’
9020 STATUS = SYS$ABORT_TRANSW (%VAL(1),,IOSB,,,TID)
IF (STATUS .NE. SS$_NORMAL .OR. IOSB(1) .NE. SS$_NORMAL) GO TO 9060
STOP
C
C Errors from DECdtm system services
C
9040 TYPE *, ’Unable to start a transaction’
GO TO 9070
9050 TYPE *, ’Failed to commit the transaction’
GO TO 9070
9060 TYPE *, ’Failed to abort the transaction’
9070 TYPE *, ’Status = ’, STATUS, ’ IOSB = ’, IOSB(1)
END
C
C Switch off TRUNCATE access and PUT with truncate on OPEN for RU Journaling
C
INTEGER FUNCTION JOURNAL_OPEN (FAB, RAB, LUN)
INCLUDE ’($FABDEF)’
INCLUDE ’($RABDEF)’
INCLUDE ’($SYSSRVNAM)’
RECORD /FABDEF/ FAB, /RABDEF/ RAB
FAB.FAB$B_FAC = FAB.FAB$B_FAC .AND. .NOT. FAB$M_TRN
RAB.RAB$L_ROP = RAB.RAB$L_ROP .AND. .NOT. RAB$M_TPT
JOURNAL_OPEN = SYS$OPEN (FAB)
IF (.NOT. JOURNAL_OPEN) RETURN
JOURNAL_OPEN = SYS$CONNECT (RAB)
RETURN
END
! The application opens DECDTM$EXAMPLE1.FILE1 and
DECDTM$EXAMPLE1.FILE2 for writing. It then zeroes the variable
COUNT and enters an infinite loop.
" The application increments the count by one and converts it to an ASCII
string.
# The application calls SYS$START_TRANSW to start a transaction. The
application checks the immediate return status and service completion status
to see whether they signify an error.
$ The application attempts to write the string to the two files. If it cannot,
the application aborts the transaction. Because the files are OpenVMS RMS
journaled files, the default transaction is assumed.
% The application calls SYS$END_TRANSW to attempt to commit the
transaction. It checks the immediate return status and service completion
status to see whether they signify an error. If they do, the application reports
the error and exits. If there are no errors, the transaction is committed and
the application continues with the loop.

Using the Distributed Transaction Manager 29–5


Using the Distributed Transaction Manager
29.3 Using DECdtm Services: An Example

& If either of the two files could not be updated, the application calls
SYS$ABORT_TRANSW to abort the transaction. It checks the immediate
return status and service completion status to see whether they signify an
error. If they do, the application reports the error and exits.

29–6 Using the Distributed Transaction Manager


30
Creating User-Written System Services

This chapter describes how to create user-written system services. It contains the
following sections:
Section 30.1 describes privileged routines and privileged shareable images.
Section 30.2 describes how to write a privileged routine.
Section 30.3 describes how to create a privileged shareable image on VAX
systems.
Section 30.4 describes how to create a privileged shareable image on Alpha
systems.

30.1 Overview
Your application may contain certain routines that perform privileged functions,
called user-written system services. To create these routines, put them in
a privileged shareable image. User-mode routines in other modules can call
the routines in the privileged shareable image to perform functions in a more
privileged mode.
You create a privileged shareable image as you would any other shareable image,
using the /SHAREABLE qualifier with the linker. (For more information about
how to create a shareable image, see the OpenVMS Linker Utility Manual.)
However, because a call to a routine in a more privileged mode must be vectored
through the system service dispatch routine, you must perform some additional
steps. The following steps outline the basic procedure. Section 30.3 provides
more detail about requirements specific to VAX systems. Section 30.4 describes
the necessary steps for Alpha systems.
1. Create the source file. The source file for a privileged shareable image
contains the routines that perform privileged functions. In addition, because
user-written system services are called using the system service dispatcher,
you must include a privileged library vector (PLV) in your shareable image.
A PLV is an operating-system-defined data structure that communicates the
location of the privileged routines to the operating system.
On VAX systems, the PLV contains the addresses of dispatch routines for
each access mode used in the image. You must write these dispatch routines
and include them in your shareable image. Section 30.3.1 provides more
information.
On Alpha systems, you list the names of the privileged routines in the PLV,
sorted by access mode. You do not need to create dispatch routines; the image
activator creates them for you automatically.
Section 30.2 provides guidelines for creating privileged routines.
2. Compile or assemble the source file.

Creating User-Written System Services 30–1


Creating User-Written System Services
30.1 Overview

3. Create the shareable image. You create a privileged shareable image as you
would any other shareable image: by specifying the /SHAREABLE qualifier
to the LINK command. Note, however, that creating privileged shareable
images has some additional requirements. The following list summarizes
these requirements. See the OpenVMS Linker Utility Manual for additional
information about linker qualifiers and options.
• Declare the privileged routine entry points as universal symbols.
Privileged shareable images use the same mechanisms to declare
universal symbols as other shareable images: transfer vectors on VAX
and symbol vectors on Alpha systems. However, because calls to user-
written system services must be vectored through the system service
dispatcher, you must use extensions to these mechanisms for privileged
shareable images. Section 30.3.3 describes how to declare a universal
symbol in a VAX privileged shareable image. Section 30.4.2 describes how
to declare a universal symbol in an Alpha system privileged shareable
image.
• Prevent the linker from processing the system default shareable image
library, SYS$LIBRARY:IMAGELIB.OLB, by specifying the /NOSYSSHR
linker qualifier. Otherwise, the linker processes this library by default.
• Protect the shareable image from user-mode access by specifying the
/PROTECT linker qualifier. If you want to protect only certain portions
of the shareable image, instead of the entire image, use the PROTECT=
linker option.
• Set the VEC attribute of the program section containing the PLV by
using the PSECT_ATTR= linker option. Modules written in MACRO can
specify this attribute in the .PSECT directive. The PLV must appear in a
program section with the VEC attribute set.
• Set the shareable image identification numbers using the GSMATCH=
option.
If your privileged application requires that you link against the system
executive, see the OpenVMS Linker Utility Manual for more information.
4. Install the privileged shareable image as a protected permanent global
section. Privileged shareable images must be installed to be available to
nonprivileged programs. The following procedure is recommended:
a. Move the privileged shareable image to a protected directory, such as
SYS$SHARE.
b. Invoke the Install utility, specifying the /PROTECT, /OPEN, and
/SHARED qualifiers. You can also specify the /HEADER_RESIDENT
qualifier. The following entry could be used to install a user-written
system service whose image name is MY_PRIV_SHARE:
$ INSTALL
INSTALL> ADD SYS$SHARE:MY_PRIV_SHARE/PROTECT/OPEN/SHARED/HEADER_RES
To use a privileged shareable image, you include it in a link operation as you
would any other shareable image: specifying the shareable image in a linker
options file with the /SHAREABLE qualifier appended to the file specification to
identify it as a shareable image.

30–2 Creating User-Written System Services


Creating User-Written System Services
30.2 Writing a Privileged Routine (User-Written System Service)

30.2 Writing a Privileged Routine (User-Written System Service)


On both VAX systems and Alpha systems, the routines that implement
user-written system services must enable any privileges they need that the
nonprivileged user of the user-written system service lacks. The user-written
system service must also disable any such privileges before the nonprivileged
user receives control again. To enable or disable a set of privileges, use the Set
Privileges ($SETPRV) system service. The following example shows the operator
(OPER) and physical I/O (PHY_IO) privileges being enabled. (Any code executing
in executive or kernel mode is granted an implicit SETPRV privilege so it can
enable any privileges it needs.)
PRVMSK: .LONG <1@PRV$V_OPER>!<1@PRV$V_PHY_IO> ;OPER and PHY_IO
.LONG 0 ;quadword mask required. No bits set in
;high-order longword for these privileges.
.
.
.
$SETPRV_S ENBFLG=#1,- ;1=enable, 0=disable
PRVADR=PRVMSK ;Identifies the privileges
When you design your system service, you must carefully define the boundaries
between the protected subsystem and the user who calls the service. A protected
image has privileges to perform tasks on its own behalf. When your image
performs tasks on behalf of users, you must ensure that your image performs
only those tasks the users could not have done on their own. Always keep the
following coding principles in mind:
• Keep privileges off, and turn them on only when necessary.
• Make sure privileges are off on all exit paths. When you perform a task for
the user, operate in user mode whenever possible and operate at all times
with the user’s privileges, identity, and so on. Make sure that operating in
an inner mode does not give you any special privileges with respect to the
operation being performed. Resume a privileged state only when you are
about to resume operation on your own behalf.
• If user input can affect an operation executed with privilege, you have to
carefully validate the input. Never pass user parameters directly to an
operation executed in an inner mode or with privilege. When designing your
program, keep in mind that the inner modes implicitly provide a user with
the system privileges SETPRV, CMKRNL, SYSNAM, and SYSLCK. (See the
OpenVMS Guide to System Security for descriptions.)
• As a protected image, your program does not have the entire operating system
programming environment at its disposal. Unless a module has the prefix
SYS$ or EXE$, you must avoid calling it from an inner mode. In particular,
do not call LIB$GET_VM or LIB$RET_VM from an inner mode. You can call
OpenVMS RMS routines from executive mode but not from kernel mode.
On VAX systems, Version 5.4 or later of the operating system, any OpenVMS
RMS files that were opened with privilege from an inner mode can be left
open during user execution; however, this is not acceptable on earlier versions
of the operating system.
• Never make subroutine calls to other shareable images from kernel or
executive mode.

Creating User-Written System Services 30–3


Creating User-Written System Services
30.2 Writing a Privileged Routine (User-Written System Service)

• When a protected subsystem opens a file on its own behalf, it should specify
executive-mode logical names only by naming executive mode explicitly in the
FAB$V_LNM_MODE subfield of the file access block (FAB). This prevents a
user’s logical name from redirecting a file specification.
On VAX systems, refer to SYS$EXAMPLES:USSDISP.MAR and USSTEST.MAR
for listings of modules in a user-written system service and of a module that calls
the user-written system service.
On Alpha systems, for C examples refer to SYS$EXAMPLES:UWSS.C and
SYS$EXAMPLES:UWSS_TEST.C.

30.3 Creating a Privileged Shareable Image (VAX Only)


On VAX systems, you must create dispatch routines that transfer control to the
privileged routines in your shareable image. You then put the addresses of these
dispatch routines in a privileged library vector (PLV). Section 30.3.1 describes
how to create a dispatch routine. Section 30.3.2 describes how to create a PLV.

30.3.1 Creating User-Written Dispatch Routines on VAX Systems


On VAX systems, you must create kernel-mode and executive-mode dispatching
routines that transfer control to the routine entry points. You must supply one
dispatch routine for all your kernel mode routines and a separate routine for all
the executive mode routines. The dispatcher is usually written using the CASE
construct, with each routine identified by a code number. Make sure that the
identification code you use in the dispatch routine and the code specified in the
transfer vector identify the same routine.
The image activator, when it activates a privileged shareable image, obtains the
addresses of the dispatch routines from the PLV and stores these addresses at a
location known to the system service dispatcher. When a call to a privileged
routine is initiated by a CHME or CHMK instruction, the system service
dispatcher attempts to match the code number with a system service code. If
there is no match, it transfers control to the location where the image activator
has stored the address of your dispatch routines.
A dispatch routine must validate the CHMK or CHME operand identification
code number, handling any invalid operands. In addition, the dispatching routine
must transfer control to the appropriate routine for each identification code if
the user-written system service contains functionally separate coding segments.
The CASE instruction in VAX MACRO or a computed GOTO-type statement in a
high-level language provides a convenient mechanism for determining where to
transfer control.

30–4 Creating User-Written System Services


Creating User-Written System Services
30.3 Creating a Privileged Shareable Image (VAX Only)

Note
Users of your privileged shareable image must specify the same code
number to identify a privileged routine as you used to identify it in the
dispatch routine. Users specify the code number in their CHMK or CHME
instruction. See Section 30.3.3 for information about transfer vectors.

In your source file, a dispatch routine must precede the routines that implement
the user-written system service.
Example 30–1 illustrates a sample dispatching routine, taken from the sample
privileged shareable image in SYS$EXAMPLES named USSDISP.MAR.

Example 30–1 Sample Dispatching Routine


KERNEL_DISPATCH:: ; Entry to dispatcher
MOVAB W^-KCODE_BASE(R0),R1 ; Normalize dispatch code value
BLSS KNOTME ; Branch if code value too low
CMPW R1,#KERNEL_COUNTER ; Check high limit
BGEQU KNOTME ; Branch if out of range
;
; The dispatch code has now been verified as being handled by this dispatcher,
; now the argument list will be probed and the required number of arguments
; verified.
;
MOVZBL W^KERNEL_NARG[R1],R1 ; Get required argument count
MOVAL @#4[R1],R1 ; Compute byte count including argcount
IFNORD R1,(AP),KACCVIO ; Branch if arglist not readable
CMPB (AP),W^<KERNEL_NARG-KCODE_BASE>[R0] ; Check for required number
BLSSU KINSFARG ; of arguments
MOVL FP,SP ; Reset stack for service routine
CASEW R0,- ; Case on change mode
.
.
.

30.3.2 Creating a PLV on VAX Systems


On VAX systems, a call to a privileged routine goes to the transfer vector that
executes a change mode instruction (CHMx) specifying the identification code of
the privileged routine as the operand to the instruction. The operating system
routes the change mode instruction to the system service dispatch routine, which
attempts to locate the system service with the code specified. Because the code is
a negative number, the system service dispatcher drops through its list of known
services and transfers control to a user-written dispatch routine, if any have been
specified.

Creating User-Written System Services 30–5


Creating User-Written System Services
30.3 Creating a Privileged Shareable Image (VAX Only)

The image activator has already placed at this location the address of whatever
user-written dispatch routines it found in the privileged shareable image’s PLV
when it activated the PLV. The dispatch routine transfers control to the routine in
the shareable image identified by the code. (You must ensure that the code used
in the transfer vector and the code specified in the dispatch routine both identify
the same routine.) Figure 30–1 illustrates this flow of control.

Figure 30–1 Flow of Control Accessing a Privileged Routine on VAX Systems

Executable Image Privileged Shareable


(mytest.exe) Image (my_share.exe)

CHMK <change_mode_code> Transfer


CHMK <change_mode_code> Vector
CHME <change_mode_code>
my_serv
kernel−mode dispatcher address Privileged
exec−mode dispatcher address Library Vector

my_share_k_dispatcher:

my_share_e_dispatcher:
OpenVMS Common
Exit Path
my_serv_int:
SRVEXIT:
return
REI:

OpenVMS Change Mode Dispatcher Image activator


set these fields to
addresses of user−
exe$cmdxxxx: written dispatchers
[code does not when it activates a
match OpenVMS codes] privileged shareable
JSB image.

Image Activator Vector


of User−Written Dispatchers

JSB my_share_k_dispatcher

JSB my_share_e_dispatcher

ZK−5071A−GE

30–6 Creating User-Written System Services


Creating User-Written System Services
30.3 Creating a Privileged Shareable Image (VAX Only)

Figure 30–2 shows the components of the PLV in VAX shareable images.

Figure 30–2 Components of the Privileged Library Vector on VAX Systems

31 0

Vector Type Code

Reserved

Kernel−Mode Dispatcher

Executive−Mode Entry

User Rundown Service

Reserved

RMS Dispatcher

Address Check

ZK−5401A−GE

Table 30–1 describes each field in the PLV on a VAX processor, including the
symbolic names the operating system defines to access each field. These names
are defined by the $PLVDEF macro in SYS$LIBRARY:STARLET.MLB.

Table 30–1 Components of the VAX Privileged Library Vector


Component Symbol Description
Vector type code PLV$L_TYPE Identifies the type of vector. For PLVs, you must specify
the symbolic constant defined by the operating system,
PLV$C_TYP_CMOD, which identifies a privileged
library vector.
Kernel-mode dispatcher PLV$L_KERNEL Contains the address of the user-supplied kernel-mode
dispatching routine if your privileged library contains
routines that run in kernel mode. The address is
expressed as an offset relative to the start of the data
structure (self-relative pointer). A value of 0 indicates
that a kernel-mode dispatcher does not exist.
Executive-mode PLV$L_EXEC Contains the address of the user-supplied executive-
dispatcher mode dispatching routine if your privileged library
contains routines that run in executive mode. The
address is expressed as an offset relative to the start of
the data structure (self-relative pointer). A value of 0
indicates that a kernel-mode dispatcher does not exist.
(continued on next page)

Creating User-Written System Services 30–7


Creating User-Written System Services
30.3 Creating a Privileged Shareable Image (VAX Only)

Table 30–1 (Cont.) Components of the VAX Privileged Library Vector


Component Symbol Description

User-supplied rundown PLV$L_USRUNDWN Contains the address of a user-supplied rundown


routine routine that performs image-specific cleanup and
resource deallocation if your privileged library contains
such a routine. When the image linked against the
user-written system service is run down by the system,
this run-time routine is invoked. Unlike exit handlers,
the routine is always called when a process or image
exits. (The image rundown code calls this routine with
a JSB instruction; it returns with an RSB instruction
called in kernel mode at IPL 0.)
RMS dispatcher PLV$L_RMS Contains the address of a user-supplied dispatcher for
OpenVMS RMS services. A value of 0 indicates that a
user-supplied OpenVMS RMS dispatcher does not exist.
Only one user-written system service should specify the
OpenVMS RMS vector, because only the last value is
used. This field is intended for use only by Compaq.
Address check PLV$L_CHECK Contains a value to verify that a user-written system
service that is not position independent is located at
the proper virtual address. If the image is position
independent, this field should contain a zero. If the
image is not position independent, this field should
contain its own address.

Example 30–2 illustrates how the sample privileged shareable image in


SYS$EXAMPLES assigns values to the PLV.

Example 30–2 Assigning Values to a PLV on a VAX System


.PAGE
$PLVDEF ; Define PLV fields
.SBTTL Change Mode Dispatcher Vector Block
! .PSECT USER_SERVICES,PAGE,VEC,PIC,NOWRT,EXE
" .LONG PLV$C_TYP_CMOD ; Set type of vector to change mode
.LONG 0 ; Reserved
.LONG KERNEL_DISPATCH-. ; Offset to kernel mode dispatcher
.LONG EXEC_DISPATCH-. ; Offset to executive mode dispatcher
.LONG USER_RUNDOWN-. ; Offset to user rundown service
.LONG 0 ; Reserved.
.LONG 0 ; No RMS dispatcher
.LONG 0 ; Address check - PIC image

! The sample program sets the VEC attribute of the program section containing
the PLV.
" Values are assigned to each field of the PLV.

30–8 Creating User-Written System Services


Creating User-Written System Services
30.3 Creating a Privileged Shareable Image (VAX Only)

30.3.3 Declaring Privileged Routines as Universal Symbols Using Transfer


Vectors on VAX Systems
On VAX systems, you use the transfer vector mechanism to declare universal
symbols (described in the OpenVMS Linker Utility Manual). However, for
privileged shareable images, the transfer vector must also contain a CHMx
instruction because the target routine operates in a more privileged mode. You
identify the privileged routine by its identification code, supplied as the only
operand to the CHMx instruction. Note that the code number used must match
the code used to identify the routine in the dispatch routine. The following
example illustrates a typical transfer vector for a privileged routine:
.TRANSFER my_serv
.MASK my_serv
CHMK <code_number>
RET
Because the OpenVMS system services codes are all positive numbers and
because the call to a privileged routine is initially handled by the system service
dispatcher, you should assign negative code numbers to identify your privileged
routines so they do not conflict with system services identification codes.

30.4 Creating a User-Written System Service (Alpha Only)


On Alpha systems, in addition to the routines that perform privileged functions,
you must also include a PLV in your source file. However, on Alpha systems,
you list the privileged routines by name in the PLV. You do not need to create a
dispatch routine that transfers control to the routine; the routine is identified by
a special code.

30.4.1 Creating a PLV on Alpha Systems


On Alpha systems, the PLV contains a list of the actual addresses of the
privileged routines. The image activator creates the dispatch routines.
Figure 30–3 illustrates the linkage for a privileged routine on Alpha systems.

Creating User-Written System Services 30–9


Creating User-Written System Services
30.4 Creating a User-Written System Service (Alpha Only)

Figure 30–3 Linkage for a Privileged Routine After Image Activation

PLV

KERNEL_ROUTINE_LIST

List of Kernel Mode Procedure Values


.ADDRESS K_RTN1_INT

.ADDRESS K_RTN2_INT

Linkage Section

Procedure descriptor for K_RTN2_INT CTL$_DISPVEC::

Procedure descriptor for K_RTN1_INT

K_RTN1_INT::
; service−specific procedure
BASE/CMOD_TABLE

K_RTN2_INT:: CMOD_TABLE_END
; service−specific procedure
PLV_LIST APLD

Symbol Vector PLV_FLAGS_LIST=0

MAXCODE=65,536*2

Linkage pair for K_RTN2_EXT

Linkage pair for K_RTN1_EXT

System Service Transfer Routines and Procedure Descriptors


Procedure descriptor for K_RTN1_EXT

Procedure descriptor for K_RTN2_EXT

K_RTN1_EXT::
BIS SP,R31,R28
LDAH R0,1(R31)
CALL_PAL CHMK
RET

K_RTN2_EXT::
BIS SP,R31,R28
LDAH R0,2(R31)
CALL_PAL CHMK
RET

ZK−5910A−GE

Table 30–2 describes the components of the privileged library vector on Alpha
systems.

30–10 Creating User-Written System Services


Creating User-Written System Services
30.4 Creating a User-Written System Service (Alpha Only)

Table 30–2 Components of the Alpha Privileged Library Vector


Component Symbol Description
Vector type code PLV$L_TYPE Identifies the type of vector. You must specify
the symbolic constant, PLV$C_TYP_CMOD,
to identify a privileged library vector.
System version number PLV$L_VERSION Specifies the system version number
(unused).
Kernel-mode routine PLV$L_KERNEL_ROUTINE_ Specifies the number of user-supplied kernel-
count COUNT mode routines listed in the kernel-mode
routine list. The address of this list is
specified in PLV$PS_KERNEL_ROUTINE_
LIST.
Executive-mode routine PLV$L_EXEC_ROUTINE_ Specifies the number of user-supplied
count COUNT executive-mode routines listed in the
executive-mode routine list. The address
of this list is specified in PLV$PS_EXEC_
ROUTINE_LIST.
Kernel-mode routine list PLV$PS_KERNEL_ROUTINE_ Specifies the address of a list of user-supplied
LIST kernel-mode routines.
Executive-mode routine PLV$PS_EXEC_ROUTINE_ Specifies the address of a list of user-supplied
list LIST executive-mode routines.
User-supplied rundown PLV$PS_KERNEL_ May contain the address of a user-supplied
routine RUNDOWN_HANDLER rundown routine that performs image-specific
cleanup and resource deallocation. When
the image linked against the user-written
system service is run down by the system,
this run-time routine is invoked. Unlike exit
handlers, the routine is always called when
a process or image exits. (Image rundown
code calls this routine with a JSB instruction;
it returns with an RSB instruction called in
kernel mode at IPL 0.)
Thread-safe system PLV$M_THREAD_SAFE Flags the system service dispatcher that the
service service requires no explicit synchronization.
It is assumed by the dispatcher that the
service provides its own internal data
synchronization and that multiple kernel
threads can safely execute the service in
parallel.
RMS dispatcher PLV$PS_RMS_DISPATCHER Specifies the address of an alternative RMS
dispatching routine.
Kernel Routine Flags PLV$PS_KERNEL_ROUTINE_ Contains either the address of an array of
Vector FLAGS quadwords that contains the defined flags
associated with each kernel system service,
or a zero. If a flag is set, the kernel mode
service may return the status SS$_WAIT_
CALLERS_MODE.
Executive Routine Flags PLV$PS_EXEC_ROUTINE_ Contains a zero value, because there are no
Vector FLAGS defined flags for executive mode.

Example 30–3 illustrates how to create a PLV on Alpha systems.

Creating User-Written System Services 30–11


Creating User-Written System Services
30.4 Creating a User-Written System Service (Alpha Only)

Example 30–3 Creating a PLV on Alpha Systems

! What follows is the definition of the PLV. The PLV lives


! in its own PSECT, which must have the VEC attribute. The
! VEC attribute is forced in the linker. The PLV looks like
! this:
!
! +-------------------------------------+
! | Vector Type Code | PLV$L_TYPE
! | (PLV$C_TYP_CMOD) |
! +-------------------------------------+
! | System Version Number | PLV$L_VERSION
! | (unused) |
! +-------------------------------------+
! | Count of Kernel Mode Services | PLV$L_KERNEL_ROUTINE_COUNT
! | |
! +-------------------------------------+
! | Count of Exec Mode Services | PLV$L_EXEC_ROUTINE_COUNT
! | |
! +-------------------------------------+
! | Address of a List of Entry Points | PLV$PS_KERNEL_ROUTINE_LIST
! | for Kernel Mode Services |
! +-------------------------------------+
! | Address of a List of Entry Points | PLV$PS_EXEC_ROUTINE_LIST
! | for Exec Mode Services |
! +-------------------------------------+
! | Address of Kernel Mode | PLV$PS_KERNEL_RUNDOWN_HANDLER
! | Rundown Routine |
! +-------------------------------------+
! | | PLV$M_THREAD_SAFE
! | |
! +-------------------------------------+
! | Address of Alternative RMS | PLV$PS_RMS_DISPATCHER
! | Dispatching Routine |
! +-------------------------------------+
! | Kernel Routine Flags Vector | PLV$PS_KERNEL_ROUTINE_FLAGS
! | |
! +-------------------------------------+
! | Exec Routine Flags Vector | PLV$PS_EXEC_ROUTINE_FLAGS
! | |
! +-------------------------------------+
!
PSECT OWN = USER_SERVICES (NOWRITE, NOEXECUTE);
OWN PLV_STRUCT : $BBLOCK[PLV$C_LENGTH] INITIAL (LONG (PLV$C_TYP_CMOD,! Type
! of vector
0, ! System version number
(KERNEL_TABLE_END - KERNEL_TABLE_START) / %UPVAL, ! Number of kernel mode
! services
(EXEC_TABLE_END - EXEC_TABLE_START) / %UPVAL, ! Number of exec mode
! services
KERNEL_TABLE_START, ! Address of list of kernel mode service routine
EXEC_TABLE_START, ! Address of list of exec mode service routine
RUNDOWN_HANDLER, ! Address of list of kernel mode rundown routine
0, ! Reserved longword
0, ! Address of alternate RMS dispatcher
0, ! reserved
0)); ! reserved
PSECT OWN = $OWN$;

30–12 Creating User-Written System Services


Creating User-Written System Services
30.4 Creating a User-Written System Service (Alpha Only)

30.4.2 Declaring Privileged Routines as Universal Symbols Using Symbol


Vectors on Alpha Systems
On Alpha systems, you declare a user-written system service to be a universal
symbol by using the symbol vector mechanism. (See the OpenVMS Linker Utility
Manual for more information about creating symbol vectors.) However, because
user-written system services must be accessed by using the privileged library
vector (PLV), you must specify an alias for the user-written system service. Use
the following syntax for the SYMBOL_VECTOR= option to specify an alias that
can be universal:
SYMBOL_VECTOR = ([universal_alias_name/]internal_name = {PROCEDURE | |
DATA})
In a privileged shareable image, calls from within the image that use the alias
name result in a fixup and subsequent vectoring through the PLV, which results
in a mode change. Calls from within the shareable image that use the internal
name are made in the caller’s mode. (Calls from external images always result in
a fixup.)
The linker command procedures and options file shown in Example 30–4
illustrate how to declare universal symbols in an Alpha system privileged
shareable image.

Example 30–4 Declaring Universal Symbols for Privileged Shareable Image on


an Alpha System
$ !
$ ! Link the protected shareable image containing
$ ! the user-written system services
$ !
$ LINK /SHARE=UWSS -
/PROTECT -
/MAP=UWSS -
/SYSEXE -
/FULL/CROSS/NOTRACE -
UWSS, -
SYS$INPUT:/OPTIONS
!
! Set the GSMATCH options
!
GSMATCH=LEQUAL,1,1
!
! Define transfer vectors for protected shareable image
!
SYMBOL_VECTOR = ( -
FIRST_SERVICE = PROCEDURE, -
SECOND_SERVICE = PROCEDURE, -
THIRD_SERVICE = PROCEDURE, -
FOURTH_SERVICE = PROCEDURE -
)
!
! Need to add the VEC attribute to the PLV psect
!
PSECT=USER_SERVICES,VEC

Creating User-Written System Services 30–13


31
System Security Services

This chapter describes the security system services that provide various
mechanisms to enhance the security of operating systems. It contains the
following sections:
Section 31.1 provides an overview of the protection scheme.
Section 31.2 describes identifiers and how they are used in security.
Section 31.3 describes the rights database.
Section 31.4 describes the persona and per-thread security features.
Section 31.5 describes how to create, translate, and maintain access control
entries (ACEs).
Section 31.6 describes protected subsystems.
Section 31.7 describes security auditing.
Section 31.8 describes how to determine a user’s access to an object.
Section 31.9 describes SYS$CHECK_PRIVILEGE system service.
Section 31.10 describes how to implement site-specific security policies.

31.1 Overview of the Operating System’s Protection Scheme


The basis of the security scheme is an identifier, which is a 32-bit binary value
that represents a set of users to the system. An identifier can represent an
individual user, a group of users, or some aspect of the environment in which
a user is operating. A process is a holder of an identifier when that identifier
can represent that process to the system. The protection scheme also includes
the user identification code (UIC), the authorization database, and access control
lists.
Authorization Database
The authorization database consists of the system authorization file
(SYSUAF.DAT), the network proxy database, and the rights list database
(RIGHTSLISTS.DAT). Note that the network proxy database is called
NETPROXY.DAT on Alpha systems and NET$PROXY.DAT on VAX systems. (The
file NETPROXY.DAT on VAX systems is maintained for platform compatibility,
translation of DECnet Phase IV node names, and layered product support.)
The system rights database is an indexed file consisting of identifier and
holder records. These records define the identifiers and the holders of those
identifiers on a system. When a user logs in to the system, a process is created
and LOGINOUT creates a rights list for the process from the applicable entries
in the rights database. The process rights list contains all the identifiers that
the process holds. A process can be the holder of a number of identifiers. These
identifiers determine the access rights of the list holder. The process rights list
becomes part of the process and is propagated to any created subprocesses.

System Security Services 31–1


System Security Services
31.1 Overview of the Operating System’s Protection Scheme

Access Protection
When a process without special privileges attempts to access an object (protected
by an ACL) in the system, the operating system uses the rights list when
performing a protection check. The system compares the identifiers in the rights
list to the protection attributes of the object and grants or denies access to the
object based on the comparison. In other words, the entries in the rights list
do not specifically grant access; instead, the system uses them to perform a
protection check when the process attempts to access an object.
Access Control Lists
The protection scheme provides security with the mechanism of the access control
list (ACL). An ACL consists of access control entries (ACEs) that specify the
type of access an identifier has to an object like a file, device, or queue. When a
process attempts to access an object with an associated ACL, the system grants
or denies access based on whether an exact match for the identifier in the ACL
exists in the process rights list.
The following sections describe each of the components of the security scheme—
identifiers, rights database, process and system rights lists, protection codes, and
ACLs—and the system services affecting those components.

31.2 Identifiers
The basic component of the protection scheme is an identifier. An identifier
represents various types of agents using the system. The types of agents
represented include individual users, groups of users, and environments in which
a process is operating. Identifiers and their attributes apply to both processes
and objects. An identifier name consists of 1 to 31 alphanumeric characters
with no embedded blanks and must contain at least one nonnumeric character. It
can include the uppercase letters A through Z, dollar signs ( $ ), and underscores
( _ ), as well as the numbers 0 through 9. Any lowercase letters are automatically
converted to uppercase.

31.2.1 Identifier Format


Each of the three types of identifier has an internal format in the rights database:
user identification code (UIC) format, identification (ID) format, and facility-
specific format. The high-order bits <31:28> of the identifier value specify the
format of the identifier.

31.2.2 General Identifiers


You can define general identifiers to meet the specific needs of your site. You
grant these identifiers to users by establishing holder records in the rights
database. General identifiers can identify a single user, a single UIC group, a
group of users, or a number of groups.
Bit <31>, which is set to 1, specifies ID format used by general identifiers as
shown in Figure 31–1. Bits <30:28> are reserved by Compaq. The remaining bits
specify the identifier value.

31–2 System Security Services


System Security Services
31.2 Identifiers

Figure 31–1 ID Format

31 27 0

1000 System−generated value

ZK−5908A−GE

You define identifiers and their holders in the rights database with the Authorize
utility or with the appropriate system services. Each user can hold multiple
identifiers. This allows you to create a different kind of group designation from
the one used with the user’s UIC.
The alternative grouping described here permits each user to be a member of
multiple overlapping groups. Access control lists (ACLs) define the access to
protected objects based on the identifiers the user holds rather than on the user’s
UIC. See Section 31.5.3.1 for information on creating ACLs.
You can also define identifiers to represent particular terminals, times of day, or
other site-specific environmental attributes. These identifiers are not given holder
records in the rights database but may be granted to users by customer-written
privileged software. This feature of the security system allows each site flexibility
and, because the identifiers can be specific to the site, enhanced security. For a
programming example demonstrating this technique, see Section 31.3.2.4. For
more information, also see the OpenVMS Guide to System Security.

31.2.3 System-Defined Identifiers


System-defined identifiers, or environmental identifiers, are general identifiers
that are automatically defined when the rights database is initialized. The
following system-defined identifiers correspond directly with the login classes and
relate to the environment in which the process operates:
BATCH All attempts at access made by batch jobs
NETWORK All attempts at access made across the network
INTERACTIVE All attempts at access made by interactive processes
LOCAL All attempts at access made by users logged in at local terminals
DIALUP All attempts at access made by users logged in at dialup terminals
REMOTE All attempts at access made by users logged in on a network
Depending on the environment in which the process is operating, the system
includes one or more of these identifiers when creating the process rights list.

31.2.4 UIC Identifiers


Each UIC identifier is unique and represents a system user. By default, when an
account is created, its UIC is associated with the account’s user name generating
an identifier value. When the high-order bit <31> of the identifier value is zero,
the value identifies a UIC format identifier as shown in Figure 31–2.

System Security Services 31–3


System Security Services
31.2 Identifiers

Figure 31–2 UIC Identifier Format

31 27 16 15 0

0000 UIC group UIC member

ZK−5907A−GE

Bits <27:16> and <15:0> designate a group field and member field. Group
numbers range from 1 through 16,382; member numbers range from 0 through
65,534.

31.2.5 Facility Identifiers


Facility-specific rights identifiers allow a range of unique binary identifier values
to be reserved for a particular software product or application. Compare the
format of facility-specific identifiers with the format of general identifiers and
UIC identifiers, as shown in Section 31.2.1. The system normally determines the
binary values of general identifiers when the system manager creates them; the
system manager determines the binary values of UIC identifiers.
Figure 31–3 shows the facility-specific identifiers.

Figure 31–3 Facility-Specific Identifiers

31 27 16 15 0

1001 Facility code Facility−specific value

ZK−5909A−GE

The binary value of a facility-specific identifier is determined at the time the


application is designed. The facility number of the identifier must match
the facility number the application has chosen for its condition and message
codes. The remaining 16-bit facility-specific value may be assigned at will by
the application designer. By reserving specific binary identifier values, the
application designer may code fixed identifier values into an application’s calls to
$CHECK_PRIVILEGE, $GRANT_ID, and so forth. It avoids the added complexity
of first having to translate an identifier name to binary with $ASCTOID.
An application can choose to register the identifiers in the rights database or
not, depending on its needs. If the identifiers are registered, they are visible
to the system manager who may grant them to users. In any case, they will
be displayed properly if they appear on access control lists. If they are not
registered, they will remain invisible to the system manager. Unregistered
identifiers that appear on access control lists are displayed as a hexadecimal
value.
To register its identifiers, the installation procedure of the application must
run a program that enters the identifiers into the rights database using the
$ADD_IDENT service. You cannot specify facility-specific identifier values to
AUTHORIZE with the ADD/IDENTIFIER command.

31–4 System Security Services


System Security Services
31.2 Identifiers

Typically, facility-specific identifiers serve to extend the OpenVMS privilege


mechanism for an application. For example, consider a database manager that
includes a function to allow appropriately privileged users to modify a schema.
Access to this function could be controlled through a facility-specific identifier
named, for example, DBM$MOD_SCHEMA. The system manager grants the
identifier to authorized persons using the AUTHORIZE command GRANT/ID.
The database services that modify schemas use the $CHECK_PRIVILEGE service
to check that the caller holds the identifier.
In another example, a privileged program run by users when they log in uses
$GRANT_ID to grant the user certain facility-specific identifiers, depending on
conditions determined by the program; for example, time of day or access port
name. These identifiers can be placed on the ACLs of files to control file access,
or they might be checked by other software with $CHECK_PRIVILEGE.

31.2.6 Identifier Attributes


An identifier has attributes associated with it in the rights database. The process
rights list includes the attributes of any identifiers that the process holds.
The use of rights identifiers can be extended with the following identifier attribute
keywords:
DYNAMIC Allows unprivileged holders of an identifier to add or remove
the identifier from the process rights list using the DCL SET
RIGHTS command. Conversely, an unprivileged user who does
not have the attribute cannot modify the identifier.
HOLDER_HIDDEN Prevents someone from using the SYS$FIND_HOLDER system
service to get a list of users who hold an identifier, unless that
person holds the identifier.
NAME_HIDDEN Allows only the holders of an identifier to have it translated,
either from binary to ASCII or from ASCII to binary.
NO_ACCESS Specifies that the identifier does not affect the access rights of
the user holding the identifier.
RESOURCE Allows the holder of an identifier to charge resources, such as
disk blocks, to an identifier.
SUBSYSTEM Allows holders of the identifier to create and maintain protected
subsystems.
Using the Resource Attribute
The following example demonstrates the advantages of defining an identifier and
holders for a project.
The Physics department of a school has a common library with an associated disk
quota on the system. In order to use the Resource attribute, you must enable disk
quotas and establish a quota file entry using the SYSMAN utility. You want to
allow the faculty members to charge disk quota that they use in conjunction with
the library to the identifier PHYSICS associated with the common library and to
prevent the students from charging resources to that identifier.
• Define an identifier PHYSICS with the Resource attribute in the rights
database using the SYS$ADD_IDENT service.
• Enable disk quotas using SYSMAN as shown in the example.

System Security Services 31–5


System Security Services
31.2 Identifiers

$ MCR SYSMAN
SYSMAN> DISKQUOTA CREATE/DEVICE=DKB0:
SYSMAN> DISKQUOTA MODIFY/DEVICE=DKB0: PHYSICS /PERMQUOTA=150000 -
_SYSMAN> /OVERDRAFT=5000
SYSMAN> EXIT
• Create the common library and assign the identifier PHYSICS using the
run-time library routine LIB$CREATE_DIR.
• Grant the identifier PHYSICS to holders FRED, a faculty member, and
GEORGE, a student, using the SYS$ADD_HOLDER service.
If you specify the Resource attribute for identifier FRED, he can charge disk
resources to the PHYSICS identifier; if you do not specify the Resource attribute
for identifier GEORGE, he will not inherit the Resource attribute associated
with the identifier PHYSICS and cannot charge disk resources to the PHYSICS
identifier. The following input file, USERLIST.DAT, contains valid UIC identifiers
of students and faculty members:
FRED NORESOURCE
GEORGE RESOURCE
NANCY NORESOURCE
HAROLD RESOURCE
SUSAN RESOURCE
CHERYL NORESOURCE
MARVIN NORESOURCE
The following program reads USERLIST.DAT and associates the UIC identifiers
with the identifier PHYSICS:
#include <stdio.h>
#include <descrip.h>
#include <ssdef.h>
#include <lib$routines.h>
#include <kgbdef.h>
#include <nam.h>
#include <string.h>
#include <stdlib.h>
#define IDENT_LEN 31
#define NO_ATTR 0
#define RESOURCE 1
#define NORESOURCE 0
unsigned int sys$asctoid(),
sys$add_ident(),
sys$add_holder(),
sys$idtoasc(),
convert_id( struct dsc$descriptor_s, unsigned int );
void add_holder( unsigned int, unsigned int, unsigned int);
struct {
unsigned int uic;
unsigned int terminator;
}holder;
static char ascii_ident[IDENT_LEN],
abuffer[IDENT_LEN],
dirbuf[NAM$C_MAXRSS],
targbuf[IDENT_LEN];
$DESCRIPTOR(target,targbuf);
unsigned int status;
main() {

31–6 System Security Services


System Security Services
31.2 Identifiers

FILE *ptr;
char attr[11];
unsigned int owner_uic, attrib, resid, bin_id;
$DESCRIPTOR(dirspec,dirbuf);
$DESCRIPTOR(aident, abuffer);
printf("\nEnter directory spec: ");
gets(dirbuf);
dirspec.dsc$w_length = strlen(dirbuf);
printf("\nEnter its owner identifier: ");
gets(targbuf);
target.dsc$w_length = strlen(targbuf);

/* Add target identifier WITH resource attribute to the rights database */


attrib = KGB$M_RESOURCE;
status = sys$add_ident( &target, 0, attrib, &resid);
if((status & 1) != SS$_NORMAL)
lib$signal( status );
else
printf("\nAdding identifier %s to rights database...\n",
target.dsc$a_pointer);
/* Create the common directory with the target id as owner */
owner_uic = resid;
status = lib$create_dir( &dirspec, &owner_uic, 0, 0);
if((status & 1) != SS$_NORMAL)
lib$signal( status );
else
printf("Creating the directory %s...\n",dirspec.dsc$a_pointer);
/* Open an input file of UIC identifiers and attribute types */
if((ptr = fopen("USERLIST.DAT","r")) == NULL) {
perror("OPEN");
exit(EXIT_FAILURE);
}
/* Read the input file of UIC identifiers */
while((fscanf(ptr,"%s %s\n",abuffer,attr)) != EOF) {
aident.dsc$w_length = strlen(abuffer);
attrib = (strcmp(attr,"RESOURCE")) == 0 ? KGB$M_RESOURCE : NO_ATTR;
bin_id = convert_id( aident, attrib);
add_holder( bin_id, resid, attrib );
}
/* Close the input file */
fclose(ptr);
}
unsigned int convert_id( struct dsc$descriptor_s uic_id,
unsigned int attr ) {
unsigned int bin_id;
status = sys$asctoid(&uic_id, &bin_id, &attr);
if((status & 1) != SS$_NORMAL)
lib$signal( status );
else {
printf("Converting identifier %s to binary format...\n",
uic_id.dsc$a_pointer);
return bin_id;
}
}

void add_holder( unsigned int bin_id, unsigned int resid,


unsigned int attrib ) {

System Security Services 31–7


System Security Services
31.2 Identifiers

int i;
$DESCRIPTOR(nambuf, ascii_ident);
holder.uic = bin_id;
holder.terminator = 0;
status = sys$add_holder( resid, &holder, attrib);
if((status & 1) != SS$_NORMAL)
lib$signal( status );
else {
status = sys$idtoasc(bin_id, 0, &nambuf, 0, 0, 0);
if((status & 1) != SS$_NORMAL)
lib$signal( status );
/* Remove padding */
nambuf.dsc$w_length = strlen(ascii_ident);
for(i=0;i < nambuf.dsc$w_length + 1; i++)
if (ascii_ident[i] == 0x20)
ascii_ident[i] = ’\0’;
printf("\nAdding holder %s to target identifier %s...\n", \
nambuf.dsc$a_pointer,target.dsc$a_pointer);
}
}

31.3 Rights Database


The rights database is an indexed file containing two types of records that define
all identifiers: identifier records and holder records.
One identifier record appears in the rights database for each identifier. The
identifier record associates the identifier name with its 32-bit binary value and
specifies the attributes of the identifier. Figure 31–4 depicts the format of the
identifier record.

Figure 31–4 Format of the Identifier Record

Identifier Value

Attributes

Identifier Name

Identifier Name

Identifier Name

Identifier Name

ZK−1904−GE

31–8 System Security Services


System Security Services
31.3 Rights Database

One holder record exists in the rights database for each holder of each identifier.
The holder record associates the holder with the identifier, specifies the attributes
of the holder, and identifies the UIC identifier of the holder. Figure 31–5 depicts
the format of the holder record.

Figure 31–5 Format of the Holder Record

Identifier Value

Attributes

UIC Identifier of Holder

(Reserved)

(Reserved)

(Reserved)

(Reserved)

ZK−1907−GE

The rights database is an indexed file with three keys. The primary key is the
identifier value, the secondary key is the holder ID, and the tertiary key is the
identifier name. Through the use of the secondary key of the holder ID, all the
identifiers held by a process can be retrieved quickly when the system creates the
process’s rights list.

31.3.1 Initializing a Rights Database


You initialize the rights database in one of the following ways:
• When a system is installed
• With the Authorize utility
• With the SYS$CREATE_RDB system service
When you call SYS$CREATE_RDB, you can use the sysid argument to pass the
system identification value associated with the rights database. If you omit sysid,
the system uses the current system time in 64-bit format. If the rights database
already exists, SYS$CREATE_RDB fails with the error code RMS$_FEX. To
create a new rights database when one already exists, you must explicitly delete
or rename the old one.
You can specify the location and name of the rights database by defining the
logical name RIGHTSLIST as a system logical name in executive mode; its
equivalence string must contain the device, directory, and file name of the rights
database.
The file RIGHTSLIST.DAT has the protection of (S:RWED,O:RWED,G:R,W).

System Security Services 31–9


System Security Services
31.3 Rights Database

In order to use SYS$CREATE_RDB, write access to the database is necessary.


If the database is in SYS$SYSTEM, which is the default, you need the SYSPRV
privilege to grant write access to the directory.
When SYS$CREATE_RDB initializes a rights database, system-defined
identifiers, which describe the environment in which a process can operate,
are automatically created.
To add any other identifiers to the rights database, you must define them with
the Authorize utility or with the appropriate system service.

31.3.2 Using System Services to Affect a Rights Database


The identifier and holder records in the rights database contain the following
elements:
• Identifier binary value
• Identifier name
• Holders of each identifier
• Attribute of each identifier and each holder of each identifier
You can use the Authorize utility or one of the system services described in
Table 31–1 to add, delete, display, modify, or translate the various elements of the
rights database.

Table 31–1 Using System Services to Manipulate Elements of the Rights


Database
Action Element Service Used
Translate Identifier name to identifier binary value SYS$ASCTOID
Identifier binary value to identifier name SYS$IDTOASC
Add Identifier holder record SYS$ADD_HOLDER
New identifier record SYS$ADD_IDENT
Find Identifier value held by holder SYS$FIND_HELD
Holders of an identifier SYS$FIND_HOLDER
All identifiers SYS$IDTOASC
Modify Attribute in holder record SYS$MOD_HOLDER
Attribute in identifier record SYS$MOD_IDENT
Delete Holder from identifier record SYS$REM_HOLDER
Identifier and all its holders SYS$REM_IDENT

The following table shows what access you need for which services:

Service Required Access


SYS$ADD_HOLDER Write
SYS$ADD_IDENT Write
SYS$ASCTOID Read1

1 On VAX systems, read access is required when certain restrictions are present (for example, if the
identifiers have the name hidden or holder hidden attributes).

31–10 System Security Services


System Security Services
31.3 Rights Database

Service Required Access


SYS$CREATE_RDB Write2
SYS$FIND_HELD Read1
SYS$FIND_HOLDER Read1
SYS$FINISH_RDB Read1
SYS$IDTOASC Read1
SYS$MOD_HOLDER Write
SYS$MOD_IDENT Write
SYS$REM_HOLDER Write
SYS$REM_IDENT Write
1 On VAX systems, read access is required when certain restrictions are present (for example, if the
identifiers have the name hidden or holder hidden attributes).
2 File creation access.

31.3.2.1 Translating Identifier Values and Identifier Names


To the system, an identifier is a 32-bit binary value; however, to make identifiers
easy to use, each binary value has an associated identifier name. The identifier
value and the ASCII identifier name string are associated in the rights database.
You can use the SYS$ASCTOID and SYS$IDTOASC system services to translate
from one format to another. When you pass to SYS$ASCTOID the address of
a string descriptor pointing to an identifier name, the corresponding identifier
binary value is returned. Conversely, you use the SYS$IDTOASC service to
translate a binary identifier value to an ASCII identifier name string.
Preventing a Translation
You can prevent a translation operation by unauthorized users by specifying the
KGB$V_NAME_HIDDEN within an attributes mask.
Listing Identifiers in the Rights Database
You can also use the SYS$IDTOASC service to list the identifier names of all of
the identifiers in the rights database. Specify the id argument as 01, initialize
the context argument to 0, and repeatedly call SYS$IDTOASC until the status
code SS$_NOSUCHID is returned. The SYS$IDTOASC service returns the
identifier names in alphabetical order. When SS$_NOSUCHID is returned,
SYS$IDTOASC clears the context longword and deallocates the record stream. If
you complete your calls to SYS$IDTOASC before SS$_NOSUCHID is returned,
use SYS$FINISH_RDB to clear the context longword and to deallocate the record
stream.
The following programming example uses SYS$IDTOASC to identify all
identifiers in a rights database:
Program ID_LIST
*
* Produce a list of all the identifiers
*
integer SYS$IDTOASC
external SS$_NORMAL, SS$_NOSUCHID
character*31 NAME
integer IDENTIFIER, ATTRIBUTES
integer ID/-1/, LENGTH, CONTEXT/0/
integer NAME_DSC(2)/31, 0/

System Security Services 31–11


System Security Services
31.3 Rights Database

integer STATUS
*
* Initialization
*
NAME_DSC(2) = %loc(NAME)
STATUS = %loc(SS$_NORMAL)
*
* Scan through the entire RDB ...
*
do while (STATUS .and. (STATUS .ne. %loc(SS$_NOSUCHID)))
STATUS = SYS$IDTOASC(%val(ID), LENGTH, NAME_DSC,
+ IDENTIFIER, ATTRIBUTES, CONTEXT)
if (STATUS .and. (STATUS .ne. %loc(SS$_NOSUCHID))) then
NAME(LENGTH+1:LENGTH+1) = ’,’
print 1, NAME, IDENTIFIER, ATTRIBUTES
1 format(1X,’Name: ’,A31,’ Id: ’,Z8,’, Attributes: ’,Z8)
end if
end do
*
* Do we need to finish the RDB ???
*
if (STATUS .ne. %loc(SS$_NOSUCHID)) then
call SYS$FINISH_RDB(CONTEXT)
end if
end
31.3.2.2 Adding Identifiers and Holders to the Rights Database
To add identifiers to the rights database, use the SYS$ADD_IDENT service in a
program. When you call SYS$ADD_IDENT, use the name argument to pass the
identifier name you want to add. You can specify an identifier value with the id
argument; however, if you do not specify a value, the system selects an identifier
value from the general identifier space.
In addition to defining the identifier value and identifier name, you use
SYS$ADD_IDENT to specify attributes in the identifier record. Attributes are
enabled for a holder of an identifier only when they are set in both the identifier
record and the holder record. The attrib argument is a longword containing a bit
mask specifying the attributes. The symbol KGB$V_RESOURCE, defined in the
system macro library $KGBDEF, sets the Resource bit in the attribute longword,
and the symbol KGB$V_DYNAMIC sets the Dynamic bit. (You can use the prefix
KGB$M rather than KGB$V.) See the description of SYS$ADD_IDENT in the
OpenVMS System Services Reference Manual for a complete list of symbols.
When SYS$ADD_IDENT successfully completes execution, a new identifier record
containing the identifier value, the identifier name, and the attributes of the
identifier exists in the rights database.
When the identifier record exists in the rights database, you define the holders of
that identifier with the SYS$ADD_HOLDER system service. You pass the binary
identifier value with the id argument and you specify the holder with the holder
argument, which is the address of a quadword data structure in the following
format. Figure 31–6 shows the format of the holder argument.

31–12 System Security Services


System Security Services
31.3 Rights Database

Figure 31–6 Format of the Holder Argument

31 0
UIC identifier of holder

ZK−1903−GE

In the rights database, the holder identifier is in UIC format. You specify the
attributes of the holder with the attrib argument in the same manner as with
SYS$ADD_IDENT.
After SYS$ADD_HOLDER completes execution, a new holder record containing
the binary value of the identifier that the holder holds, the attributes of the
holder, and the UIC of the holder exists in the rights database.
31.3.2.3 Determining Holders of Identifiers
To determine the holders of a particular identifier, use the SYS$FIND_HOLDER
service in a program. When you call SYS$FIND_HOLDER, use the id argument
to pass the binary value of the identifier whose holder you want to determine. On
successful execution, SYS$FIND_HOLDER returns the holder identifier with the
holder argument and the attributes of the holder with the attrib argument.
You can identify all of the identifier’s holders by initializing the context
argument to 0 and repeatedly calling SYS$FIND_HOLDER, as detailed in
Section 31.3.3. Because SYS$FIND_HOLDER identifies the records by the same
key (holder ID), it returns the records in the order in which they were written.
31.3.2.4 Determining Identifiers Held by a Holder
To determine the identifiers held by a holder, use the SYS$FIND_HELD service
in a program. When you call SYS$FIND_HELD, use the holder argument to
specify the holder whose identifier is to be found.
On successful execution, SYS$FIND_HELD returns the identifier’s binary
identifier value and attributes.
You can identify all the identifiers held by the specified holder by initializing the
context argument to 0 and repeatedly calling SYS$FIND_HELD, as detailed in
Section 31.3.3. Because SYS$FIND_HELD identifies the records by the same key
(identifier), it returns the records in the order in which they were written.
31.3.2.5 Modifying the Identifier Record
To modify an identifier record by changing the identifier’s name, value, or
attributes, or all three in the rights database, use the SYS$MOD_IDENT service
in a program. Use the id argument to pass the binary value of the identifier
whose record you want to modify. To enable attributes, use the set_attrib
argument, which is a longword containing a bit mask specifying the attributes.
The symbol KGB$V_RESOURCE, defined in the system macro library $KGBDEF,
sets the Resource bit in the attribute longword. The symbol KGB$V_DYNAMIC
sets the Dynamic bit. (You can use the prefix KGB$M rather than KGB$V.) See
the description of SYS$MOD_IDENT in the OpenVMS System Services Reference
Manual for a complete list of symbols.

System Security Services 31–13


System Security Services
31.3 Rights Database

If you want to disable the attributes for the identifier, use the clr_attrib
argument, which is a longword containing a bit mask specifying the attributes.
If the same attribute is specified in set_attrib and clr_attrib, the attribute is
enabled.
You can also change the identifier name, value, or both with the new_name and
new_value arguments. The new_name argument is the address of a descriptor
pointing to the identifier name string; new_value is a longword containing the
binary identifier value. If you change the value of an identifier that is the holder
of other identifiers (a UIC, for example), SYS$MOD_IDENT updates all the
corresponding holder records with the new holder identifier value.
When SYS$MOD_IDENT successfully completes execution, a new identifier
record containing the identifier value, the identifier name, and the attributes of
the identifier exists in the rights database.
31.3.2.6 Modifying a Holder Record
To modify a holder record, use the SYS$MOD_HOLDER service in a program.
When you call SYS$MOD_HOLDER, use the id argument and the holder
argument to pass the binary identifier value and the UIC holder identifier whose
holder record you want to modify.
Use the SYS$MOD_HOLDER service to enable or disable the attributes of an
identifier in the same way as with SYS$MOD_HOLDER.
When SYS$MOD_HOLDER completes execution, a new holder record containing
the identifier value, the identifier name, and the attributes of the identifier exists
in the rights database.
The following programming example uses SYS$MOD_HOLDER to modify holder
records in the rights database:
Program MOD_HOLDER
*
* Modify the attributes of all the holders of identifiers to reflect
* the current attribute setting of the identifiers themselves.
*
external SS$_NOSUCHID
parameter KGB$M_RESOURCE = 1, KGB$M_DYNAMIC = 2
integer SYS$IDTOASC, SYS$FIND_HELD, SYS$MOD_HOLDER
*
* Store information about the holder here.
*
integer HOLDER(2)/2*0/
equivalence (HOLDER(1), HOLDER_ID)
integer HOLDER_NAME(2)/31, 0/
integer HOLDER_ID, HOLDER_CTX/0/
character*31 HOLDER_STRING
*
* Store attributes here.
*
integer OLD_ATTR, NEW_ATTR, ID_ATTR, CONTEXT
*
* Store information about the identifier here.
*
integer IDENTIFIER, ID_NAME(2)/31, 0/
character*31 ID_STRING

31–14 System Security Services


System Security Services
31.3 Rights Database

integer STATUS
*
* Initialize the descriptors.
*
HOLDER_NAME(2) = %loc(HOLDER_STRING)
ID_NAME(2) = %loc(ID_STRING)
*
* Scan through all the identifiers.
*
do while
+ (SYS$IDTOASC(%val(-1),, HOLDER_NAME, HOLDER_ID,, HOLDER_CTX)
+ .ne. %loc(SS$_NOSUCHID))
*
* Test all the identifiers held by this identifier (our HOLDER).
*
if (HOLDER_ID .le. 0) go to 2
CONTEXT = 0
do while
+ (SYS$FIND_HELD(HOLDER, IDENTIFIER, OLD_ATTR, CONTEXT)
+ .ne. %loc(SS$_NOSUCHID))
*
* Get name and attributes of held identifier.
*
STATUS = SYS$IDTOASC(%val(IDENTIFIER),, ID_NAME,, ID_ATTR,)
*
* Modify the holder record to reflect the state of the identifier itself.
*
if ((ID_ATTR .and. KGB$M_RESOURCE) .ne. 0) then
STATUS = SYS$MOD_HOLDER
+ (%val(IDENTIFIER), HOLDER, %val(KGB$M_RESOURCE),)
NEW_ATTR = OLD_ATTR .or. KGB$M_RESOURCE
else
STATUS = SYS$MOD_HOLDER
+ (%val(IDENTIFIER), HOLDER,, %val(KGB$M_RESOURCE))
NEW_ATTR = OLD_ATTR .and. (.not. KGB$M_RESOURCE)
end if
if ((ID_ATTR .and. KGB$M_DYNAMIC) .ne. 0) then
STATUS = SYS$MOD_HOLDER
+ (%val(IDENTIFIER), HOLDER, %val(KGB$M_DYNAMIC),)
NEW_ATTR = OLD_ATTR .or. KGB$M_DYNAMIC
else
STATUS = SYS$MOD_HOLDER
+ (%val(IDENTIFIER), HOLDER,, %val(KGB$M_DYNAMIC))
NEW_ATTR = OLD_ATTR .and. (.not. KGB$M_DYNAMIC)
end if
*
* Was it successful?
*
if (.not. STATUS) then
NEW_ATTR = OLD_ATTR
call LIB$SIGNAL(%val(STATUS))
end if
*
* Report it all.
*

System Security Services 31–15


System Security Services
31.3 Rights Database

print 1, HOLDER_STRING, ID_STRING,


+ OLD_ATTR, ID_ATTR, NEW_ATTR
1 format(1X, ’Holder: ’, A31, ’ Id: ’, A31,
+ ’ Old: ’, Z8, ’ Id: ’, Z8, ’ New: ’, Z8)
end do
2 continue
end do
end
31.3.2.7 Removing Identifiers and Holders from the Rights Database
To remove an identifier and all of its holders, use the SYS$REM_IDENT service
in a program. When you call SYS$REM_IDENT, use the id argument to pass
the binary value of the identifier you want to remove. When SYS$REM_IDENT
completes execution, the identifier and all of its associated holder records are
removed from the rights database.
To remove a holder from the list of an identifier’s holders, use the SYS$REM_
HOLDER service in a program. When you call SYS$REM_HOLDER, use the id
argument and the holder argument to pass the binary ID value and the UIC
identifier of the holder whose holder record you want to delete.
On successful execution, SYS$REM_HOLDER removes the holder from the list of
the identifier’s holders.

31.3.3 Search Operations


You can search the entire rights database when you use the SYS$IDTOASC,
SYS$FIND_HELD, and SYS$FIND_HOLDER services. You initialize the context
longword to 0 and repeatedly call one of the three services until the status code
SS$_NOSUCHID is returned. When SS$_NOSUCHID is returned, the service
clears the context longword and deallocates the record stream. If you complete
your calls to one of these services before SS$_NOSUCHID is returned, you must
use SYS$FINISH_RDB to clear the context longword and to deallocate the record
stream.
The structure of the rights database affects the order in which each of these
services returns the records when you search the rights database. The rights
database is an indexed file with three keys. The primary key is the identifier
binary value, the secondary key is the holder UIC identifier, and the tertiary key
is the identifier name.
During a searching operation, the service obtains the first record with an indexed
OpenVMS RMS GET operation. The key used for the GET operation depends on
the service. The SYS$FIND_HOLDER service uses the identifier binary value;
SYS$FIND_HELD uses the holder UIC identifier. After the indexed GET, the
service returns the records with sequential RMS GET operations. Consequently,
the file organization, the key used for the first GET operation, and the order in
which the records were originally written in the database determine the order of
records returned.
Table 31–2 summarizes how records are returned by the SYS$IDTOASC,
SYS$FIND_HELD, and SYS$FIND_HOLDER services when used in a searching
operation.

31–16 System Security Services


System Security Services
31.3 Rights Database

Table 31–2 Returned Records of SYS$IDTOASC, SYS$FIND_HELD, and


SYS$FIND_HOLDER
Service Record Order
SYS$IDTOASC Identifier name order.
SYS$FIND_HELD First GET operation—holder key. Subsequent records are
returned in the order in which they were written.
SYS$FIND_HOLDER First GET operation—identifier key. Subsequent records are
returned in the order in which they were written.

The following programming example uses SYS$IDTOASC, SYS$FINISH_RDB,


and SYS$FIND_HOLDER to search the entire rights database for identifiers with
holders and produces a list of those identifiers and their holders:
Module ID_HOLDER
( main = MAIN,
addressing_mode(external=GENERAL) ) =
begin
!
! Produce a list of all the identifiers, that have holders,
! with their respective holders.
!
!
! Declarations:
!
library
’SYS$LIBRARY:LIB’;
forward routine
MAIN;
external routine
LIB$PUT_OUTPUT,
SYS$FAO,
SYS$IDTOASC,
SYS$FINISH_RDB,
SYS$FIND_HOLDER;
!
! To create static descriptors
!
macro S_DESCRIPTOR[NAME, SIZE] =
own
%name(NAME, ’_BUFFER’): block[%number(SIZE), byte],
%name(NAME): block[DSC$K_S_BLN, byte]
preset( [DSC$B_CLASS] = DSC$K_CLASS_S,
[DSC$W_LENGTH] = %number(SIZE),
[DSC$A_POINTER] = %name(NAME, ’_BUFFER’) ); %;
!
! Descriptors for ID, holder NAME, and output LINE
!
S_DESCRIPTOR(’ID_NAME’, 31);
S_DESCRIPTOR(’NAME’, 31);
S_DESCRIPTOR(’LINE’, 76);
own
STATUS,

System Security Services 31–17


System Security Services
31.3 Rights Database

ID,
ID_LENGTH,
ID_CONTEXT: initial(0),
HOLDER,
LENGTH,
CONTEXT: initial(0),
ATTRIBS,
VALUE,
LINE_: block[DSC$K_S_BLN, byte]
preset( [DSC$B_CLASS] = DSC$K_CLASS_S,
[DSC$A_POINTER] = LINE_BUFFER );
!
! To check for existence of an ID or HOLDER
!
macro CHECK(EXPRESSION) =
(STATUS = %remove(EXPRESSION)) and (.STATUS neq SS$_NOSUCHID) %;
!
! List all the identifiers, which have holders, with their holders.
!
routine MAIN =
begin
!
! Examine all IDs (-1).
!
while
CHECK(<SYS$IDTOASC(-1, ID_LENGTH, ID_NAME, ID, ATTRIBS, ID_CONTEXT)>)
do
begin
CONTEXT = 0;
!
! Find all holders of ID.
!
while CHECK(<SYS$FIND_HOLDER(.ID, HOLDER, ATTRIBS, CONTEXT)>) do
begin
!
! Translate the HOLDER to find its NAME.
!
SYS$IDTOASC(.HOLDER, LENGTH, NAME, VALUE, ATTRIBS, 0);
!
! Print a message reporting ID and HOLDER.
!
SYS$FAO( %ascid’Id: !AD, Holder: !AD’,
LINE_[DSC$W_LENGTH], LINE,
.ID_LENGTH, .ID_NAME[DSC$A_POINTER],
.LENGTH, .NAME[DSC$A_POINTER] );
LIB$PUT_OUTPUT(LINE_);
end;
end;
return SS$_NORMAL;
end;
end
eludom

31–18 System Security Services


System Security Services
31.3 Rights Database

31.3.4 Modifying a Rights List


When a process is created, LOGINOUT builds a rights list for the process
consisting of the identifiers the user holds and any appropriate environmental
identifiers. A system rights list is the default rights list used in addition to
any process rights list. Modifications to the system rights list effectively become
modifications to the rights of each process.
A privileged user can alter the process or system rights list with the
SYS$GRANTID or SYS$REVOKID services. These services are not intended
for the general system user. Use of these services requires CMKRNL privilege.
The SYS$GRANTID service adds an identifier to a rights list or, if the identifier is
already part of the rights list, the SYS$GRANTID service modifies the attributes
of the identifier. The SYS$REVOKID service removes an identifier from a rights
list.
The SYS$GRANTID and SYS$REVOKID services treat the pidadr and prcnam
arguments the same way all other process control services treat these arguments.
For more details, see the OpenVMS Guide to System Security.
You can also modify the process or system rights list with the DCL command
SET RIGHTS_LIST. Additionally, you can use SET RIGHTS_LIST to modify
the attributes of the identifier if the identifier is already part of the rights list.
Note that you cannot use the SET RIGHTS_LIST command to modify the rights
database from which the rights list was created. For more information about
using the SET RIGHTS_LIST command, see the OpenVMS DCL Dictionary.

31.4 Persona (Alpha Only1 )


A persona contains a user’s security profile. The persona contains all identity
and credential information about the process, including the username, UIC,
privileges masks, and rights identifiers. Every process in the system has at least
one persona, the natural persona of the process. The natural persona is created
during process creation. OpenVMS stores a persona in a single data structure,
the Persona Security Block (PSB).
The persona block (PSB) contains the following:
• UIC
• Persona and system rights chains
• Permanent, authorized, and working privileges
• Account name
• User name
• Auditing flags and counters

1
Earlier versions of OpenVMS contained base support for the persona. The base
support was provided by the SYS$PERSONA_CREATE, SYS$PERSONA_ASSUME, and
SYS$PERSON_DELETE system services. VAX support is limited to these base services.

System Security Services 31–19


System Security Services
31.4 Persona (Alpha Only1 )

31.4.1 Impersonation Services (Alpha Only)


For client/server applications, the server processes requests on behalf of the
client. With OpenVMS, the server application developer can use impersonation
services for client requests. This mechanism allows the operating system to
perform object access checking (and auditing) for the server.
The impersonation system services allow a privileged OpenVMS process to
create and use personae. A process, for example a server, can acquire more
Persona System Blocks and switch between them using impersonation system
services, such as SYS$PERSONA_CREATE, SYS$PERSONA_ASSUME, and
SYS$PERSONA_CLONE. Each process has a persona array which is used to
store the addresses of all PSBs allocated to the process. Other impersonation
services support PSB lookup and attribute retrieval and modification, such as
SYS$PERSONA_FIND, SYS$PERSONA_QUERY, and SYS$PERSONA_MODIFY,
respectively.
31.4.1.1 Using Impersonation System Services
The following discussion assumes there is a running server that has the ability to
impersonate clients and is able to perform work requests for clients. This could
be a file server, for example.
When the client connects to the server, the server creates a user profile using the
SYS$PERSONA_CREATE service with the username argument. The server can
do the following to process a client’s requests:
• Switch the server’s execution context to the client’s profile, which has been
previously created, by having the server call SYS$PERSONA_ASSUME,
specifying the client’s persona.
• Make copies of the created profile and then execute client requests under
thread control with a multithreaded server. That is, the server calls
the SYS$PERSONA_CLONE service, specifying the client’s persona as
input, resulting in a copy. The server can now handle multiple requests
from the client, using an available copy of the client’s persona as input to
SYS$PERSONA_ASSUME.
• Check to determine if a given client’s profile already exists by calling
SYS$PERSONA_FIND. The SYS$PERSONA_FIND service enables the caller
to find the personae, within a process, that have certain attributes or settings.
For example, the service could specify the USERNAME item as an attribute.
• Check the client’s profile, since some client requests may require certain
privileges or rights, by calling SYS$PERSONA_QUERY, specifying the
persona to check and the items to retrieve. If required and allowable,
the server can update the person’s working privileges or rights by calling
SYS$PERSONA_MODIY, specifying the client’s persona and the attributes to
change.
• Remove a client’s profiles with a client disconnects. The server again
could use SYS$PERSONA_FIND to locate personae that match the client’s
USERNAME attribute. The server invokes SYS$PERSONA_DELETE to
remove the specified persona from the server’s process.
For more information about the persona system services, see the OpenVMS
System Services Reference Manual: GETUTC–Z.

31–20 System Security Services


System Security Services
31.4 Persona (Alpha Only1 )

31.4.2 Per-Thread Security (Alpha Only)


OpenVMS provides per-thread security capabilities. With per-thread security,
a multithreaded process allows each thread of execution to have an individual
security profile. That is, a PSB is bound to a thread of execution. Each process
has at least one kernel thread. The kernel thread block (KTB) points to the PSB
for the currently active thread. Individual user threads can point to different
PSBs, which give each user thread a separate identity. Per-thread security
profiles are supported by impersonation system services and changes to the
underlying system framework.
31.4.2.1 Previous Security Model
Prior to OpenVMS V7.2, the information that constitutes a user’s security profile
was bound at the process level, common to all threads of execution within a
process. Figure 31–7 shows this relationship.

Figure 31–7 Previous Per-Thread Security Model

Generic
Security Profile
(ARB, PCB, JIB, ...)

Profile

Execution

Thread 1 Thread 2 Thread 3 Thread 4

Security profile Security profile Security profile Security profile


DATA DATA DATA DATA

ZK−9134A−GE

Modifications that are made to the security profile by one thread are potentially
visible to other threads, depending on two key factors:
• Whether multiple threads can truly execute simultaneously
• How the threads perform profile management among themselves
31.4.2.2 Per-Thread Security Model
With OpenVMS Version 7.2, the users’ security profile (that is, their privileges,
rights, and identifier information) is shifted from the process level to the user
thread level. The security information previously stored in several structures,
including the Access Rights Block (ARB), the Process Control Block (PCB), the
Process Header Descriptor (PHD), the Job Information Block (JIB), and the
Control (CTL) region fields, has moved to the new Persona Security Block (PSB)
data structure.

System Security Services 31–21


System Security Services
31.4 Persona (Alpha Only1 )

Each thread of execution can share a security profile with other threads or have a
thread-specific security profile. Figure 31–8 shows these relationships.

Figure 31–8 Per-Thread Security Profile Model

Security Security Security


Profile 1 Profile 2 Profile 3
(PSB) (PSB) (PSB)

Profile

Execution

Thread 1 Thread 2 Thread 3 Thread 4

ZK−9135A−GE

As is the case with the previous model, modifications to a shared profile are
potentially visible to all threads that share the profile. However, modifications
made to a thread-specific profile are only applicable to the particular thread.
For more information about per-thread security, see the OpenVMS Guide to
System Security.

31.4.3 Persona Extensions (Alpha Only)


A persona extension is a mechanism to attach support for additional security
credentials into the already existing persona support. This mechanism consists
of extension-specific execlet-based code and an extension-specific data structure
(PXB) attached to an existing persona block (PSB).
To extend these capabilities, persona extension blocks (PXBs) that represent
identity and credential information of a security agent other than OpenVMS can
be attached to a PSB. The process can therefore have multiple identities: for
example, one for OpenVMS and one for NT.
An extension is more than just a data structure attached to a PSB. Routines
provided by the extension are called to process the extension data structure. This
leaves the layout of the PXB completely up to the author of the extension support
routines. A new credential/security extension can be added to a system by simply
creating the new extension routines that describe a PXB. This capability will be
added in a future release of OpenVMS.
The new and existing SYS$PERSONA system services invoke extension-specific
support routines on behalf of the registered extensions. The services also handle
new item codes that describe values stored in the PXB. Besides operating on
items for individually named extension-specific data, the services use other item
codes to establish a current PXB on which subsequent items operate. Before
using an extension-specific item code, that extension must be switched to by using
the SWITCH_EXTENSION item code. A generic set of item codes pointing to

31–22 System Security Services


System Security Services
31.4 Persona (Alpha Only1 )

generally useful PXB values (for example, principal name and domain) can be
used to fetch these values without concern for the extension-specific name.

31.5 Managing Object Protection


An ACL is a list of entries defining the type of access allowed to an object in the
system such as a file, device, or mailbox. An access control entry (ACE) consists
of an identifier and one or more access types.
(IDENTIFIER=GREEN,ACCESS=WRITE+READ+CONTROL)
(IDENTIFIER=YELLOW,ACCESS=READ)
(IDENTIFIER=RED,ACCESS=NOACCESS)
Managing object protection involves using system services to manipulate
protection codes, UICs, and ACEs; that is, creating, translating, and maintaining
ACEs, establishing object ownership, and manipulating the protection codes of
protected objects.

31.5.1 Protected Objects


A protected object is an entity that can contain or receive information. When
such information is not considered shareable, access to those objects can be
restricted. The system recognizes eleven classes of protected objects as shown in
the following table:

Class Name Description


Capability1 A resource to which the system controls access;
currently, the only defined capability is the vector
processor.
Common event flag cluster A set of 32 event flags that enable cooperating
processes to post event notifications to each other.
Device A class of peripherals connected to a processor that are
capable of receiving, storing, or transmitting data.
File Files–11 On-Disk Structure Level 2 (ODS-2) files and
directories.
Group global section A shareable memory section potentially available to all
processes in the same group.
Logical name table A shareable table of logical names and their
equivalence names for the system or a particular
group.
Queue A set of jobs to be processed in a batch, terminal,
server, or print job queue.
Resource domain A namespace controlling access to the lock manager’s
resources.
Security class A data structure containing the elements and
management routines for all members of the security
class.
System global section A shareable memory section potentially available to all
processes in the system.
Volume A mass storage medium, such as a disk or tape, that
is in ODS-2 format. Volumes contain files and may be
mounted on devices.
1 Exists only on systems with vector processors

System Security Services 31–23


System Security Services
31.5 Managing Object Protection

31.5.2 Object Security Profile


The security profile summarizes the various types of protection mechanisms
applied to a protected object. The security profile associates a protected object
with an owner, a protection code, and optionally an ACL. When a user or process
requests access to a protected object, the system compares the user’s privileges
and identifiers in the system authorization database with appropriate elements
in the object’s security profile.
31.5.2.1 Displaying the Security Profile
You can display an object’s security profile by using the SYS$GET_SECURITY
system service. On your first call to SYS$GET_SECURITY, be sure to initialize
the context variable to 0. Use the OSS$M_RELCTX flag to release any locks
on the context structure when the routine completes execution. The following
example illustrates the type of information contained in the security profile of a
logical name table:
LNM$GROUP object of class LOGICAL_NAME_TABLE
Owner: [ACCOUNTING]
Protection: (System: RWCD, Owner: RWCD, Group: R, World: R)
Access Control List:
(IDENTIFIER=[USER,CHEHKOV],ACCESS=CONTROL)
(IDENTIFIER=[USER,VANNEST],ACCESS=READ+WRITE)
After you have returned owner and protection code information, you can call
SYS$GET_SECURITY iteratively to return each ACE in the ACL (if it exists) or
you can read the entire ACL. In addition, you can perform iterative searches to
retrieve objects and their templates.
31.5.2.2 Modifying the Security Profile
You can modify all the security characteristics listed in a protected object’s profile
by using the SYS$SET_SECURITY system service. You can add or delete ACEs
in the ACL selectively or you can delete the entire ACL. You have the option of
modifying a local copy of the profile without altering the master copy using the
OSS$M_LOCAL flags or you can modify the master copy directly. Also, use the
context to release the context structure after the service completes execution.

31.5.3 Types of Access Control Entries


There are seven types of security-related ACEs as described in the following
table:

ACE Description
Alarm Sets an alarm
Application Contains application-dependent information
Audit Sets a security audit
Creator Controls access to an object based on creators
Default Protection Specifies the default protection for all files and subdirectories
created in the directory
Identifier Controls the type of access allowed based on identifiers
Subsystem Maintains protected subsystems

For information about the structure of specific types of ACEs, see the
SYS$FORMAT_ACL system service in OpenVMS System Services Reference
Manual.

31–24 System Security Services


System Security Services
31.5 Managing Object Protection

You use SYS$FORMAT_ACL and SYS$PARSE_ACL to translate ACEs from one


format to another in the same way that SYS$IDTOASC and SYS$ASCTOID
translate identifiers from binary to text format and text to binary format.
To create and manipulate ACLs, use the ACL editor, the DCL command SET
ACL, or the SYS$GET_SECURITY and SYS$SET_SECURITY system services in
a program. The following table lists services that manipulate ACEs:

Service Description
SYS$FORMAT_ACL Converts an ACE from binary format to ASCII text
SYS$GET_SECURITY Retrieves the security characteristics of an object
SYS$PARSE_ACL Converts an ACE from ASCII text to binary format
SYS$SET_SECURITY Modifies the security characteristics of a protected
object

31.5.3.1 Design Considerations


Before you attempt to manipulate ACLs, you should understand the meaning and
relationship among existing identifiers. If you are populating a previously empty
ACL, you need to plan the access types and position of each ACE within the ACL.
The position of the ACE within the ACL is an important consideration when
creating an ACE. By default, ACEs are added to the top of an ACL. The ACL
management services accept options allowing you to control the placement of
ACEs. The system compares the identifiers granted to the process requesting
access with those associated with the object starting with the top ACE in the
object’s ACL. Once a matching identifier name is found in the object’s ACL, the
search stops.
31.5.3.2 Translating ACEs
To translate ACEs from binary format to a text string, use the SYS$FORMAT_
ACL service. The aclent argument is the address of a descriptor pointing to a
buffer containing the description of the ACE. The first byte of the buffer contains
the length of the ACE and the second byte contains the type, which in turn
defines the format of the ACE.
The acllen argument specifies the length of the text string written to the buffer
pointed to by aclstr. You use the width, trmdsc, and indent arguments to
specify a particular width, termination character, and number of blank characters
for an ACE. The accnam argument contains the address of an array of 32
quadword descriptors called an access name table. The access name table
defines the names of the bits in the access mask of the ACE. The access mask
defines the access types associated with a protected object. Use run-time library
(RTL) routine LIB$GET_ACCNAM described in the OpenVMS RTL Library
(LIB$) Manual to obtain the address of the access name table. If accnam is
omitted, the following names are used:

System Security Services 31–25


System Security Services
31.5 Managing Object Protection

Bit <0> READ


Bit <1> WRITE
Bit <2> EXECUTE
Bit <3> DELETE
Bit <4> CONTROL
Bit <5> BIT_5
Bit <6> BIT_6
.
.
.
Bit <31> BIT_31
The SYS$PARSE_ACL service translates an ACE from text string format to
binary format. The aclstr argument is the address of a string descriptor pointing
to the ACE text string. As with SYS$FORMAT_ACL, the aclent argument is the
address of a descriptor pointing to a buffer containing the description of the ACE.
The first byte of the buffer contains the length of the ACE and the second byte
contains the type, which in turn defines the format of the ACE. If SYS$PARSE_
ACL fails, the errpos argument points to the failing point in the string. The
accnam argument contains the address of an array of 32 quadword descriptors
that define the names of the bits in the access mask of the ACE. If accnam is
omitted, the names specified in the description of SYS$FORMAT_ACL are used.
31.5.3.3 Creating and Maintaining ACEs
The SYS$GET_SECURITY and SYS$SET_SECURITY system services replace the
SYS$CHANGE_ACL system service. The OpenVMS System Services Reference
Manual: A–GETUAI and the OpenVMS System Services Reference Manual:
GETUTC–Z describe these system services.
To create or modify an ACL associated with a protected object, you use the
SYS$SET_SECURITY service. You specify the object whose ACL is to be modified
with either the objhan argument, which specifies the I/O channel associated
with the object, or the objnam argument, which specifies the object name. If
you specify objnam, objhan must be omitted or specified as 0. The clsnam
argument specifies the type of object.
Use the acmode argument to specify the access mode used when checking file
access protection. By default, kernel mode is used, but the system compares
acmode against the caller’s access mode and uses the least privileged mode.
Compaq recommends that this argument be omitted (passed as zero).
The item code specifies the change to be made to the ACL. Table 31–3 describes
the symbols for the item codes that are defined in the system macro library
($ACLDEF). Note that without the itmlst argument, you can manipulate only
the security profile locks or release contxt resources.

Table 31–3 Item Code Symbols and Meanings


Item Code Description
OSS$_ACL_ADD_ENTRY Adds an access control entry (ACE)
OSS$_ACL_DELETE Deletes all unprotected ACEs from an ACL
OSS$_ACL_DELETE_ALL Deletes the ACL, including protected ACEs
OSS$_ACL_DELETE_ENTRY Deletes an ACE
(continued on next page)

31–26 System Security Services


System Security Services
31.5 Managing Object Protection

Table 31–3 (Cont.) Item Code Symbols and Meanings


Item Code Description

OSS$_ACL_FIND_ENTRY Locates an ACE


OSS$_ACL_FIND_NEXT Moves the current position to the next ACE in
the ACL
OSS$_ACL_FIND_TYPE Locates an ACE of the specified type
OSS$_ACL_MODIFY_ENTRY Replaces an ACE at the current position
OSS$_ACL_POSITION_BOTTOM Sets a marker that points to the end of the
ACL
OSS$_ACL_POSITION_TOP Sets a marker that points to the beginning of
the ACL
OSS$_OWNER Sets the UIC or general identifier of the
object’s owner
OSS$_PROTECTION Sets the protection code of the object

31.6 Protected Subsystems


A protected subsystem is a set of application programs that allows controlled
access to objects. It has under its control one or more protected objects and a
gatekeeper application. Users cannot access the objects within the subsystem
unless they execute the gatekeeper application. Once users have successfully
executed the application, their process rights list acquires the identifiers
necessary to access objects owned by the subsystem. The identifiers allow
processes to use the resources of the subsystem. When the application completes
execution or the user exits, the identifiers are removed from the user’s process
rights list. Protected subsystems are an alternative to creating privileged images
and protected shareable images (user-written system services), and help prevent
the overuse of privileges.
Roles and Responsibilities
You should think of a protected subsystem as an isolated security domain where
the system manager creates and grants SUBSYSTEM identifiers using the
Authorize utility as shown in the following example:
UAF> ADD/IDENTIFIER FOO/ATTRIBUTES=SUBSYSTEM
UAF> GRANT/IDENTIFIER FOO FRANK /ATTRIBUTES=SUBSYSTEM
The system manager can delegate responsibility for the maintenance of the
subsystem to subsystem managers who can associate existing identifiers with the
subsystem executable and its data. In the following example, the manager of a
protected subsystem creates an ACE in a subsystem’s image and data files:
$ SET SECURITY BLOP.EXE -
_$ /ACL=(SUBSYSTEM, IDENTIFIER=FOO) -
$ SET SECURITY BLOP.DAT -
_$ /ACL=(IDENTIFIER=FOO, ACCESS=READ+WRITE) -
$ SET SECURITY BLOP.EXE -
_$ /ACL=(IDENTIFIER=HARRY, ACCESS=EXECUTE) -
Finally, a user uses the protected subsystem to access data available only through
the subsystem.

System Security Services 31–27


System Security Services
31.6 Protected Subsystems

Subsystem Security
During the execution of a protected subsystem, $IMGACT adds subsystem
identifiers to the image rights list. What happens if the user presses the Ctrl/Y
key sequence during execution? Will the user retain whatever privileges were
granted by the subsystem? If the user presses Ctrl/Y, image identifiers are
removed from the process. Also, subprocesses do not inherit image identifiers
by default. However, SYS$CREPRC and LIB$SPAWN do contain flags PRC$M_
SUBSYSTEM and SUBSYSTEM, respectively, that allow subprocesses to inherit
image identifiers.

31.7 Security Auditing


Auditing is the recording of security-relevant activity as it occurs on a system.
See the OpenVMS Guide to System Security for a list of all types of security-
relevant activity or classes of events that are audited. The following table
describes the security services that provide security auditing:

Service Description
SYS$AUDIT_EVENT Appends an event message to the system audit log file
or sends an alarm to a security operator terminal
SYS$CHECK_PRIVILEGE Determines whether the caller has the specified
privileges or identifiers

The system service SYS$AUDIT_EVENT is used to report security events to the


auditing system. It examines the settings of the DCL command SET AUDIT to
determine if an event is enabled for auditing. If the event is enabled for alarms
or audits, SYS$AUDIT_EVENT generates an audit record and appends it to the
system audit log file (or sends an alarm to a security operator terminal) that
identifies the process involved and lists information supplied by its caller.

31.8 Checking Access Protection


The operating system provides two system services that allow a process to check
access to objects on the system: SYS$CHKPRO and SYS$CHECK_ACCESS.
The SYS$CHKPRO service performs the system access protection check on a
user attempting direct access to an object on the system; SYS$CHECK_ACCESS
performs a similar check on a third party attempting access to an object. The
following table describes the security services that provide access checking:

Service Description
SYS$CHECK_ACCESS Invokes a system access protection check on behalf of
another user
SYS$CHKPRO Invokes a system access protection check

The SYS$CHKPRO and SYS$CHECK_ACCESS system services have been


extended to support auditing. The OpenVMS Guide to System Security describes
how to use the auditing function. The OpenVMS System Services Reference
Manual: A–GETUAI describes how to use the two system services. These
services are described in the following sections.

31–28 System Security Services


System Security Services
31.8 Checking Access Protection

31.8.1 Creating a Security Profile


The SYS$CREATE_USER_PROFILE system service returns a user profile,
using information in the rights database and the system authorization
database to generate the profile. The system services SYS$CHECK_ACCESS or
SYS$CHKPRO accept as input the profile from SYS$CREATE_USER_PROFILE.

31.8.2 SYS$CHKPRO System Sevice


The SYS$CHKPRO system service invokes the access protection check used by
the system. The service does not grant or deny access; rather, it performs the
protection check. Subsequently, an application might grant or deny access to the
specified object.
To pass the input and output information to SYS$CHKPRO, use the itmlst
argument, which is the address of an item list of descriptors. The SYS$CHKPRO
service compares the item list of the rights and privileges of the accessor to a list
of the protection attributes of the object to be accessed. If the accessor can access
the object, SYS$CHKPRO returns the status SS$_NORMAL; if the accessor
cannot access the object, SYS$CHKPRO returns the status SS$_NOPRIV. The
SYS$CHKPRO service does not grant or deny access. The subsystem itself must
grant or deny access based on the output (SS$_NORMAL or SS$_NOPRIV) from
SYS$CHKPRO.
The SYS$CHKPRO service also returns an item list of the rights or privileges
that allowed the accessor access to the object, as well as the names of security
alarms raised by the access attempt. For information about the item codes
defined for SYS$CHKPRO, see the description of SYS$CHKPRO in the OpenVMS
System Services Reference Manual.
See the OpenVMS Guide to System Security for a flowchart describing how
SYS$CHKPRO evaluates an access request attempt.

31.8.3 SYS$CHECK_ACCESS System Service


The SYS$CHECK_ACCESS service performs a protection check on a third-party
accessor. An example of this is a file server program that uses SYS$CHECK_
ACCESS to ensure that an accessor (the third party) requesting a file has the
required privileges to do so.
You pass the input and output information to SYS$CHECK_ACCESS by using
the itmlst argument, which is the address of an item list of descriptors. You
also pass the name of the accessor and the name and type of the object being
accessed by using the usrnam, objnam, and objtyp arguments, respectively.
The SYS$CHECK_ACCESS service compares the rights and privileges of the
accessor to a list of the protection attributes of the object to be accessed. If
the accessor can access the object, SYS$CHECK_ACCESS returns the status
SS$_NORMAL; if the accessor cannot access the object, SYS$CHECK_ACCESS
returns the status SS$_NOPRIV.
The SYS$CHECK_ACCESS service does not grant or deny access. The subsystem
itself must explicitly grant or deny access based on the output (SS$_NORMAL or
SS$_NOPRIV) from SYS$CHECK_ACCESS.
The SYS$CHECK_ACCESS service also returns an item list of the rights or
privileges that allowed the accessor to access the object, as well as the names of
security alarms raised by the access attempt. For information about the item
codes defined for SYS$CHECK_ACCESS, see the description of SYS$CHECK_
ACCESS in the OpenVMS System Services Reference Manual.

System Security Services 31–29


System Security Services
31.9 SYS$CHECK_PRIVILEGE

31.9 SYS$CHECK_PRIVILEGE
The SYS$CHECK_PRIVILEGE system service determines whether the caller
has the specified privileges or identifiers. The service performs the privilege
check and looks at the SET AUDIT settings to determine whether the system
administrator enabled privilege auditing. When privilege auditing is enabled,
SYS$CHECK_PRIVILEGE generates an audit record. The audit record identifies
the process (subject) and privilege involved, provides the result of the privilege
check, and lists supplemental event information supplied by its caller. Privilege
audit records usually contain either the DCL command line or the system service
name associated with the privilege check.
SYS$CHECK_PRIVILEGE completes asynchronously; that is, it does not wait for
final status. For synchronous completion, use the SYS$CHECK_PRIVILEGEW
service.

31.10 Implementing Site-Specific Security Policies


Occasionally, you may need to write routines that implement site-specific policies
or special algorithms. The routines that you write can either replace or augment
built-in operating system policies. This section contains instructions for replacing
key operating system security routines with routines that are specific to your
site. Two types of routines are discussed: loadable system services and shareable
images.

31.10.1 Creating Loadable Security Services


This section describes how to create a system service image and how to update
the SYS$LOADABLE_IMAGES:VMS$SYSTEM_IMAGES.DATA file, which
controls site-specific loading of system images. These procedures update the
loading of system images for all nodes of a cluster.
Currently, you can replace the following three system services with services
specific to your site:

Service Description
SYS$ERAPAT Generates a security erasure pattern
SYS$MTACCESS Controls magnetic tape access
SYS$HASH_PASSWORD Applies a hash algorithm to an ASCII password

When you create the system service, you code the source module and define the
vector offsets, the entry point, and the program sections for the system service.
Then, you can assemble and link the module to create a loadable image.
Once you have created the loadable image, you install it. First, you copy the
image into the SYS$LOADABLE_IMAGES directory and add an entry for it
in the operating system’s images file using the System Management utility
(SYSMAN). Next, you invoke the system images command procedure to generate
a new system image data file. Finally, you reboot the system to load your service.
The following sections describe how to create and load the the Get Security Erase
Pattern (SYS$ERAPAT) system service.
On VAX only systems, you can find an example of the SYS$ERAPAT system
service in SYS$EXAMPLES:DOD_ERAPAT.MAR on the operating system. The
description here also applies to the Hash Password (SYS$HASH_PASSWORD)
and Magnetic Tape Accessibility (SYS$MTACCESS) system services. You can find

31–30 System Security Services


System Security Services
31.10 Implementing Site-Specific Security Policies

an example of how to prepare and load the SYS$HASH_PASSWORD service in


SYS$EXAMPLES:HASH_PASSWORD.MAR.
31.10.1.1 Preparing and Loading a System Service
With the following VAX only example, use this procedure to prepare and load a
system service, in this case SYS$ERAPAT:
1. Create the source module.
a. Include the following macro to define system service vector offsets:
$SYSVECTORDEF ; Define system service vector offsets
b. Use the following macro to define the system service entry point:
SYSTEM_SERVICE ERAPAT, - ; Entry point name
<R4>, - ; Register to save
MODE=KERNEL,- ; Mode of system service
NARG=3 ; Number of arguments
(The code immediately following this macro is the first instruction of the
SYS$ERAPAT system service.)
c. Use the following macros to declare the desired program sections:
DECLARE_PSECT EXEC$PAGED_CODE ; Pageable code PSCET
DECLARE_PSECT EXEC$PAGED_DATA ; Pageable data PSECT
DECLARE_PSECT EXEC$NONPAGED_DATA ; Nonpageable data PSECT
DECLARE_PSECT EXEC$NONPAGED_CODE ; Nonpageable code PSCET
2. Assemble the source module by using the following command:
$ MACRO DOD_ERAPAT+SYS$LIBRARY:LIB.MLB/LIB
3. Link the module to create a SYS$ERAPAT.EXE executive loaded image. You
can link the module using the command procedure DOD_ERAPAT_LNK.COM
in SYS$EXAMPLES. (A command procedure is also available to link the
SYS$HASH_PASSWORD example.) To link the SYS$ERAPAT module, enter
the following command:
$ @SYS$EXAMPLES:DOD_ERAPAT_LNK.COM
4. Prepare the operating system image to be loaded.
a. Copy the SYS$ERAPAT.EXE image produced by the link command into
the SYS$COMMON:[SYS$LDR] directory. Note that privilege is required
to put files into this directory.
b. Add an entry for the SYS$ERAPAT.EXE image in the
SYS$UPDATE:VMS$SYSTEM_IMAGES.IDX data file.
You add an entry by using the SYSMAN command SYS_LOADABLE
ADD. (See the OpenVMS System Management Utilities Reference Manual
for a description of this command.) For example, the following commands
add an entry in VMS$SYSTEM_IMAGES.IDX for SYS$ERAPAT.EXE:
$ RUN SYS$SYSTEM:SYSMAN
SYSMAN> SYS_LOADABLE ADD _LOCAL_ SYS$ERAPAT -
_SYSMAN> /LOAD_STEP = SYSINIT -
_SYSMAN> /SEVERITY = WARNING -
_SYSMAN> /MESSAGE = "failure to load SYS$ERAPAT.EXE"

System Security Services 31–31


System Security Services
31.10 Implementing Site-Specific Security Policies

This entry specifies that the SYS$ERAPAT.EXE image is to be loaded by


the SYSINIT process during the bootstrap. If there is an error loading the
image, the following messages are printed on the console terminal:
%SYSINIT-E-failure to load SYS$ERAPAT.EXE
-SYSINIT-E-error loading <SYS$LDR>SYS$ERAPAT.EXE, status = "status"
The following table shows other error messages that may be returned:

Message Meaning User Action


NO_PHYSICAL_ Physical memory is not Check SYSGEN
MEMORY available. parameters.
NO_POOL Amount of nonpaged Check SYSGEN
pool is insufficient. parameters.
MULTIPLE_ISDS Encountered more than Check link options.
one image section of a
given type.
BAD_GSD An inconsistency was Verify that the image was
detected. linked properly.
NO_SUCH_IMAGE The requested image Check image name
cannot be located. against images in
SYS$LOADABLE_
IMAGES.

c. Invoke the SYS$UPDATE:VMS$SYSTEM_IMAGES.COM command


procedure to generate a new system image data file (VMS$SYSTEM_
IMAGES.DATA). The system bootstrap uses this image data file to load
the appropriate images into the system.
d. Reboot the system, which loads the original SYS$ERAPAT.EXE image
into the system. Subsequent calls to the SYS$ERAPAT system service use
the normal operating system routine.
As the default, the system bootstrap loads all images described in
VMS$SYSTEM_IMAGES.DATA. You can disable this feature by setting
the special system parameter LOAD_SYS_IMAGES to 0.
31.10.1.2 Removing an Executive Loaded Image
With the following VAX only example, use this procedure to remove an executive
loaded image; in this case, SYS$ERAPAT.EXE:
1. Enter the following SYSMAN command:
SYSMAN> SYS_LOADABLE REMOVE _LOCAL_ SYS$ERAPAT
2. Invoke the SYS$UPDATE:VMS$SYSTEM_IMAGES.COM command
procedure to generate a new system image data file (VMS$SYSTEM_
IMAGES.DATA). The system bootstrap uses this image data file to load
the appropriate images into the system.
3. Reboot the system, which loads the installation-specific SYS$ERAPAT.EXE
image into the system. Subsequent calls to the SYS$ERAPAT system service
use the installation-specific routine.
As the default, the system bootstrap loads all images described in the
system image data file (VMS$SYSTEM_IMAGES.DATA). You can disable this
functionality by setting the special system parameter LOAD_SYS_IMAGES
to 0.

31–32 System Security Services


System Security Services
31.10 Implementing Site-Specific Security Policies

31.10.2 Installing Filters for Site-Specific Password Policies


A site security administrator can screen new passwords to make sure they comply
with a site-specific password policy. (See the OpenVMS Guide to System Security
for more information.) This section describes how a security administrator can
encode the policy, create a shareable image and install it in SYS$LIBRARY, and
enable the policy by setting a SYSGEN parameter.
Installing and enabling a site-specific password policy image requires both
SYSPRV and CMKRNL privileges.
31.10.2.1 Creating a Shareable Image
To compile and link a shareable image that filters passwords for words that are
sensitive to your site, perform the following steps:
1. Create the source module VMS$PASSWORD_POLICY.*.
Bliss and Ada examples of the policy module’s interface, called
VMS$PASSWORD_POLICY.*, are located in SYS$EXAMPLES.
Define two routine names in the source module: POLICY_PLAINTEXT and
POLICY_HASH. These routines must be global (see your language reference
for instructions on defining a global routine). The Set Password utility looks
for these routine names and displays the message SYMNOTFOU either if the
names are missing or if the routines are not defined as global.
2. Link the source file.
For VAX only examples, use the VMS$PASSWORD_POLICY_LNK.COM
command procedure, located in SYS$EXAMPLES.
31.10.2.2 Installing a Shareable Image
To install a shareable image, perform the following steps:
1. Copy the file to SYS$LIBRARY and install it using the following commands:
$ COPY VMS$PASSWORD_POLICY.EXE SYS$COMMON:[SYSLIB]/PROTECTION=(W:RE)
$ INSTALL ADD SYS$LIBRARY:VMS$PASSWORD_POLICY/OPEN/HEAD/SHARE
2. Set the system parameter LOAD_PWD_POLICY to 1 as follows:
$ RUN SYS$SYSTEM:SYSGEN
SYSGEN> USE ACTIVE
SYSGEN> SET LOAD_PWD_POLICY 1
SYSGEN> WRITE ACTIVE
SYSGEN> WRITE CURRENT

System Security Services 31–33


System Security Services
31.10 Implementing Site-Specific Security Policies

3. To make the changes permanent, add the INSTALL command from step 1
to the SYS$SYSTEM:SYSTARTUP_VMS.COM file and modify the system
parameter file, MODPARAMS.DAT, so that the LOAD_PWD_POLICY
parameter is set to 1.
4. Run AUTOGEN as follows to ensure that the system parameters are set
correctly on subsequent system startups:
$ @SYS$UPDATE:AUTOGEN SAVPARAMS SETPARAMS

31–34 System Security Services


32
Logical Name and Logical Name Tables

This chapter describes how to create and use logical names and logical name
tables. It contains the following sections:
Section 32.1 describes how to use logical name system services and DCL
commands, how to use logical and equivalence names, and how to use logical
name tables.
Section 32.2 describes how to create user-defined and clusterwide logical name
tables.
Section 32.3 describes how to check access and protection of logical names and
logical name tables.
Section 32.4 describes how to specify access modes of a logical name.
Section 32.5 describes how to translate logical names.
Section 32.6 describes how to specify attributes.
Section 32.7 describes how to establish logical name table quotas.
Section 32.8 describes interprocess communication.
Section 32.9 describes the format convention for logical names and equivalence
names.
Section 32.10 describes how to use logical name and logical name tables system
services with example programs.

32.1 Logical Name System Services and DCL Commands


This section describes how to use system services to establish logical names
for general application purposes. The system performs special logical name
translation procedures for names associated with certain system services. For
further information, see the following chapters:
• Mailbox names and device names for I/O services: Chapter 9
• Common event flag cluster names: Chapter 6
• Global section names: Chapter 21
The operating system’s logical name services provide a technique for
manipulating and substituting character-string names. Logical names are
commonly used to specify devices or files for input or output operations. You can
also use logical names to communicate information between processes by creating
a logical name in one process in a shared logical name table and translating the
logical name in another process.

Logical Name and Logical Name Tables 32–1


Logical Name and Logical Name Tables
32.1 Logical Name System Services and DCL Commands

Besides using logical name system services, you can use DCL commands to create
and manipulate logical names and logical name tables. Table 32–1 lists the
operating system’s logical name system services and equivalent DCL commands.

Table 32–1 Logical Name Services and DCL Commands


System Service Meaning DCL Command Meaning
SYS$CRELNM Create Logical Name ALLOCATE Optionally associates a
logical name with a device
ASSIGN Creates a logical
name and assigns an
equivalence string to a
specific logical name
DEFINE Associates an equivalence
name with a logical name
MOUNT Allows the optional
naming of a logical name
for a disk or magnetic
tape volume
SYS$CRELNT Create Logical Name CREATE/NAME_TABLE Creates a new logical
Table name table
SYS$DELLNM Delete Logical Name DEASSIGN Cancels a logical name
assignment
SYS$TRNLNM Translate Logical Name SHOW LOGICAL Displays translations and
the logical name table for
a specified logical name
SHOW TRANSLATION Displays the first
translation found for
the specified logical name

As the names of the logical name system services imply, when you use the logical
name system services, you are concerned with creating, deleting, and translating
logical names and with creating and deleting logical name tables.
The following sections describe various concepts you should be aware of when you
use the logical name system services. For further discussion of logical names, see
the OpenVMS User’s Manual.

32.1.1 Logical Names, Equivalence Names, and Search Lists


A logical name is a user-specified character string that can represent a
file specification, device name, logical name table name, application-specific
information, or another logical name. Typically, for process-private purposes, you
specify logical names that are easy to use and to remember. System managers
and privileged users choose mnemonics for files, system devices, and search lists
that are frequently accessed by all users.
An equivalence string, or an equivalence name, is a character string that
denotes the actual file specification, device name, or character string. An
equivalence name can also be a logical name. In this case, further translation is
necessary to reveal the actual equivalence name.
A multivalued logical name, commonly called a search list, is a logical name
that has more than one equivalence string. Each equivalence string in the search
list is assigned an index number starting at zero.

32–2 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.1 Logical Name System Services and DCL Commands

Logical names and their equivalence strings are stored in logical name tables.
Logical names can have a maximum length of 255 characters. Equivalence
strings can have a maximum of 255 characters. You can establish logical name
and equivalence string pairs as follows:
• At the command level, with the DCL commands ALLOCATE, ASSIGN,
DEFINE, or MOUNT
• In a program, with the Create Logical Name (SYS$CRELNM), Create Mailbox
and Assign Channel (SYS$CREMBX), or Mount Volume (SYS$MOUNT)
system service
For example, you could use the symbolic name TERMINAL to refer to an output
terminal in a program. For a particular run of the program, you could use the
DEFINE command to establish the equivalence name TTA2.
To create a logical name in a program, you must define character-string
descriptors for the name strings and call the system service within your program.

32.1.2 Logical Name Tables


A logical name table contains logical name and equivalence string pairs. Each
table is an independent name space. When you translate a logical name, you
specify the table containing the name. A logical name table is referred to by its
name, which is itself a logical name, or by another logical name that translates
into the table name.
Logical name tables can be created in process space or in system space. Tables
created in process space are accessible only by that process. Tables created in
system space are potentially shareable among many processes. OpenVMS creates
a number of logical name tables with specific characteristics. These predefined
logical name tables have names beginning with the prefix LNM$.
Logical name and equivalence name pairs are maintained in three types of logical
name tables:
• Directory tables
• Default tables
• User-defined name tables
32.1.2.1 Logical Name Directory Tables
Because the names of logical name tables are logical names, table names must
reside in logical name tables. Two special tables called directories exist for this
purpose. Table names are translated from these logical name directory tables.
Logical name and equivalence name pairs for logical name tables are maintained
in the following two directory tables:
• Process directory table (LNM$PROCESS_DIRECTORY)
• System directory table (LNM$SYSTEM_DIRECTORY)
The process directory table contains the names of all process-private user-defined
logical name tables created through the SYS$CRELNT system service. In
addition, the process directory table contains system-assigned logical name table
names and the name of the process logical name table LNM$PROCESS_TABLE.
The system directory table contains the names of potentially shareable logical
name tables and system-assigned logical name table names. Typically, you must
have the SYSPRV privilege to create a logical name in the system directory table.
For a discussion of privileges, see Section 32.3.

Logical Name and Logical Name Tables 32–3


Logical Name and Logical Name Tables
32.1 Logical Name System Services and DCL Commands

Logical names other than logical name table names can exist within these tables,
but are strongly discouraged. The length of the logical names and table names
created in either of these tables must not exceed 31 characters. Logical table
names and logical names created in the directory tables must consist of uppercase
alphanumeric characters, dollar signs ( $ ), and underscores ( _ ). Equivalence
strings must not exceed 255 characters.
32.1.2.2 Process, Job, Group, System and Clusterwide Default Logical Name Tables
OpenVMS creates a number of logical name tables automatically, some at system
initialization and some at process creation. Some of these tables are accessible to
all processes, and some are accessible only to selected processes. These tables are
called the default logical name tables.
Each default logical name table has a logical name associated with it in addition
to its table name. The default logical name table names and the common logical
names used to refer to them are as follows:

Table Name Logical Name


Process LNM$PROCESS_TABLE LNM$PROCESS
Job LNM$JOB_xxxxxxxx1 LNM$JOB
Group LNM$GROUP_gggggg2 LNM$GROUP
System LNM$SYSTEM_TABLE, LNM$SYSTEM
LNM$SYSCLUSTER
Clusterwide LNM$SYSCLUSTER_TABLE LNM$SYSCLUSTER
system table
Clusterwide LNM$CLUSTER_TABLE LNM$CLUSTER
parent table
1 The letter x represents a numeral in an 8-digit hexadecimal number that uniquely identifies the job
logical name table.
2 The letter g represents a numeral in a 6-digit octal number that contains the user’s group number.

The length of the logical names created in these tables cannot exceed 255
characters, with no restriction on the types of characters used. Equivalence
strings cannot exceed 255 characters. By convention, a Compaq-created logical
name begins with a facility-specific prefix, followed by a dollar sign ($) and a
name within that facility. You are strongly encouraged to define logical names
without the dollar sign ($) to avoid inadvertent conflicts.
32.1.2.2.1 Process Logical Name Table The process logical name table
LNM$PROCESS_TABLE contains names used exclusively by the process. A
process logical name table exists for each process in the system. Some entries
in the process logical name table are made by system programs executing at
more privileged access modes; these entries are qualified by the access mode from
which the entry was made. The process logical name table contains the following
process-permanent logical names:

Logical Name Meaning


SYS$INPUT Default input stream
SYS$OUTPUT Default output stream
SYS$COMMAND Original first-level (SYS$INPUT) input stream

32–4 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.1 Logical Name System Services and DCL Commands

Logical Name Meaning

SYS$ERROR Default device to which the system writes error messages

SYS$COMMAND is created only for processes that execute LOGINOUT.


Usually, you create logical names only in your process logical name table. Most
entries in the process logical name table are made in user or supervisor mode.
Process logical names that are created in user mode are deleted whenever the
creating process runs an image down. The following DCL commands illustrate
this behavior with supervisor mode and /TABLE=LNM$PROCESS as the defaults
(default mode and default table) for the DEFINE command:
$ DEFINE/USER ABC XYZ
$ SHOW TRANSLATION ABC
ABC = XYZ
$ DIRECTORY
.
.
.
$ SHOW LOGICAL ABC
ABC = (undefined)
The DCL command DIRECTORY performs image rundown when it is finished
operating. At that time, all user-mode process-private logical names are deleted,
including the logical name ABC.
32.1.2.2.2 Job Logical Name Table The job logical name table is a shareable
table that is accessible by all processes within the same job tree. Whenever a
detached process is created, a job logical name table is created for this process
and for all of its potential subprocesses. At the same time, the process-private
logical name LNM$JOB is created in the process directory logical name table
LNM$PROCESS_DIRECTORY. The logical name LNM$JOB translates to the
name of the job logical name table.
Because the job logical name table already exists for the main process, only the
process-private logical name LNM$JOB is created when a subprocess is created.
The job logical name table contains the following three process-permanent logical
names for processes that execute LOGINOUT:

Logical Name Meaning


SYS$LOGIN Original default device and directory
SYS$LOGIN_DEVICE Original default device
SYS$SCRATCH Default device and directory to which temporary files are
written

Instead of creating these logical names within the process logical name table
LNM$PROCESS_TABLE for every process within a job tree, LOGINOUT creates
these logical names once when it is executed for the process at the root of the job
tree.
Additionally, the job logical name table can contain the following logical names:
• The logical name optionally specified and associated with a newly created
temporary mailbox

Logical Name and Logical Name Tables 32–5


Logical Name and Logical Name Tables
32.1 Logical Name System Services and DCL Commands

• The logical name optionally specified and associated with a privately mounted
volume
You do not need special privileges to modify the job logical name table. For a
discussion of privileges, see Section 32.3.
32.1.2.2.3 Group Logical Name Table The group logical name table contains
names that cooperating processes in the same group can use. You need the
GRPNAM privilege to add or delete a logical name in the group logical name
table. For a discussion of privileges, see Section 32.3.
A group logical name table is created when a top-level process with a unique
group code is created. The logical name LNM$GROUP exists in each process’s
process directory LNM$PROCESS_DIRECTORY. This logical name translates
into the name of the group logical name table.
32.1.2.2.4 System Logical Name Table The system logical name table
LNM$SYSTEM_TABLE contains names that all processes in the system can
access. This table includes the default names for all system-assigned logical
names. You need the SYSNAM or SYSPRV privilege to add or delete a logical
name in the system logical name table. For a discussion of privileges, see
Section 32.3.
The system logical table contains system-assigned logical names accessible to
all processes in the system. For example, the logical names SYS$LIBRARY and
SYS$SYSTEM provide logical names that all users can access to use the device
and directory that contain system files.

Logical Name Equivalence Name


SYS$LIBRARY SYS$SYSROOT:[SYSLIB]
SYS$SYSTEM SYS$SYSROOT:[SYSEXE]
... ...
... ...
... ...

The Logical Names section of the OpenVMS User’s Manual contains a list of these
system-assigned logical names.
32.1.2.2.5 Clusterwide Logical Name Table The clusterwide system logical
name table LNM$SYSCLUSTER_TABLE contains names that all processes in
the cluster can access. This is the clusterwide table that contains system logical
names. Because this table exists on all systems, the programs and command
procedures that use clusterwide logical names are transportable to both clustered
and nonclustered systems. The names in this table are available to anyone
translating a logical name using SHOW LOGICAL/SYSTEM and specifying a
table name of LNM$SYSTEM, or LNM$DCL_LOGICAL (DCL’s default table
search list), or LNM$FILE_DEV (system and RMS default).
LNM$SYSCLUSTER is the logical name for LNM$SYSCLUSTER_TABLE. It
is provided for convenience in referencing LNM$SYSCLUSTER_TABLE and
it is consistent in format with LNM$SYSTEM_TABLE and its logical name,
LNM$SYSTEM.
You need either the SYSNAM or SYSPRV privilege or write access to the table to
create or delete a name in this table.

32–6 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.1 Logical Name System Services and DCL Commands

The definition of LNM$SYSTEM has been expanded to include


LNM$SYSCLUSTER. When a system logical name is translated, the search
order is LNM$SYSTEM_TABLE, LNM$SYSCLUSTER.
The clusterwide logical name table LNM$CLUSTER_TABLE is the parent table
for all logical names, including LNM$SYSCLUSTER_TABLE. When you create a
new table using LNM$CLUSTER_TABLE as the parent table, the new table will
be available clusterwide.
LNM$CLUSTER is the logical name for LNM$CLUSTER_TABLE. It is provided
for convenience in referencing LNM$CLUSTER_TABLE.
You need either the SYSPRV privilege or write access to the table to create or
delete a name in this table.
Logical names in these two tables and their descendant tables are clusterwide.
Creation and deletion of cluster wide logical names are replicated on other
nodes of the cluster. Creation and deletion of clusterwide logical name tables
are replicated on other nodes of the cluster. When a node boots into a cluster, it
receives the current set of clusterwide logical names.
LNM$SYSCLUSTER_TABLE and LNM$CLUSTER_TABLE are created on all
systems, regardless of whether they are cluster nodes. Their existence enables
OpenVMS to maintain a consistent application environment.

32.1.3 Logical Name Table Names and Search Lists


The process, job, group, and system tables are typically referred to indirectly. For
example, the process table is usually specified as LNM$PROCESS. This indirect
reference enables you to redefine LNM$PROCESS as multiple equivalence names
and thus include one or more of your own tables in it.
The system table is specified as LNM$SYSTEM. The logical name LNM$SYSTEM
is defined as LNM$SYSTEM_TABLE, LNM$SYSCLUSTER. Thus, it includes
both systemwide names specific to the node and systemwide names common to
all nodes in the cluster. When a system name is translated, the search order is
LNM$SYSTEM_TABLE, LNM$SYSCLUSTER.
As described in the OpenVMS User’s Manual, OpenVMS automatically defines
a number of logical names, some of which are names of logical name tables. In
addition to the table names in the table in Section 32.1.2.2, OpenVMS defines
LNM$FILE_DEV and LNM$DCL_LOGICAL.
RMS and other system components specify the table LNM$FILE_DEV for file
specification and device name translations. Its definition is LNM$PROCESS,
LNM$JOB, LNM$GROUP, LNM$SYSTEM. Thus, the precedence order for
resolving logical names using this search list is as follows:
process-->job-->group-->system-->clusterwide system
The table name LNM$DCL_LOGICAL is used for the SHOW LOGICAL and
SHOW TRANSLATION DCL commands and for the logical name lexical
functions. Its definition is LNM$FILE_DEV.

Logical Name and Logical Name Tables 32–7


Logical Name and Logical Name Tables
32.1 Logical Name System Services and DCL Commands

32.1.4 Specifying the Logical Name Table Search List


Logical names exist as entries within logical name tables. When a logical name
is to be created, deleted, or translated, you must specify or take the default name
that designates the logical name table that contains the logical name. This name
possesses one or more of the following characteristics:
• It is the name of a logical name table.
• It is a logical name that iteratively translates in the process or system
directory table to the name of a logical name table.
• It is a multivalued logical name (search list) that iteratively translates to
the names of several logical name tables. The tables are used in the order in
which they appear.
As mentioned in Section 32.1.2, predefined logical names exist for certain logical
name tables. These predefined names begin with the prefix LNM$. You can
redefine these names to modify the search order or the tables used.
Instead of a fixed set of logical name tables and a rigidly defined order (process,
job, group, system) for searching those tables, you can specify which tables are
to be searched and the order in which they are to be searched. Logical names in
the directory tables are used to specify this searching order. By convention, each
class of logical name (for example, device or file specification) uses a particular
predefined name for this purpose.
For example, LNM$FILE_DEV is the logical name that defines the list of logical
name tables used whenever file specifications or device names are translated
by OpenVMS RMS or the I/O services. LNM$FILE_DEV is the default for file
specifications and device names. This name must translate to a list of one or
more logical name table names that specify the tables to be searched when
translating file specifications.
By default, LNM$FILE_DEV specifies that the process, job, group, and system
tables are all searched, in that order, and that the first match found is returned.
Logical name table names are translated from two tables: the process logical
name directory table LNM$PROCESS_DIRECTORY and the system logical name
directory table LNM$SYSTEM_DIRECTORY. The LNM$FILE_DEV logical name
table must be defined in one of these tables.
Thus, if identical logical names exist in the process and group tables, the process
table entry is found first, and the job and group tables are not searched. When
the process logical name table is searched, the entries are searched in order
of access mode, with user-mode entries matched first, supervisor-mode entries
second, and so on.
If you want to change the list of tables used for device and file specifications, you
can redefine LNM$FILE_DEV in the process directory table LNM$PROCESS_
DIRECTORY.

32.2 Creating User-Defined and Clusterwide Logical Name Tables


You can create process-private tables and shareable tables by calling the
SYS$CRELNT system service in a program, or with the DCL command CREATE
/NAME_TABLE. However, to create a shareable table you must have create (C)
access to the parent table and either SYSPRV privilege or write (W) access to
LNM$SYSTEM_DIRECTORY. If granted access, processes other than the creating
process can use shareable tables. For a discussion of privileges, see Section 32.3.

32–8 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.2 Creating User-Defined and Clusterwide Logical Name Tables

Processes other than the creating process cannot use logical names contained in
process-private tables.
You can assign protection to these shareable tables through the promsk
argument of the SYS$CRELNT system service. The promsk argument allows
you to specify the type of access for system, owner, group, and world users, as
follows:
• Read privileges allow access to names in the logical name table.
• Write privileges allow creation and deletion of names within the logical name
table.
• Delete privileges allow deletion of the logical name table.
• Create privilege to a table allows creation of children tables.
You can apply the following types of ownership and access to a shareable logical
name table:
• OWNERSHIP: SYSTEM(S), GROUP(G), or WORLD(W)
• ACCESS: READ(R), WRITE(W), CREATE(C), or DELETE(D)
If the promsk argument is omitted, complete access is granted to system and
owner, and no access is granted to group and world.
When a shareable table is created, both the specified promsk argument and the
current default security profile for tables are applied.
In addition, you can specify finer-grained access rights by modifying the access
control list using either the DCL command SET SECURITY or the SYS$SET_
SECURITY system service. For more information, see Chapter 25 and OpenVMS
Guide to System Security.
The length of logical names created in user-defined logical name tables cannot
exceed 255 characters. Equivalence strings cannot exceed 255 characters.

32.2.1 Creating Clusterwide Logical Name Tables


You might want to create additional clusterwide logical name tables for the
following purposes:
• For use by a multiprocess clusterwide application
• For sharing by members of a UIC group
You can create additional clusterwide logical name tables in the same way that
you can create additional process, job, and group logical name tables—with the
CREATE/NAME_TABLE command or with the $CRELNT system service. When
creating a clusterwide logical name table, you must specify the /PARENT_TABLE
qualifier and provide a value for the qualifier that is a clusterwide name. Any
existing clusterwide table used as the parent table will make the new table
clusterwide.
The following example shows how to create a clusterwide logical name table:
$ CREATE/NAME_TABLE/PARENT_TABLE=LNM$CLUSTER_TABLE -
_$ new_clusterwide_logical_name_table

Logical Name and Logical Name Tables 32–9


Logical Name and Logical Name Tables
32.2 Creating User-Defined and Clusterwide Logical Name Tables

To create clusterwide logical names that will reside in the clusterwide logical
name table you created, you define the new clusterwide logical name with the
DEFINE command, specifying your new clusterwide table’s name with the
/TABLE qualifier, as shown in the following example:
$ DEFINE/TABLE=new_clusterwide_logical_name_table logical_name -
_$ equivalence_string

32.3 Checking Access and Protection


When a user tries to access a logical name table, the operating system compares
the security profile of the user with the security profile of the table. The operating
system uses the following sequence:
1. Scans the table’s access control list for an entry matching any of the user’s
rights identifiers.
2. Evaluates the table’s protection mask against the user’s UIC.
3. Looks for special privileges.
The system checks the privileges in the user authorization file (UAF) granted
to you when your system manager sets up your account. Privileges allow you to
perform the functions listed in Table 32–2.

Table 32–2 Summary of Privileges


Privilege Function
GRPNAM Creates or deletes a logical name in your group logical name table
GRPPRV Creates or deletes a logical name in your group logical name table
SYSNAM Creates executive-mode or kernel-mode logical names; creates or deletes
a logical name in the system logical name table; deletes a logical name
or table at an inner access mode
SYSPRV Creates or deletes a logical name in the system logical name table
Creates or deletes a shareable table

The system also checks for read, write, and delete access.
For example, a user without SYSPRV privilege but with write access to
LNM$SYSTEM_DIRECTORY can create or delete a shareable table.
All users can create, delete, and translate their own process-private logical names
and process-private logical name tables.

32.4 Specifying Access Modes


You can specify the access mode of a logical name when you define the logical
name. If you do not specify an access mode, then the access mode defaults to that
of the caller of the SYS$CRELNM system service. If you specify the acmode
argument and the process has SYSNAM privilege, the logical name is created
with the specified access mode. Otherwise, the access mode cannot have more
privileges than the mode from which the service was requested. For information
about access modes, see Chapter 20 and the discussion of SYS$CRELNM in the
OpenVMS System Services Reference Manual.

32–10 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.4 Specifying Access Modes

A logical name table can contain multiple definitions of the same logical name
with different access modes. If a request to translate such a logical name specifies
the acmode argument, then the SYS$TRNLNM system service ignores all names
defined at a less privileged mode. A request to delete a logical name includes the
access mode of the logical name. Unless the process has the SYSNAM privilege,
the mode specified can be no more privileged than the caller.
By default, the command interpreter places entries made from the command
stream into the process-private logical name table; these are supervisor-mode
entries and are not deleted at image exit (except for the logical names defined
by the DCL commands ASSIGN/USER and DEFINE/USER). During certain
system operations, such as the activation of an image installed with privilege,
only executive-mode and kernel-mode logical names are used.
Logical names or logical name table names, which either an image running
in user mode or the DCL commands ASSIGN/USER and DEFINE/USER have
placed in a process-private logical name table, are automatically deleted at
image exit. Shareable user-mode names, however, survive image exit and process
deletion.

32.5 Translating Logical Names


Only one entry can exist for a particular logical name of a given access mode in
a logical name table. However, a logical name table can contain entries for the
same logical name at different access modes. Different logical name tables can
contain entries for the same logical name.
Because identical logical names can exist in more than one logical name table, the
translation that the system uses depends on the order in which it searches the
logical name tables. For example, when the system attempts to translate a logical
name to identify the location of a file, it uses the logical name LNM$FILE_DEV
to provide the list of tables in which to look for the name.
If, for example, a logical name exists in both the process and the group logical
name tables, the logical name within the process table is used.
By default, the DEFINE and DEASSIGN commands place names in, and delete
names from, your process table. However, you can request a different table with
the /TABLE qualifier, as shown in the following example:
$ DEFINE/TABLE=LNM$SYSTEM REVIEWERS DISK3:[PUBLIC]REVIEWERS.DIS
Any number of logical names can have the same equivalence name. Consider the
following examples of the logical name TERMINAL defined in several tables. The
logical name TERMINAL translates differently depending on the table specified.
Process Logical Name Table for Process A
The following process logical name table equates the logical name TERMINAL
to the specific terminal TTA2. The INFILE and OUTFILE logical names are
equated to disk specifications. The logical names were created from supervisor
mode.

Logical Name Equivalence Name Access Mode


INFILE DM1:[HIGGINS]TEST.DAT Supervisor
OUTFILE DM1:[HIGGINS]TEST.OUT Supervisor

Logical Name and Logical Name Tables 32–11


Logical Name and Logical Name Tables
32.5 Translating Logical Names

Logical Name Equivalence Name Access Mode

TERMINAL TTA2: Supervisor


... ... ...
... ... ...

To determine the equivalence string for the logical name TERMINAL in the
preceding table, enter the following command:
$ SHOW LOGICAL TERMINAL
The system returns the equivalence string TTA2:.
Job Logical Name Table
The portion of the following job logical name table assigns the logical name
TERMINAL to a virtual terminal VTA14. The logical name SYS$LOGIN is the
device and directory for the process when you log in. The SYS$LOGIN logical
name is defined in executive mode.

Logical Name Equivalence Name Access Mode


SYS$LOGIN DBA9:[HIGGINS] Executive
TERMINAL VTA14: User
... ... ...
... ... ...

To determine the equivalence string of the logical name TERMINAL defined in


the preceding table, enter the following command:
$ SHOW LOGICAL/JOB TERMINAL
The system returns the equivalence string VTA14: as the translation.
User-Defined Logical Name Table
The following user-defined logical name table (called LOG_TBL for purposes
of this discussion) contains a definition of TERMINAL as the mailbox device
MBA407. The multivalued logical name (search list) XYZ has two translations:
DISK1 and DISK3.

Logical Name Equivalence Name Access Mode


TERMINAL MBA407: Supervisor
XYZ DISK1:,DISK3: Supervisor
... ... ...
... ... ...

To determine the equivalence string for the logical name TERMINAL in the
preceding user-defined table, enter the following command:
$ SHOW LOGICAL/TABLE=LOG_TBL TERMINAL
The system returns the equivalence string MBA407. In order to use this
definition of TERMINAL as a device or file specification, you must redefine
the logical name LNM$FILE_DEV to reference the user-defined table, as follows:
$ DEFINE/TABLE=LNM$PROCESS_DIRECTORY LNM$FILE_DEV LOG_TBL, -
_$ LNM$PROCESS,LNM$JOB,LNM$GROUP,LNM$SYSTEM

32–12 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.5 Translating Logical Names

In this example, the DCL command DEFINE is used to redefine the default
search list LNM$FILE_DEV. The /TABLE qualifier specifies the table
LNM$PROCESS_DIRECTORY that is to contain the redefined search list. The
system searches the tables defined by LNM$FILE_DEV in the following order:
LOG_TBL, LNM$PROCESS, LNM$JOB, LNM$GROUP, and LNM$SYSTEM.
Logical Name Supersession
If the logical name TERMINAL is equated to TTA2 in the process table, as shown
in the previous examples, and the process subsequently equates the logical name
TERMINAL to TTA3, the equivalence of TERMINAL TTA2 is replaced by the new
equivalence name. The successful return status code SS$_SUPERSEDE indicates
that a new entry replaced an old one.
The definitions of TERMINAL in the job table and in the user-defined table LOG_
TBL are unaffected.

32.6 Specifying Attributes


Generally, attributes specified through the logical name system services perform
two functions: they affect the creation of logical names or govern how the system
service operates, and they affect the translation of logical names and equivalence
strings.
Attributes that affect the creation of the logical names are specified optionally in
the attr argument of a system service call. The attr argument attributes that
are available from the SYS$CRELNM system service are as follows:

Attribute Meaning
LNM$M_CONFINE Prevents this process-private logical name from being copied to
subprocesses. Subprocesses are created by the DCL command
SPAWN or by the run-time library LIB$SPAWN routine.
LNM$M_NO_ALIAS Prevents creation of a duplicate logical name in the specified
logical name table at an outer access mode. If another logical
name already exists in the table at an outer access mode, that
name is deleted.

The attr argument attributes that are available from the SYS$CRELNT system
service are as follows:

Attribute Meaning
LNM$M_CONFINE Prevents this process-private logical table from being copied to
subprocesses. Subprocesses are created by the DCL command
SPAWN or by the run-time library LIB$SPAWN routine.
LNM$M_CREATE_IF Prevents creation of a nonclusterwide logical name table if the
specified table already exists at the specified access mode in the
appropriate directory table. This attribute applies only to local
tables.
LNM$M_NO_ALIAS Prevents creation of a logical name table at an outer access
mode in a directory table if the table name already exists in the
directory table.

The attr argument attributes that are available from the SYS$TRNLNM system
service are as follows:

Logical Name and Logical Name Tables 32–13


Logical Name and Logical Name Tables
32.6 Specifying Attributes

Attribute Meaning
LNM$M_CASE_BLIND Governs the translation process and causes
SYS$TRNLNM to ignore uppercase and lowercase
differences in letters when searching for logical names.
LNM$M_INTERLOCKED Ensures that any clusterwide logical name
modifications in progress are completed before the
name is translated.

The translation attributes LNM$M_CONCEALED and LNM$M_TERMINAL


associated with logical names and equivalence strings are specified optionally
through the LNM$_ATTRIBUTES item code in the itmlst argument of the
SYS$CRELNM system service call. The equivalence name attributes for
SYS$CRELNM are as follows:

Attribute Meaning
LNM$M_CONCEALED Indicates that the equivalence string at the current
index value for the logical name is an OpenVMS RMS
concealed device name.
LNM$M_TERMINAL Indicates that the equivalence strings cannot be
translated further.

When the item code LNM$_ATTRIBUTES is specified through SYS$TRNLNM,


the system returns the current attributes associated with the logical name and
equivalence string at the current index value. Since a logical name can have
more than one equivalence name, each equivalence name is identified by an
index value. The item code LNM$_INDEX of SYS$TRNLNM searches for an
equivalence name that has the specified index value.
The equivalence returned attributes for SYS$TRNLNM are as follows:

Attribute Meaning
LNM$M_CONCEALED Indicates that the equivalence string at the current
index value for the logical name is an OpenVMS RMS
concealed device name.
LNM$M_CONFINE Indicates that the logical name cannot be used by
spawned subprocesses. Subprocesses are created by
the DCL command SPAWN or by the run-time library
LIB$SPAWN routine.
LNM$M_CRELOG Indicates that the logical name was created by the
SYS$CRELOG system service.
LNM$M_EXISTS Indicates that the equivalence string at the specified
index value exists.
LNM$M_NO_ALIAS Indicates that if the logical name already exists in the
table, it cannot be created in that table at an outer
access mode.
LNM$M_TABLE Indicates that the logical name is the name of a logical
name table.
LNM$M_TERMINAL Indicates that the equivalence strings cannot be
translated further.
LNM$V_CLUSTERWIDE Indicates that the logical name is clusterwide.

32–14 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.6 Specifying Attributes

The attributes of multiple equivalence strings do not have to match. For more
information about attributes, refer to the appropriate system service in the
OpenVMS System Services Reference Manual.

32.7 Establishing Logical Name Table Quotas


A logical name table quota is the number of bytes allocated in memory for
logical names contained in a logical name table. Logical name table quotas are
established in the following instances:
• When the system is initialized
• When a process is created
• When logical name tables are created
Each logical name table has a quota associated with it that limits the number of
bytes of memory (either process pool or system paged pool) that can be occupied
by the names defined in the table. The quota for a table is established when the
table is created.
If no quota is specified, the newly created table has unlimited quota. Note that
this table can expand to consume all available process or system memory, and
all users with write access to such a shareable table can cause the unlimited
consumption of system paged pool.

32.7.1 Directory Table Quotas


When the system is initialized, unlimited quota is automatically established for
the system directory table LNM$SYSTEM_DIRECTORY.
When you log in to the system, unlimited quota is automatically established for
the process directory table LNM$PROCESS_DIRECTORY.

32.7.2 Default Logical Name Table Quotas


The process, group, system, clusterwide system, and clusterwide parent logical
name tables have unlimited quota.

32.7.3 Job Logical Name Table Quotas


Because the job logical name table is a shareable table, and because you do not
need special privileges to create logical names within it, the quota allocated
to this logical name table is constrained at the time the table is created. The
following three mechanisms specify the quota for the job logical name table at the
time of its creation:
• For all processes that activate LOGINOUT, the quota for the job logical name
table is obtained from the system authorization file. This allows the quota for
the job to be specified on a user-by-user basis. You can modify the job logical
name table quota by specifying a value with the DCL command AUTHORIZE
/JTQUOTA.
• For all processes that do not activate LOGINOUT, the quota for the job logical
name table can be specified as a quota list item (PQL$_JTQUOTA) in the call
to the Create Process (SYS$CREPRC) system service. If a detached process is
to be created by means of the DCL command RUN/DETACHED, then you can
use the /JOB_TABLE_QUOTA qualifier to specify the SYS$CREPRC quota
list item.

Logical Name and Logical Name Tables 32–15


Logical Name and Logical Name Tables
32.7 Establishing Logical Name Table Quotas

• For all processes that do not activate LOGINOUT and do not specify a PQL$_
JTQUOTA quota list item in their call to SYS$CREPRC, the quota for the
job logical name table is taken from the dynamic System Generation utility
(SYSGEN) parameter PQL$_DJTQUOTA. You can use SYSGEN to display
both PQL$_DJTQUOTA and PQL$_MJTQUOTA, the default and minimum
job logical name table quotas, respectively.

32.7.4 User-Defined Logical Name Table Quotas


User-defined logical name tables can be created with either an explicit limited
quota or no quota limit.
The presence of user-defined logical name table quotas eliminates the need for a
privilege (for example, SYSNAM or GRPNAM) to control consumption of paged
pool when you create logical names in a shareable table.

32.8 Interprocess Communication


Although logical names typically represent device and file names, shareable
logical names can also be used to pass information among cooperating processes.
When a process creates a shareable logical name, it can store up to 255 bytes of
information in each equivalence name. The processes can agree to any arbitrary
form for the information. Cooperating processes can translate the shareable
name to retrieve the data in its eqivalence names.
The operating system ensures one process cannot change a logical name at the
same time another process is either translating the name or trying to change
it. In other words, the synchronization provided by OpenVMS allows multiple
concurrent readers or a single writer to access shared logical names that are not
clusterwide.
Each instance of OpenVMS has its own shareable logical name database. When
a process creates a new shareable logical name, that name can be translated
immediately by any other process in the system with access to the containing
table.
On an OpenVMS cluster, each node has its own shareable logical name database.
In addition, the clusterwide tables and their names are replicated on each node
of the cluster. Cluster communication and replication time can delay the time
when a clusterwide logical name is visible on other cluster nodes. For increased
performance, the default synchronization provided by OpenVMS for clusterwide
logical names allows a single writer to access shared logical names, but it does
not block concurrent readers.
Synchronization provided by OpenVMS may therefore be insufficient for a given
application. In particular, the following circumstances require that an application
provide additional synchronization:
• Retrieval of the most recent version of a clusterwide logical name
• Multiple modifiers of a given logical name, clusterwide or local
If you have an application where a logical name translator must be certain of
getting the most recent definition of a clusterwide logical name, you should
specify in the application the LNM$M_INTERLOCKED attribute in the attr
argument. Use of this attribute synchronizes the translation with any pending
changes to clusterwide names and ensures that the translation retrieves the most
recent definition of the name. Use of this attribute to translate a local name adds
a small amount of overhead but is otherwise harmless.

32–16 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.8 Interprocess Communication

No logical name service provides an atomic modify of a logical name, clusterwide


or local; it is thus not possible in one system service call to read the information
in a logical name’s equivalence names and recreate it with updated information.
This means that if you have an interprocess application in which multiple
processes modify a logical name, you must provide additional synchronization to
create a critical section containing the SYS$TRNLNM and SYS$CRELNM calls.
For example, your application could take the following steps:
1. Call SYS$ENQ to acquire a restrictive lock on an application-specific resource
name.
2. Call SYS$TRNLNM to retrieve the current equivalence names, modify them,
and call SYS$CRELNM to recreate the logical name. Use the LNM$M_
INTERLOCKED attribute if the name could be clusterwide.
3. Call SYS$DEQ to release the lock.
Because locks synchronize processes running on multiple cluster nodes, this
method synchronizes processes that are running on a single node or multiple
nodes.

32.9 Using Logical Name and Equivalence Name Format


Conventions
The operating system uses special conventions for assigning logical names to
equivalence names and for translating logical names. These conventions are
generally transparent to user programs; however, you should be aware of the
programming considerations involved.
If a logical name string presented in I/O services is preceded by an underscore
( _ ), the I/O services bypass logical name translation, drop the underscore, and
treat the logical name as a physical device name.
When you log in, the system creates default logical name table entries for
process-permanent files. The equivalence names for these entries (for example,
SYS$INPUT and SYS$OUTPUT) are preceded by a 4-byte header that contains
the following information:

Byte Contents
0 ^X1B (escape character)
1 ^X00
2–3 OpenVMS RMS Internal File Identifier (IFI)

This header is followed by the equivalence name string. If any of your program
applications must translate system-assigned logical names, you must prepare the
program both to check for the existence of this header and to use only the desired
part of the equivalence string. The following program demonstrates how to do
this:

#include <stdio.h>
#include <lnmdef.h>
#include <ssdef.h>
#include <descrip.h>
#include <ctype.h>
#include <string.h>
#define HEADER 4

Logical Name and Logical Name Tables 32–17


Logical Name and Logical Name Tables
32.9 Using Logical Name and Equivalence Name Format Conventions

/* Define an item descriptor */


struct {
unsigned short buflen, item_code;
void *bufaddr;
void *retlenaddr;
unsigned int terminator;
}item_lst;

main() {
unsigned int status,len,i;
char resstring[LNM$C_NAMLENGTH];
$DESCRIPTOR(tabdesc,"LNM$FILE_DEV");
$DESCRIPTOR(logdesc,"SYS$OUTPUT");
item_lst.buflen = LNM$C_NAMLENGTH;
item_lst.item_code = LNM$_STRING;
item_lst.bufaddr = resstring;
item_lst.retlenaddr = 0;
item_lst.terminator = 0;
/* Translate the logical name */
status = SYS$TRNLNM( 0, /* attr - attributes of the logical name */
&tabdesc, /* tabnam - logical name table */
&logdesc, /* lognam - logical name */
0, /* acmode - accessm mode */
&item_lst); /* itmlst - item list */
if((status & 1) != 1)
LIB$SIGNAL( status );
/*
Examine 4-byte header
Is first character an escape char?
If so, dump the header
*/
if( resstring[0] == 0x1B) {
printf("\nDumping the header...\n");
for(i = 0; i < HEADER; i++)
printf(" Byte %d: %X\n",i,resstring[i]);
printf("\nEquivalence string: %s\n",(resstring + HEADER));
}
else
printf("Header not found\n");
}

32.10 Using Logical Names and Logical Name Table System


Services in Programs
The following sections describe by programming examples how to use
SYS$CRELNM, SYS$CRELNT, SYS$DELLNM, and SYS$TRNLNM system
services.

32.10.1 Using SYS$CRELNM to Create a Logical Name


To perform an assignment in a program, you must provide character-string
descriptors for the name strings, select the table to contain the logical name,
and use the SYS$CRELNM system service as shown in the following example.
In either case, the result is the same: the logical name DISK is equated to the
physical device name DUA2 in table LNM$JOB.

32–18 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.10 Using Logical Names and Logical Name Table System Services in Programs

#include <stdio.h>
#include <lnmdef.h>
#include <descrip.h>
#include <string.h>
#include <ssdef.h>
/* Define an item descriptor */
struct itm {
unsigned short buflen, item_code;
void *bufaddr;
void *retlenaddr;
};
/* Declare an item list */
struct {
struct itm items2];
unsigned int terminator;
}itm_lst;
main() {
static char eqvnam[] = "DUA2:";
unsigned int status, lnmattr;
$DESCRIPTOR(logdesc,"DISK");
$DESCRIPTOR(tabdesc,"LNM$JOB");
lnmattr = LNM$M_TERMINAL;
/* Initialize the item list */
itm_lst.items[0].buflen = 4;
itm_lst.items[0].item_code = LNM$_ATTRIBUTES;
itm_lst.items[0].bufaddr = &lnmattr;
itm_lst.items[0].retlenaddr = 0;
itm_lst.items[1].buflen = strlen(eqvnam);
itm_lst.items[1].item_code = LNM$_STRING;
itm_lst.items[1].bufaddr = eqvnam;
itm_lst.items[1].retlenaddr = 0;
itm_lst.terminator = 0;
/* Create the logical name */
status = SYS$CRELNM(0, /* attr - attributes */
&tabdesc, /* tabnam - logical table name */
&logdesc, /* lognam - logical name */
0, /* acmode - access mode 0 means use the */
/* access mode of the caller=user mode */
&itm_lst); /* itmlst - item list */
if((status & 1) != 1)
LIB$SIGNAL(status);
}

Note that the translation attribute is specified as terminal. This attribute


indicates that iterative translation of the logical name DISK ends when the
equivalence string DUA2 is returned. In addition, because the acmode argument
was not specified, the access mode of the logical name DISK is the access mode
from which the image requested the SYS$CRELNM service.
The following example shows how a process-private logical name with multiple
equivalence names can be created in user mode by an image:

Logical Name and Logical Name Tables 32–19


Logical Name and Logical Name Tables
32.10 Using Logical Names and Logical Name Table System Services in Programs

#include <stdio.h>
#include <lnmdef.h>
#include <ssdef.h>
#include <descrip.h>
/* Define an item descriptor */
struct lst {
unsigned short buflen, item_code;
void *bufaddr;
void *retlenaddr;
};
/* Declare an item list */
struct {
struct lst items[2];
unsigned int terminator;
}item_lst;
/* Equivalence name strings */
static char eqvnam1[] = "XYZ";
static char eqvnam2[] = "DEF";
main() {
unsigned int status;
$DESCRIPTOR(logdesc,"ABC");
$DESCRIPTOR(tabdesc,"LNM$PROCESS");
item_lst.items[0].buflen = strlen(eqvnam1);
item_lst.items[0].item_code = LNM$_STRING;
item_lst.items[0].bufaddr = eqvnam1;
item_lst.items[0].retlenaddr = 0;
item_lst.items[1].buflen = strlen(eqvnam2);
item_lst.items[1].item_code = LNM$_STRING;
item_lst.items[1].bufaddr = eqvnam2;
item_lst.items[1].retlenaddr = 0;
item_lst.terminator = 0;
/* Create a logical name */
status = SYS$CRELNM( 0, /* attr - attributes of logical name */
&tabdesc, /* tabnam - name of logical name table */
&logdesc, /* lognam - name of logical name */
0, /* acmode - access mode 0 means use the */
/* access mode of the caller=user mode */
&item_lst); /* itm_lst - item list */
if((status & 1) != 1)
LIB$SIGNAL(status);
}

In the preceding example, logical name ABC was created and represents a search
list with two equivalence strings, XYZ and DEF. Each time the LNM$_STRING
item code of the itmlst argument is invoked, an index value is assigned to the
next equivalence string. The newly created logical name and its equivalence
string are contained in the process logical name table LNM$PROCESS_TABLE.
The following example illustrates the creation of a logical name in supervisor
mode through DCL:
$ DEFINE/SUPERVISOR_MODE/TABLE=LNM$PROCESS ABC XYZ,DEF
In the preceeding example, supervisor mode and /TABLE=LNM$PROCESS are
the defaults (default mode and default table) for the DEFINE command.

32–20 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.10 Using Logical Names and Logical Name Table System Services in Programs

32.10.2 Using SYS$CRELNT to Create Logical Name Tables


The Create Logical Name Table (SYS$CRELNT) system service creates logical
name tables. Logical name tables can be created in any access mode depending on
the privileges of the calling process. A user-specified logical name that identifies
a process-private created logical name table is stored in the process directory
table LNM$PROCESS_DIRECTORY. The name of a shareable table is stored in
the system directory table LNM$SYSTEM_DIRECTORY.
The following example illustrates a call to the SYS$CRELNT system service:

#include <stdio.h>
#include <ssdef.h>
#include <lnmdef.h>
#include <descrip.h>

main() {
unsigned int status, tab_attr=LNM$M_CONFINE, tab_quota=5000;
$DESCRIPTOR(tabdesc,"LOG_TABLE");
$DESCRIPTOR(pardesc,"LNM$PROCESS_TABLE");
/* Create the logical name table */
status = SYS$CRELNT(&tab_attr, /* attr - table attributes */
0, /* resnam - logical table name */
0, /* reslen - length of table name */
&tab_quota, /* quota - max no. of bytes allocated */
/* for names in this table */
0, /* promsk - protection mask */
&tabdesc, /* tabnam - name of new table */
&pardesc, /* partab - name of parent table */
0); /* acmode - access mode */
if((status & 1) != 1) {
LIB$SIGNAL(status);
}

In this example, a user-defined table LOG_TABLE is created with an explicit


quota of 5000 bytes. The name of the newly created table is an entry in the
process-private directory LNM$PROCESS_DIRECTORY. The quota of 5000
bytes is deducted from the parent table LNM$PROCESS_TABLE. Because the
CONFINE attribute is associated with the logical name table, the table cannot be
copied from the process to its spawned processes.

32.10.3 Using SYS$DELLNM to Delete Logical Names


The Delete Logical Name (SYS$DELLNM) system service deletes entries from a
logical name table. When you write a call to the SYS$DELLNM system service,
you can specify a single logical name to delete, or you can specify that you want
to delete all logical names from a particular table. For example, the following call
deletes the process logical name TERMINAL from the job logical name table:

#include <stdio.h>
#include <lnmdef.h>
#include <ssdef.h>
#include <descrip.h>
main() {
unsigned int status;
$DESCRIPTOR(logdesc,"DISK");
$DESCRIPTOR(tabdesc,"LNM$JOB");

Logical Name and Logical Name Tables 32–21


Logical Name and Logical Name Tables
32.10 Using Logical Names and Logical Name Table System Services in Programs

/* Delete the logical name */


status = SYS$DELLNM(&tabdesc, /* tabnam - logical table name */
&logdesc, /* lognam - logical name */
0); /* acmode - access mode */
if ((status & 1) != 1)
LIB$SIGNAL(status);
}

For information about access modes and the deletion of logical names, see
Chapter 20 and Appendix B.

32.10.4 Using SYS$TRNLNM to Translate Logical Names


The Translate Logical Name (SYS$TRNLNM) system service translates a logical
name to its equivalence string. In addition, SYS$TRNLNM returns information
about the logical name and equivalence string.
The system service call to SYS$TRNLNM specifies the tables to search for the
logical name. The tabnam argument can be either the name of a logical name
table or a logical name that translates to a list of one or more logical name tables.
Because logical names can have many equivalence strings, you can specify which
equivalence string you want to receive.
A number of system services that require a device name accept a logical name
and translate the logical name iteratively until a physical device name is found
(or until the system default number of logical name translations has been
performed, typically 10). These services implicitly use the logical name table
name LNM$FILE_DEV. For more information about LNM$FILE_DEV, refer to
Section 32.1.4.
The following system services perform iterative logical name translation
automatically:
• Allocate Device (SYS$ALLOC)
• Assign I/O Channel (SYS$ASSIGN)
• Broadcast (SYS$BRDCST)
• Create Mailbox (SYS$CREMBX)
• Deallocate Device (SYS$DALLOC)
• Dismount Volume (SYS$DISMOU)
• Get Device/Volume Information (SYS$GETDVI)
• Mount Volume (SYS$MOUNT)
In many cases, however, a program must perform the logical name translation
to obtain the equivalence name for a logical name outside the context of a
device name or file specification. In that case, you must supply the name of
the table or tables to be searched. The SYS$TRNLNM system service searches
the user-specified logical name tables for a specified logical name and returns
the equivalence name. In addition, SYS$TRNLNM returns attributes that are
specified optionally for the logical name and equivalence string.
The following example shows a call to the SYS$TRNLNM system service to
translate the logical name ABC:

32–22 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.10 Using Logical Names and Logical Name Table System Services in Programs

#include <stdio.h>
#include <lnmdef.h>
#include <descrip.h>
#include <ssdef.h>
/* Define an item descriptor */
struct itm {
unsigned short buflen, item_code;
void *bufaddr;
void *retlenaddr;
};
/* Declare an item list */
struct {
struct itm items[2];
unsigned int terminator;
}trnlst;
main() {
char eqvbuf1[LNM$C_NAMLENGTH], eqvbuf2[LNM$C_NAMLENGTH];
unsigned int status, trnattr=LNM$M_CASE_BLIND;
unsigned int eqvdesc1, eqvdesc2;
$DESCRIPTOR(logdesc,"ABC");
$DESCRIPTOR(tabdesc,"LNM$FILE_DEV");
/* Assign values to the item list */
trnlst.items[0].buflen = LNM$C_NAMLENGTH;
trnlst.items[0].item_code = LNM$_STRING;
trnlst.items[0].bufaddr = eqvbuf1;
trnlst.items[0].retlenaddr = &eqvdesc1;
trnlst.items[1].buflen = LNM$C_NAMLENGTH;
trnlst.items[1].item_code = LNM$_STRING;
trnlst.items[1].bufaddr = eqvbuf2;
trnlst.items[1].retlenaddr = &eqvdesc2;
trnlst.terminator = 0;
/* Translate the logical name */
status = SYS$TRNLNM(&trnattr, /* attr - attributes */
&tabdesc, /* tabnam - table name */
&logdesc, /* lognam - logical name */
0, /* acmode - access mode */
&trnlst); /* itmlst - item list */
if((status & 1) != 1)
LIB$SIGNAL(status);
}

This call to the SYS$TRNLNM system service results in the translation of the
logical name ABC. In addition, LNM$FILE_DEV is specified in the tabnam
argument as the search list that SYS$TRNLNM is to use to find the logical name
ABC. The logical name ABC was assigned two equivalence strings. The LNM$_
STRING item code in the itmlst argument directs SYS$TRNLNM to look for
an equivalence string at the current index value. Note that the LNM$_STRING
item code is invoked twice. The equivalence strings are placed in the two output
buffers, EQVBUF1 and EQVBUF2, described by TRNLIST.
The attribute LNM$M_CASE_BLIND governs the translation process. The
SYS$TRNLNM system service searches for the equivalence strings without
regard to uppercase or lowercase letters. The SYS$TRNLNM system service
matches any of the following character strings: ABC, aBC, AbC, abc, and so forth.

Logical Name and Logical Name Tables 32–23


Logical Name and Logical Name Tables
32.10 Using Logical Names and Logical Name Table System Services in Programs

The output equivalence name string length is written into the first word of the
character string descriptor. This descriptor can then be used as input to another
system service.

32.10.5 Using SYS$CRELNM, SYS$TRNLNM, and SYS$DELLNM in a Program


Example
In the following example, the Fortran program CALC.FOR creates a spawned
subprocess to perform an iterative calculation. The logical name REP_NUMBER
specifies the number of times that REPEAT should perform the calculation.
Because the two processes are part of the same job, REP_NUMBER is placed
in the job logical name table LNM$JOB. (Note that logical name table names
are case sensitive. Specifically, LNM$JOB is a system-defined logical name that
refers to the job logical name table; lnm$job is not.)
PROGRAM CALC
! Status variable and system routines
INCLUDE ’($LNMDEF)’
INCLUDE ’($SYSSRVNAM)’
INTEGER*4 STATUS
INTEGER*2 NAME_LEN,
2 NAME_CODE
INTEGER*4 NAME_ADDR,
2 RET_ADDR /0/,
2 END_LIST /0/
COMMON /LIST/ NAME_LEN,
2 NAME_CODE,
2 NAME_ADDR,
2 RET_ADDR,
2 END_LIST
CHARACTER*3 REPETITIONS_STR
INTEGER REPETITIONS
EXTERNAL CLI$M_NOLOGNAM,
2 CLI$M_NOCLISYM,
2 CLI$M_NOKEYPAD,
2 CLI$M_NOWAIT
NAME_LEN = 3
NAME_CODE = (LNM$_STRING)
NAME_ADDR = %LOC(REPETITIONS_STR)
STATUS = SYS$CRELNM (,’LNM$JOB’,’REP_NUMBER’,,NAME_LEN)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
MASK = %LOC (CLI$M_NOLOGNAM) .OR.
2 %LOC (CLI$M_NOCLISYM) .OR.
2 %LOC (CLI$M_NOKEYPAD) .OR.
2 %LOC (CLI$M_NOWAIT)
STATUS = LIB$GET_EF (FLAG)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
STATUS = LIB$SPAWN (’RUN REPEAT’,,,MASK,,,,FLAG)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
END

32–24 Logical Name and Logical Name Tables


Logical Name and Logical Name Tables
32.10 Using Logical Names and Logical Name Table System Services in Programs

PROGRAM REPEAT
INTEGER STATUS,
2 SYS$TRNLNM,SYS$DELLNM
INTEGER*4 REITERATE,
2 REPEAT_STR_LEN
CHARACTER*3 REPEAT_STR
! Item list for SYS$TRNLNM
INTEGER*2 NAME_LEN,
2 NAME_CODE
INTEGER*4 NAME_ADDR,
2 RET_ADDR,
2 END_LIST /0/
COMMON /LIST/ NAME_LEN,
2 NAME_CODE,
2 NAME_ADDR,
2 RET_ADDR,
2 END_LIST
NAME_LEN = 3
NAME_CODE = (LNM$_STRING)
NAME_ADDR = %LOC(REPEAT_STR)
RET_ADDR = %LOC(REPEAT_STR_LEN)
STATUS = SYS$TRNLNM (,
2 ’LNM$JOB’, ! Logical name table
2 ’REP_NUMBER’,, ! Logical name
2 NAME_LEN) ! List requesting equivalence string
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
READ (UNIT = REPEAT_STR,
2 FMT = ’(I3)’) REITERATE
DO I = 1, REITERATE
END DO
STATUS = SYS$DELLNM (’LNM$JOB’, ! Logical name table
2 ’REP_NUMBER’,) ! Logical name
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
END

Logical Name and Logical Name Tables 32–25


33
Image Initialization

This chapter describes the system declaration mechanism, including


LIB$INITIALIZE, which performs calls to any initialization routine declared
for the image by the user. However, use of LIB$INITIALIZE is discouraged and
should be used only when no other method is suitable. This chapter contains the
following sections:
Section 33.1 describes the steps to perform image initialization.
Section 33.2 describes the argument list that is passed from the command
interpreter, the debugger, or LIB$INITIALIZE to the main program.
Section 33.3 describes how a library or user program can declare an initialization
routine.
Section 33.4 describes how the LIB$INITIALIZE dispatcher calls the initialization
routine in a list.
Section 33.5 describes the options available to an initialization routine.
Section 33.6 illustrates with a code example several functions of an initialization
routine on both VAX and Alpha systems.

33.1 Initializing an Image


In most cases, both user and library routines are self-initializing. This means
that they can process information with no special action required by the calling
program. Initialization is automatic in two situations:
• When the routine’s statically allocated data storage is initialized at compile or
link time
• When a statically allocated flag is tested and set on each call so that
initialization occurs only on the first call
Any special initialization, such as a call to other routines or to system services,
can be performed on the first call before the main program is initialized. For
example, you can establish a new environment to alter the way errors are
handled or the way messages are printed.
Such special initialization is required only rarely; however, when it is required,
the caller of the routine does not need to make an explicit initialization call. The
run-time library provides a system declaration mechanism that performs all such
initialization calls before the main program is called. Thus, special initialization
is invisible to later callers of the routine.
On VAX systems, before the main program or main routine is called, a number
of system initialization routines are called as specified by a 1-, 2-, or 3-longword
initialization list set up by the linker.

Image Initialization 33–1


Image Initialization
33.1 Initializing an Image

On Alpha systems, before the main program or main routine is called, a number
of system initialization routines are called as specified by a 1-, 2-, or 3-quadword
initialization list set up by the linker.
On VAX systems, the initialization list consists of the following (in order):
• The addresses of the debugger (if present)
• The LIB$INITIALIZE routine (if present)
• The entry point of the main program or main routine
On Alpha systems, the initialization list consists of the following (in order):
• The procedure value addresses of the debugger (if present)
• The LIB$INITIALIZE routine (if present)
• The entry point of the main program or main routine
The following initialization steps take place:
1. The image activator maps the user program into the address space of the
process and sets up useful information, such as the program name. Then it
starts the command language interpreter (CLI).
2. The CLI sets up an argument list and calls the next routine in the
initialization list (debugger, LIB$INITIALIZE, main program, or main
routine).
3. On VAX systems, the debugger, if present, initializes itself and calls the next
routine in the initialization list (LIB$INITIALIZE, main program, or main
routine).
On Alpha systems, the CLI calls the debugger, if present, to set the initial
breakpoints. Then the CLI calls the next entry in the vector.
4. The LIB$INITIALIZE library routine, if present, calls each library and user
initialization routine declared using the system LIB$INITIALIZE mechanism.
Then it calls the main program or main routine.
5. The main program or main routine executes and, at the user’s discretion,
accesses its argument list to scan the command or to obtain information about
the image. The main program or main routine can then call other routines.
6. Eventually, the main program or main routine terminates by executing a
return instruction (RET) with R0 set to a standard completion code to indicate
success or failure, where bit <0> equals 1 (success) or 0 (failure).
7. The completion code is returned to LIB$INITIALIZE (if present), the
debugger (if present), and, finally, to the CLI, which issues a SYS$EXIT
system service with the completion status as an argument. Any declared exit
handlers are called at this point.

Note
Main programs should not call the SYS$EXIT system service directly. If
they do, other programs cannot call them as routines.

33–2 Image Initialization


Image Initialization
33.1 Initializing an Image

Figure 33–1 and Figure 33–2 illustrate the sequence of calls and returns in a
typical image initialization. Each box is a routine activation as represented
on the image stack. The top of the stack is at the top of the figure. Each
upward arrow represents the result of a call instruction that creates a routine
activation on the stack to which control is being transferred. Each downward
arrow represents the result of a RET (return) instruction. A RET instruction
removes the routine activation from the stack and causes control to be transferred
downward to the next box.
A user program can alter the image initialization sequence by making a program
section (PSECT) contribution to PSECT LIB$INITIALIZE and by declaring
EXTERNAL LIB$INITIALIZE. This adds the optional initialization steps
shown in Figure 33–1 and Figure 33–2 labeled ‘‘Program Section Contribution
to LIB$INITIALIZE.’’ (A program section is a portion of a program with a
given protection and set of storage management attributes. Program sections
that have the same attributes are gathered together by the linker to form
an image section.) If the initialization routine also performs a coroutine call
back to LIB$INITIALIZE, the optional steps labeled ‘‘Coroutine Call Back to
LIB$INITIALIZE’’ in Figure 33–1 and Figure 33–2 are added to the image
initialization sequence.
On VAX systems, Figure 33–1 shows the call instruction calling the debugger, if
present, and the debugger then directly calling LIB$INITIALIZE and the main
program.

Image Initialization 33–3


Image Initialization
33.1 Initializing an Image

Figure 33–1 Sequence of Events During Image Initialization on VAX Systems

Library User User


Procedure Procedure* Procedure*

Library User
Procedure User Procedure*
Procedure*

Initialization Main Program*


Procedure*

LIB$INITIALIZE
Coroutine Call Back to
LIB$INITIALIZE
(Optional)

Initialization
Initialization Procedure*
Procedure*

LIB$INITIALIZE Program Section


Contribution to
LIB$INITIALIZE
(Optional)
Debugger
(If Present)

Command
Language
Interpreter

Image
Activator
*These procedures are (or can be) user supplied.
ZK−1977−GE

On Alpha systems, Figure 33–2 shows the call instruction calling the debugger, if
present, to set a breakpoint at the main program’s entry point.

33–4 Image Initialization


Image Initialization
33.1 Initializing an Image

Figure 33–2 Sequence of Events During Image Initialization on Alpha Systems

Library User User


Procedure Procedure* Procedure*

Library User
Procedure User Procedure*
Procedure*

Initialization Main Program*


Procedure*

LIB$INITIALIZE
Coroutine Call Back to
LIB$INITIALIZE
(Optional)

Initialization
Initialization Procedure*
Procedure*

LIB$INITIALIZE Program Section


Contribution to
LIB$INITIALIZE
(Optional)
Debugger
(If Present)

Command
Language
Interpreter

Image
Activator
*These procedures are (or can be) user supplied.

ZK−5911A−GE

33.2 Initializing an Argument List


The following argument list is passed from the CLI, the debugger, or
LIB$INITIALIZE to the main program. This argument list is the same for
each routine activation.
(start ,cli-coroutine [,image-info])
The start argument is the address of the entry in the initialization vector that is
used to perform the call.
The cli-coroutine argument is the address of a CLI coroutine to obtain command
arguments. For more information, see the OpenVMS Utility Routines Manual.
The image-info argument is useful image information, such as the program
name.

Image Initialization 33–5


Image Initialization
33.2 Initializing an Argument List

The debugger or LIB$INITIALIZE, or both, can call the next routine in the
initialization chain using the following coding sequence:
.
.
.
ADDL #4, 4(AP) ; Step to next initialization list entry
MOVL @4(AP), R0 ; R0 = next address to call
CALLG (AP), (R0) ; Call next initialization routine
.
.
.
This coding sequence modifies the contents of an argument list entry. Thus, the
sequence does not follow the OpenVMS calling standard. However, the argument
list can be expanded in the future without requiring any change either to the
debugger or to LIB$INITIALIZE.

33.3 Declaring Initialization Routines


Any library or user program module can declare an initialization routine. This
routine is called when the image is started. The declaration is made by making
a contribution to the LIB$INITIALIZE program section, which contains a list
of routine entry point addresses to be called before the main program or main
routine is called.
The following VAX MACRO example declares an initialization routine by placing
the routine entry address INIT_PROC in the list:
.EXTRN LIB$INITIALIZE ; Cause library initialization
; Dispatcher to be loaded
.PSECT LIB$INITIALIZE, NOPIC, USR, CON, REL, GBL, NOSHR, NOEXE, RD, NOWRT, LONG
.LONG INIT_PROC ; Contribute entry point address of
; initialization routine.
.PSECT ...
The .EXTRN declaration links the initialization routine dispatcher,
LIB$INITIALIZE, into your program’s image. The reference contains a definition
of the special global symbol LIB$INITIALIZE, which is the routine entry point
address of the dispatcher. The linker stores the value of this special global symbol
in the initialization list along with the starting address of the debugger and the
main program. The GBL specification ensures that the PSECT LIB$INITIALIZE
contribution is not affected by any clustering performed by the linker.
Note that moving modules and PSECTS around to affect symbol resolution may
result in unintended memory placement within your image. If, for example, you
add a CLUSTER statement to your linker options file, the initialization code may
not run because the CLUSTER statement in the linker option file may cause the
various LIB$INITIALIZE PSECTS to become separated. To remedy this possible
condition, either add to your options file a CLUSTER or COLLECT statement
like the following:

CLUSTER = <cluster name>,,,<module>, SYS$LIBRARY:STARLET.OLB/include = LIB$INITIALIZE


COLLECT = <cluster name>, LIB$INITIALIZDZ, LIB$INITIALIZD_, LIB$INITIALIZE,LIB$INITIALIZE$

33–6 Image Initialization


Image Initialization
33.4 Dispatching to Initialization Routines

33.4 Dispatching to Initialization Routines


The LIB$INITIALIZE dispatcher calls each initialization routine in the list with
the following argument list:
CALL init-proc (init-coroutine ,cli-coroutine [, image-info])
The init-coroutine argument is the address of a library coroutine to be called to
effect a coroutine linkage with LIB$INITIALIZE.
The cli-coroutine is the address of a CLI coroutine used to obtain command
arguments.
The image-info argument is useful image information, such as the program
name.

33.5 Initialization Routine Options


An initialization routine can be used to do the following:
• Set up an exit handler by calling the Declare Exit Handler ($DCLEXH)
system service, although exit handlers are generally set up by using a
statically allocated first-time flag.
• Initialize statically allocated storage, although this is done preferably at
image activation time using compile-time and link-time data initialization
declarations or by using a first-time call flag in its statically allocated storage.
• Call the initialization dispatcher (instead of returning to it) by calling the
init-coroutine argument. This achieves a coroutine link. Control returns to
the initialization routine when the main program returns control. Then the
initialization routine should also return control to pass back the completion
code returned by the main program (to the debugger or CLI, or both).
• Establish a condition handler in the current frame before performing the
preceding actions. This leaves the initialization routine condition handler on
the image stack for the duration of the image execution. This occurs after the
CLI sets up the catchall stack frame handler and after the debugger sets up
its stack frame handler. Thus, the initialization routine handler can override
either of these handlers, because it will receive signals before they do.

33.6 Initialization Example


The following VAX MACRO code fragment, which works on both VAX and Alpha
systems, shows how an initialization routine does the following:
• Establishes a handler
• Calls the init-coroutine argument routine, so that the coroutine calls the
initialization dispatcher
• Gains control after the main program returns
• Returns to the normal exit processing

.ENTRY INIT_PROC, ^M<> ; No registers used


MOVAL HANDLER, (FP) ; Establish handler
... ; Perform any other initialization

Image Initialization 33–7


Image Initialization
33.6 Initialization Example

CALLG (AP), @INIT_CO_ROUTINE(AP)


; Continue initialization which
10$: ; then calls main program or
; routine.
... ; Return here when main program
; returns with R0 = completion
RET ; Status return to normal exit
; processing with R0 = completion
; status

.ENTRY HANDLER, ^M<...> ; Register mask


... ; handle condition
; could unwind to 10$
MOVL #..., R0 ; Set completion status with a
; condition value
RET ; Resignal or continue depending
; on R0 being SS$_RESIGNAL or
; SS$_CONTINUE.

33–8 Image Initialization


Part III
Appendixes

This part of this second volume describes the generic macros used for calling
system services, OpenVMS data types, and the distributed name services on
OpenVMS VAX systems.
A
Generic Macros for Calling System Services

This appendix describes the use of generic macros to specify argument lists with
appropriate symbols and conventions in the system services interface to MACRO
assemblers.
System service macros generate argument lists and CALL instructions
to call system services. These macros are located in the system library
SYS$LIBRARY:STARLET.MLB. When you assemble a source program, this
library is searched automatically for unresolved references.
Knowledge of VAX MACRO rules for assembly language programming is required
for understanding the material presented in this appendix. The VAX MACRO
and Instruction Set Reference Manual contains the necessary prerequisite
information.
Each system service has four macros associated with it. These macros allow
you to define symbolic names for argument offsets, construct argument lists for
system services, and call system services. Table A–1 lists the generic macros and
the functions they serve.

Table A–1 Generic Argument List Macros of the System Service Interface
Macro Function
$nameDEF Defines symbolic names for the argument list offsets
$name Defines symbolic names for the argument list offsets and constructs
the argument list
$name_S Calls the system service and constructs the argument list
$name_G Calls the system service and uses the argument list constructed by
$name macro

Generic Macros for Calling System Services A–1


Generic Macros for Calling System Services
A.1 Using Macros to Construct Argument Lists

A.1 Using Macros to Construct Argument Lists


You can use two generic macros for constructing argument lists for system
services:
$name
$name_S
The macro you use depends on which macro you are going to use to call the
system service. If you use the $name_G macro to call a system service, you
should use the $name macro to construct the argument list. If you use the
$name_S macro to call a system service, you can also use it to construct the
argument list.

A.1.1 Specifying Arguments with the $name_S Macro and the $name Macro
When you use the $name_S or the $name macro to construct an argument list for
a system service, you can specify arguments in any one of three ways:
• By using keywords to describe the arguments. All keywords must be followed
by an equals sign ( = ) and then by the value of the argument.
• By using positional order, with omitted arguments indicated by commas in the
argument positions. You can omit commas for optional trailing arguments.
• By using both positional order and keyword names (positional arguments
must be listed first).
For example, $MYSERVICE can have the following format:
$MYSERVICE arga ,[argb] ,[argc] ,argd
For purposes of this example, assume that arga and argb require you to specify
numeric values and that argc and argd require you to specify addresses.
Examples A–1 and A–2 show valid ways of writing the $name_S macro to call
$MYSERVICE.

Example A–1 Using Keywords with the $name_S Macro


MYARGD: .LONG 100
.
.
.
$MYSERVICE_S ARGB=#0,ARGC=0,ARGA=#1,ARGD=MYARGD

Example A–2 Specifying Arguments in Positional Order with the $name_S


Macro
MYARGD: .LONG 100
.
.
.
$MYSERVICE_S #1,,,MYARGD

(continued on next page)

A–2 Generic Macros for Calling System Services


Generic Macros for Calling System Services
A.1 Using Macros to Construct Argument Lists

Example A–2 (Cont.) Specifying Arguments in Positional Order with the


$name_S Macro
The argument list is pushed on the stack, as follows:
PUSHAL MYARGD
PUSHL #0
PUSHL #0
PUSHL #1

Note that all arguments, whether specified positionally or with keywords, must
be valid assembler expressions because they are used as source operands in
instructions.
Examples A–3 and A–4 show valid ways of writing a $name macro to construct
an argument list for a later call to $MYSERVICE.

Example A–3 Using Keywords with the $name Macro


LIST: $MYSERVICE -
ARGB=0, -
ARGC=0, -
ARGA=1, -
ARGD=MYARGD

Example A–4 Specifying Arguments in Positional Order with the $name Macro
LIST: $MYSERVICE -
1,,,MYARGD
Both methods generate the following:
LIST: .LONG 4
.LONG 1
.LONG 0
.LONG 0
.ADDRESS -
MYARGD
Note that all arguments, whether specified positionally or by keyword, must be
expressions that the assembler can evaluate to generate .LONG or .ADDRESS
data directives. Contrast this to the arguments for the $name_S macro, which
must be valid assembler expressions because they are used as source operands in
instructions.

Generic Macros for Calling System Services A–3


Generic Macros for Calling System Services
A.1 Using Macros to Construct Argument Lists

A.1.2 Conventions for Specifying Arguments to System Services


You must specify the arguments according to the VAX MACRO assembler rules
for specifying and addressing operands.
The way to specify a particular argument depends on the following factors:
• Whether the system service requires an address or a value as the argument.
In the OpenVMS System Services Reference Manual, the descriptions of the
arguments following a system service macro format always indicate whether
the argument is an address. A Boolean value, number, or mask takes a value
as the argument.
• The system service macro being used. The expansions of the $name and
$name_S macros in the examples in Section A.1.1 show the code generated by
each macro.
If you are unsure whether you specified a value or an address argument correctly,
you can assemble the program with the .LIST MEB directive to check the macro
expansion. See the VAX MACRO and Instruction Set Reference Manual for
details.

A.1.3 Defining Symbolic Names for Argument List Offsets: $name and
$nameDEF
You can refer symbolically to arguments in the argument list. Each argument in
an argument list has an offset from the beginning of the list; a symbolic name is
defined for the numeric offset of each argument. If you use the symbolic names to
refer to the arguments in a list, you do not have to remember the numeric offset
(which is based on the position of the argument shown in the macro format).
There are two additional advantages to referring to arguments by their symbolic
names:
• Your program is easier to read.
• If an argument list for a system service changes with a later release of a
system, the symbols remain the same.
You form the offset names for all system service argument lists by following the
service macro name with $_ and the keyword name of the argument. In the
following example, name is the name for the system service macro and keyword is
the keyword argument:
name$_keyword
Similarly, you can define a symbolic name for the number of arguments a
particular macro requires, as follows:
name$_NARGS
You can define symbolic names for argument list offsets automatically whenever
you use the $name macro for a particular system service. You can also define
symbolic names for system service argument lists using the $nameDEF macro.
This macro does not generate any executable code; it merely defines the symbolic
names so they can be used later in the program. For example:
$QIODEF
This macro defines the symbol QIO$_NARGS and the symbolic names for the
$QIO argument list offsets.

A–4 Generic Macros for Calling System Services


Generic Macros for Calling System Services
A.1 Using Macros to Construct Argument Lists

You may need to use the $nameDEF macro either if you specify an argument list
to a system service without using the $name macro or if a program refers to an
argument list in a separately assembled module.
For example, the $READEF and $READEFDEF macros define the values listed
in the following table.

Symbolic Name Meaning


READEF$_NARGS Number of arguments in the list ( 2 )
READEF$_EFN Offset of EFN argument ( 4 )
READEF$_STATE Offset of STATE argument ( 8 )

Thus, you can specify the $READEF macro to build an argument list for a
$READEF system service call, as follows:
READLST: $READEF EFN=1,STATE=TEST1
Later, the program may want to use a different value for the state argument to
call the service. The following lines show how you can do this with a call to the
$name_G macro.
MOVAL TEST2,READLST+READEF$_STATE
$READEF_G READLST
The MOVAL instruction replaces the address TEST1 in the $READEF argument
list with the address TEST2; the $READEF_G macro calls the system service
with the modified list.

A.2 Using Macros to Call System Services


You can use two generic macros for writing calls to system services:
$name_S
$name_G
Which macro you use depends on how the argument list for the system service is
constructed.
• The $name_S macro requires you to supply the arguments to the system
service in the system service macro. The macro generates code to push the
argument list onto the call stack during program execution. With this macro,
you can use registers to contain or point to arguments so that you can write
reentrant programs.
• The $name_G macro requires you to construct an argument list elsewhere
in the program and specify the address of this list as an argument to the
system service. (A macro is provided to create an argument list for each
system service.) With this macro, you can use the same argument list, with
modifications if necessary, for more than one invocation of the macro.
The $name_S macro generates a CALLS instruction; the $name_G macro
generates a CALLG instruction. The services are called according to the standard
procedure-calling conventions. System services save all registers except R0 and
R1, and restore the saved registers before returning control to the caller.
The following sections describe how to code system service calls using each of
these macros.

Generic Macros for Calling System Services A–5


Generic Macros for Calling System Services
A.2 Using Macros to Call System Services

A.2.1 The $name_S Macro


The $name_S macro call has the following format:
$name_S arg1, ..., argn
The macro generates code to push the arguments on the stack in reverse order.
The actual instructions used to place the arguments on the stack are determined
as follows:
• If the system service requires a value for an argument, either a PUSHL
instruction or a MOVZWL to –(SP) instruction is generated.
• If the system service requires an address for an argument, a PUSHAB,
PUSHAW, PUSHAL, or PUSHAQ instruction is generated, depending on the
context.
The macro then generates a call to the system service in the following format:
CALLS #n,@#SYS$name
In this format, n is the number of arguments on the stack.
A.2.1.1 Example of $name_S Macro Call
Because a $name_S macro constructs the argument list at execution time, you
can supply addresses and values by using register addressing modes. You can use
the following line to execute the $READEF_S macro:
$READEF_S EFN=#1,STATE=(R10)
R10 contains the address of the longword that will receive the status of the flags.
This macro instruction is expanded as follows.
PUSHAL (R10)
PUSHL #1
CALLS #2,@#SYS$READEF

A.2.2 The $name_G Macro


The $name_G macro requires a single operand:
$name_G label
In this format, label is the address of the argument list.

A.2.3 The $name Macro


Macros are provided to create argument lists for the $name_G macro. The
$name_G macro (used with the $name macro) is especially useful for doing the
following:
• Making calls to system services that have long argument lists
• Calling services repeatedly during the execution of a single program with the
same, or essentially the same, argument list
The format of the macros is as follows:
label: $name arg1,...,argn

A–6 Generic Macros for Calling System Services


Generic Macros for Calling System Services
A.2 Using Macros to Call System Services

label
Symbolic address of the generated argument list. This is the label given as an
argument in the $name_G macro.

$name
The service macro name.

arg1,...,argn
Arguments to be placed in successive longwords in the argument list.

A.2.4 Example of $name and $name_G Macro Calls


The example that follows shows how you can write a call to the Read Event Flags
($READEF) system service using an argument list created by $name.
The $READEF system service has the following macro format:
$READEF efn ,state
The efn argument must specify the number of an event flag cluster, and the state
argument must supply the address of a longword that will receive the contents of
the cluster.
You can specify these arguments using the $name macro, as follows:
READLST:
$READEF EFN=1, - ; Argument list for $READEF
STATE=TESTFLAG
This $READEF macro generates the following code:
READLST:
.LONG 2 ; Argument list for $READEF
.ADDRESS 1
.ADDRESS -
TESTFLAG
Executing the $READEF macro requires only the following line:
$READEF_G READLST
The macro generates the following code to call the Read Event Flags system
service:
CALLG READLST,@#SYS$READEF
SYS$READEF is the name of a vector to the entry point of the Read Event Flags
system service. The linker automatically resolves the entry point addresses for
all system services.

Generic Macros for Calling System Services A–7


B
OpenVMS Data Types

As part of the OpenVMS common language environment, the OpenVMS system


routine data types provide compatibility between procedure calls that support
many different high-level languages. Specifically, the OpenVMS data types
apply to both Alpha and VAX architectures as the mechanism for passing
argument data between procedures. This appendix describes the context and
structure of the OpenVMS system routine data types and identifies the associated
declarations to each of the specific high-level language implementations.

B.1 OpenVMS Data Types


The OpenVMS usage entry in the documentation format for system routines
indicates the OpenVMS data type of the argument. Most data types can be
considered conceptual types; that is, their meaning is unique in the context of
the OpenVMS operating system. The OpenVMS data type access_mode is one
example. The storage representation of this OpenVMS type is an unsigned byte,
and the conceptual content of this unsigned byte is the fact that it designates
a hardware access mode and therefore has only four valid values: 0, kernel
mode; 1, executive mode; 2, supervisor mode; and 3, user mode. However, some
OpenVMS data types are not conceptual types; that is, they specify a storage
representation but carry no other semantic content in the OpenVMS context. For
example, the data type byte_signed is not a conceptual type.

Note
The OpenVMS usage entry is not a traditional data type such as the
OpenVMS standard data types—byte, word, longword, and so on. It
is significant only within the OpenVMS operating system environment
and is intended solely to expedite data declarations within application
programs.

To use the OpenVMS usage entry, perform the following steps:


1. Find the data type in Table B–1 and read its definition.
2. Find the same OpenVMS data type in the appropriate high-level language
implementation table (Tables B–2 through B–13) and its corresponding
source-language type declaration.
3. Use this code as your type declaration in your application program. Note
that, in some instances, you might have to modify the declaration.
For both Alpha and VAX architectures, Table B–1 lists and describes the standard
OpenVMS data type declarations for the OpenVMS usage entry of any system
routine call.

OpenVMS Data Types B–1


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 OpenVMS Usage Data Type Entries


Data Type Definition
access_bit_names Homogeneous array of 32 quadword descriptors; each descriptor defines the name
of one of the 32 bits in an access mask. The first descriptor names bit <0>, the
second descriptor names bit <1>, and so on.
access_mode Unsigned byte denoting a hardware access mode. This unsigned byte can contain
one of four values: 0, kernel mode; 1, executive mode; 2, supervisor mode; and 3,
user mode.
address Unsigned longword denoting a position in virtual memory. On Alpha systems,
the address can be represented by a 64-bit value, in which case the high-order 33
bits of that value must be the same (for example, the 64-bit value must equal the
sign-extended 32-bit value).
address_range Unsigned quadword denoting a range of virtual addresses that identifies an area
of memory. The first longword specifies the beginning address in the range; the
second longword specifies the ending address in the range.
arg_list Procedure call argument list containing a sequence of entries together with a count
of the number of argument entries.
On Alpha systems2 , an argument list is represented as quadword entities in
hardware registers (R16–21 or F16–21). The AI register (R25) contains the
argument count. When there are more than six arguments, the argument list
overflows onto the stack. See Figure 18–5 for more information.
On VAX systems1 , an argument list (shown in the following figure) is represented
as a vector of longwords, where the first longword contains the count and each
remaining longword contains one argument.

VAX Specific
31 0
Must be 0 Argument :arglst
count (n)
arg1

arg2

argn

ZK−4721A−GE

ast_procedure The procedure value of a procedure to be called at asynchronous system trap (AST)
level. (Procedures that are not to be called at AST level are of type procedure.)
boolean Unsigned longword denoting a Boolean truth value flag. This longword can have
one of two values: 1 (true) or 0 (false).
buffer Generic term for temporary memory.
buffer_length Generic term for temporary memory that indicates the size of a buffer.
byte_signed Same as the data type byte integer (signed) in Table 17–3.
byte_unsigned Same as the data type byte (unsigned) in Table 17–3.

1 VAX specific.
2 Alpha specific.

(continued on next page)

B–2 OpenVMS Data Types


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
channel Unsigned word integer that is an index to an I/O channel.
char_string String of from 0 to 65535 eight-bit characters. This OpenVMS data type is the
same as the data type character string in Table 17–3. The following diagram
shows the character string XYZ:

7 0
:A
"X"

:A+1
"Y"

:A+2
"Z"

ZK−4202−GE

complex_number One of the OpenVMS standard complex floating-point data types. The six complex
floating point numbers are F_floating complex, D_floating complex, G_floating
complex, S_floating, T_floating, and X_floating.
As shown in the following figure, an F_floating point complex number
( real, imaginary ) is composed of two F_floating point numbers: the first is the
real part of the complex number; the second is the imaginary part. For more
structure detail, see floating_point described later in this table.

31 0
F_floating number (real) :A

F_floating number (imaginary) :A+4

63 32
ZK−4720A−GE

As shown in the following figure, a D_floating point complex number


( real, imaginary ) is composed of two D_floating point numbers: the first is the
real part of the complex number; the second is the imaginary part.
For more structure detail, see floating_point described later in this table.

31 0
D_floating number (real) :A

D_floating number (imaginary) :A+8

ZK−4719A−GE

(continued on next page)

OpenVMS Data Types B–3


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
As shown in the following figure, a G_floating point complex number
( real, imaginary ) is composed of two G_floating point numbers: the first is the
real part of the complex number; the second is the imaginary part.
For more structure detail, see floating_point described later in this table.

31 0
G_floating number (real) :A

G_floating number (imaginary) :A+8

ZK−4728A−GE

On VAX systems1 , as shown in the following figure, an H_floating complex number


( real, imaginary ) is composed of two H_floating point numbers: the first is the real
part of the complex number; the second is the imaginary part. Note that H_float
numbers apply to VAX environments only.
For more structure detail, see floating_point described later in this table.

VAX Specific
31 0
H_floating number (real) :A

H_floating number (imaginary) :A+16

ZK−4729A−GE

1 VAX specific.

(continued on next page)

B–4 OpenVMS Data Types


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
On Alpha systems2 , as shown in the following figure, an S_floating point complex
number ( real, imaginary ) is composed of two S_floating point numbers: the first is
the real part of the complex number; the second is the imaginary part.
For more structure detail, see floating_point described later in this table.

Alpha Specific
31 0
:A
S_floating number (real)
:A+4
S_floating number (imaginary)

63 32

ZK−5189A−GE

On Alpha systems2 , as shown in the following figure, a T_floating complex number


( real, imaginary ) is composed of two T_floating point numbers: the first is the real
part of the complex number; the second is the imaginary part.
For more structure detail, see floating_point described later in this table.

Alpha Specific

31 0
:A
T_floating number (real)

:A+8
T_floating number (imaginary)

ZK−5190A−GE

2 Alpha specific.

(continued on next page)

OpenVMS Data Types B–5


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
On Alpha systems2 , as shown in the following figure, an X_floating complex number
( real, imaginary ) is composed of two X_floating point numbers: the first is the real
part of the complex number; the second is the imaginary part.
For more structure detail, see floating_point described later in this table.

Alpha Specific
31 0
:A

X_floating number (real)

:A+16

X_floating number (imaginary)

ZK−6512A−GE

cond_value Longword integer for VAX or quadword sign-extended integer for Alpha denoting a
condition value (a return status or system condition code) that is typically returned
by a procedure in R0. Each numeric condition value has a unique symbolic name
in the following format, where the severity condition code is a mnemonic describing
the return condition:

31 28 27 3 2 0

Control Condition identification Severity

2 1 0

*S

27 16 15 3

Facility number Message number

*S = Success
ZK−1795−GE

2 Alpha specific.

(continued on next page)

B–6 OpenVMS Data Types


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
Depending on your specific needs, you can test just the low-order bit, the low-order
three bits, or the entire value.
• The low-order bit indicates successful (1) or unsuccessful (0) completion of the
service.
• The low-order 3 bits taken together represent the severity of the error.
• The remaining bits <31:3> classify the particular return condition and the
operating system component that issued the condition value.

context Unsigned longword used by a called procedure to maintain position over an


iterative sequence of calls. The data type is usually initialized by the caller but
thereafter is manipulated by the called procedure.
date_time Unsigned 64-bit binary integer denoting a date and time as the number of elapsed
100-nanosecond units since 00:00 o’clock, November 17, 1858. This OpenVMS data
type is the same as the data type absolute date and time in Table 17–3.
device_name Character string denoting the 1- to 15-character name of a device. This string can
be a logical name, but if it is, it must translate to a valid device name. If the device
name contains a colon ( : ), the colon and the characters following it are ignored.
An underscore ( _ ) preceding the device name string indicates that the string is a
physical device name.
ef_cluster_name Character string denoting the 1- to 15-character name of an event flag cluster. This
string can be a logical name, but if it is, it must translate to a valid event-flag
cluster name.
ef_number Unsigned longword integer denoting the number of an event flag. Local event flags
numbered 32 to 63 are available to your programs.
exit_handler_block Variable-length structure denoting an exit-handler control block. This control block,
which describes the exit handler, is depicted in the following diagram:

31 0
Forward link (used by OpenVMS only)

Exit handler address

Must be 0 Argument count

Address condition value (written by OpenVMS)

Additional argument for the


exit handler; optional; one
argument per longword

ZK−1714−GE

fab Structure denoting an RMS file access block.

(continued on next page)

OpenVMS Data Types B–7


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
file_protection Unsigned word that is a 16-bit mask that specifies file protection. The mask
contains four 4-bit fields, each of which specifies the protection (access protected
when a bit is 1) to be applied to file access attempts by one of the four categories
of users, from rightmost field to leftmost field: (1) system users, (2) file owner, (3)
users in the same UIC group as the owner, and (4) all other users (the world). Each
field specifies, from rightmost bit to leftmost bit: (1) read access, (2) write access,
(3) execute access, (4) delete access. Set bits indicate that access is denied.
The following diagram depicts the 16-bit file-protection mask:

World Group Owner System


D E W R D E W R D E W R D E W R
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
ZK−1706−GE

floating_point One of the Alpha or VAX standard floating-point data types. VAX systems
support F_floating, D_floating, G_floating, or H_floating data types. In addition,
Alpha systems support S_floating, T_floating, or X_floating types. The following
paragraphs briefly describe these data types:
The structure of an F_floating datum follows. It contains two fraction fields.
Note that the field 2 extension holds the least significant portion of the fractional
number.

15 14 7 6 0
S Exponent Fraction field 1 :A

Fraction field 2 :A+2

31 16
ZK−4722A−GE

(continued on next page)

B–8 OpenVMS Data Types


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
The structure of a D_floating datum follows. It contains four fraction fields. Note
that the field 4 extension holds the least significant portion of the fractional
number.
While OpenVMS Alpha 2 supports the manipulation of D_floating and D_floating
complex data, compiled-code support invokes conversion from D_floating to G_
floating for Alpha arithmetic operations. Also, the conversion of G_floating
intermediate results are converted back to D_floating when needed either for
stores to memory or for passing parameters. However, use of D_floating data in
arithmetic operations on Alpha processors produces results that are limited to
G_float precision.

15 14 7 6 0
S Exponent Fraction field 1 :A

Fraction field 2 :A+2

Fraction field 3 :A+4

Fraction field 4 :A+6

63 48
ZK−4723A−GE

The structure of a G_floating datum follows. It contains four fraction fields. Note
that the field 4 extension holds the least significant portion of the fractional
number.

15 14 4 3 0
S Exponent Field 1 :A

Fraction field 2 :A+2

Fraction field 3 :A+4

Fraction field 4 :A+6

63 48
ZK−4724A−GE

2 Alpha specific.

(continued on next page)

OpenVMS Data Types B–9


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
The structure of an H_floating datum follows (VAX 1 systems only). It contains
seven fraction fields. Note that the field 7 extension holds the least significant
portion of the fractional number.

VAX Specific
15 14 0
:A
S Exponent
:A+2
Fraction field 1
:A+4
Fraction field 2
:A+6
Fraction field 3
:A+8
Fraction field 4
:A+10
Fraction field 5
:A+12
Fraction field 6
:A+14
Fraction field 7

ZK−4725A−GE

The structure of an S_floating datum follows (Alpha 2 systems only). It contains


two fraction fields. Note that the field 2 extension holds the least significant portion
of the fractional number.

Alpha Specific
15 0
:A
Fraction field 2
:A+2
S Fraction field 1 Exponent

31 30 23 22 16

ZK−4726A−GE

1 VAX specific.
2 Alpha specific.

(continued on next page)

B–10 OpenVMS Data Types


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
The structure of a T_floating datum follows (Alpha 2 systems only). It contains four
fraction fields. Note that fraction field 1 holds the most significant bits, and the
field 4 extension holds the least significant portion of the fractional number.

Alpha Specific
15 0
:A
Fraction field 4
:A+2
Fraction field 3
:A+4
Fraction field 2
:A+6
S Exponent Field 1

63 62 52 51 48

ZK−4727A−GE

The structure of an X_floating datum follows (Alpha2 systems only). An X_floating


datum occupies 16 contiguous bytes in memory or two consecutive floating-point
registers. It contains seven fraction fields (0–6). Note that fraction field 6 holds the
most significant bits and the field 0 extension holds the least significant portion of
the fractional number.

Alpha Specific
15 0
:A
Fraction field 0
:A+2
Fraction field 1
:A+4
Fraction field 2
:A+6
Fraction field 3
:A+8
Fraction field 4
:A+10
Fraction field 5
:A+12
Fraction field 6
:A+14
S Exponent

127 112

ZK−6511A−GE

function_code Unsigned longword specifying the exact operations a procedure is to perform. This
longword has two word-length fields: the first field is a number specifying the major
operation; the second field is a mask or bit vector specifying various suboperations
within the major operation.
identifier Unsigned longword that identifies an object returned by the system.

2 Alpha specific.

(continued on next page)

OpenVMS Data Types B–11


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
2
invo_context_blk Structure that contains the context information of a specific procedure invocation
in a call chain. For information describing the invocation context block, see the
OpenVMS Calling Standard.
invo_handle2 Unsigned longword that refers to a specific procedure invocation at run time. The
invo_handle longword defines the invocation handle of a procedure in a call chain.
io_status_block Quadword structure containing information returned by a procedure that completes
asynchronously. The information returned varies depending on the procedure.
The following figure illustrates the format of the information written in the IOSB
for SYS$QIO:

31 16 15 0
Count Condition value

Device−dependent information

ZK−0856−GE

The first word contains a condition value indicating the success or failure of the
operation. The condition values used are the same as for all returns from system
services; for example, SS$_NORMAL indicates successful completion.
The second word contains the number of bytes actually transferred in the I/O
operation. Note that for some devices this word contains only the low-order word of
the count.
The second longword contains device-dependent return information.
To ensure successful I/O completion and the integrity of data transfers, you should
check the IOSB following I/O requests, particularly for device-dependent I/O
functions.
item_list_2 Structure that consists of one or more item descriptors and is terminated by
a longword containing 0. Each item descriptor is a 2-longword structure that
contains three fields.
The following diagram depicts a single-item descriptor:

31 15 0
Item code Component length

Component address

ZK−1709−GE

The first field is a word in which the service writes the length (in characters) of the
requested component. If the service does not locate the component, it returns the
value 0 in this field and in the component address field.
The second field contains a user-supplied, word-length symbolic code that specifies
the component desired. The item codes are defined by the macros specific to the
service.
The third field is a longword in which the service writes the starting address of the
component. This address is within the input string itself.

2 Alpha specific.

(continued on next page)

B–12 OpenVMS Data Types


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
item_list_3 Structure that consists of one or more item descriptors and is terminated by
a longword containing 0. Each item descriptor is a 3-longword structure that
contains four fields.
The following diagram depicts the format of a single-item descriptor:

31 15 0

Item code Buffer length

Buffer address

Return length address

ZK−1705−GE

The first field is a word containing a user-supplied integer specifying the length (in
bytes) of the buffer in which the service writes the information. The length of the
buffer needed depends on the item code specified in the item code field of the item
descriptor. If the value of buffer length is too small, the service truncates the data.
The second field is a word containing a user-supplied symbolic code specifying the
item of information that the service is to return. These codes are defined by macros
specific to the service.
The third field is a longword containing the user-supplied address of the buffer in
which the service writes the information.
The fourth field is a longword containing the user-supplied address of a word in
which the service writes the length in bytes of the information it actually returned.
item_list_pair Structure that consists of one or more longword pairs, or doublets, and is
terminated by a longword containing 0. Typically, the first longword contains
an integer value such as a code. The second longword can contain a real or integer
value.
item_quota_list Structure that consists of one or more quota descriptors and is terminated by
a byte containing a value defined by the symbolic name PQL$_LISTEND. Each
quota descriptor consists of a 1-byte quota name followed by an unsigned longword
containing the value for that quota.
lock_id Unsigned longword integer denoting a lock identifier. This lock identifier is
assigned to a lock by the lock manager when the lock is granted.
lock_status_block Structure into which the lock manager writes status information about a lock. A
lock status block always contains at least two longwords: the first word of the
first longword contains a condition value; the second word of the first longword is
reserved by Compaq. The second longword contains the lock identifier.
The lock status block receives the final condition value plus the lock identification,
and optionally contains a lock value block. When a request is queued, the lock
identification is stored in the lock status block even if the lock has not been granted.
This allows a procedure to dequeue locks that have not been granted.
The condition value is placed in the lock status block only when the lock is granted
(or when errors occur in granting the lock).

(continued on next page)

OpenVMS Data Types B–13


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
The following diagram depicts a lock status block that includes the optional 16-byte
lock value block:

31 15 0
Reserved Condition value

Lock identification

16−byte lock value block


(Used only when the LCK$M_VALBLK flag is set)

ZK−1708−GE

lock_value_block A 16-byte block that the lock manager includes in a lock status block if the user
requests it. The contents of the lock value block are user-defined and are not
interpreted by the lock manager.
logical_name Character string of from 1 to 255 characters that identifies a logical name or
equivalence name to be manipulated by OpenVMS logical name system services.
Logical names that denote specific OpenVMS objects have their own OpenVMS
types; for example, a logical name identifying a device has the OpenVMS type
device_name.
longword_signed Same as the data type longword integer (signed) in Table 17–3.
longword_unsigned Same as the data type longword (unsigned) in Table 17–3.
mask_byte Unsigned byte in which each bit is interpreted by the called procedure. A mask is
also referred to as a set of flags or as a bit mask.
mask_longword Unsigned longword in which each bit is interpreted by the called procedure. A
mask is also referred to as a set of flags or as a bit mask.
mask_quadword Unsigned quadword in which each bit is interpreted by the called procedure. A
mask is also referred to as a set of flags or as a bit mask.
mask_word Unsigned word in which each bit is interpreted by the called procedure. A mask is
also referred to as a set of flags or as a bit mask.
mechanism_args Structure (array) of mechanism argument vectors that contain information about
the machine state when an exception occurs or when a condition is signaled. For
more information concerning mechanism argument vectors, see the OpenVMS
Calling Standard.
null_arg Unsigned longword denoting a null argument. (A null argument is one whose only
purpose is to hold a place in the argument list.)
octaword_signed Same as the data type octaword integer (signed) in Table 17–3.
octaword_unsigned Same as the data type octaword (unsigned) in Table 17–3.

(continued on next page)

B–14 OpenVMS Data Types


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
page_protection Unsigned longword specifying page protection to be applied by the Alpha or VAX
hardware. Protection values are specified using bits <3:0>; bits <31:4> are ignored.
If you specify the protection as 0, the protection defaults to kernel read only.
The $PRTDEF macro defines the following symbolic names for the protection codes:

Symbol Description
PRT$C_NA No access
PRT$C_KR Kernel read only
PRT$C_KW Kernel write
PRT$C_ER Executive read only
PRT$C_EW Executive write
PRT$C_SR Supervisor read only
PRT$C_SW Supervisor write
PRT$C_UR User read only
PRT$C_UW User write
PRT$C_ERKW Executive read; kernel write
PRT$C_SRKW Supervisor read; kernel write
PRT$C_SREW Supervisor read; executive write
PRT$C_URKW User read; kernel write
PRT$C_UREW User read; executive write
PRT$C_URSW User read; supervisor write

procedure Procedure value of a procedure that is not to be called at AST level. (Arguments
specifying procedures to be called at AST level have the OpenVMS type ast_
procedure.)
A procedure value is an address that represents a procedure. On VAX systems, a
procedure value is the address of the procedure entry mask. On Alpha systems, a
procedure value is the address of the procedure descriptor for the procedure. For
more information, see the OpenVMS Calling Standard.
process_id Unsigned longword integer denoting a process identification (PID). This process
identification is assigned to a process by the operating system when the process is
created.
process_name Character string containing 1 to 15 characters that specifies the name of a process.
quadword_signed Same as the data type quadword integer (signed) in Table 17–3.
quadword_unsigned Same as the data type quadword (unsigned) in Table 17–3.

(continued on next page)

OpenVMS Data Types B–15


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
rights_holder Unsigned quadword specifying a user’s access rights to a system object. This
quadword consists of two fields: the first is an unsigned longword identifier
(OpenVMS type rights_id), and the second is a longword bit mask in which each
bit specifies an access right. The following diagram depicts the format of a rights
holder:

31 0
UIC identifier of holder

ZK−1903−GE

rights_id Unsigned longword denoting a rights identifier, which identifies an interest group
in the context of the OpenVMS security environment. This rights environment
might consist of all or part of a user’s user identification code (UIC).
Identifiers have two formats in the rights database: UIC format (OpenVMS type
uic) and ID format. The high-order bits of the identifier value specify the format of
the identifier. Two high-order zero bits identify a UIC format identifier; bit <31>,
set to 1, identifies an ID format identifier. Bits <30:28> are reserved by Compaq.
The remaining bits specify the identifier value. The following diagram depicts the
ID format of a rights identifier:

31 27 0
1000 Identifier

ZK−1906−GE

To the system, an identifier is a binary value; however, to make identifiers easy to


use, the system translates the binary identifier value into an identifier name. The
binary value and the identifier name are associated in the rights database.
An identifier name consists of 1 to 31 alphanumeric characters and contains at
least one nonnumeric character. An identifier name cannot consist entirely of
numeric characters. It can include the characters A through Z, dollar signs ( $ ),
and underscores ( _ ), as well as the numbers 0 through 9. Any lowercase characters
are automatically converted to uppercase.
rab Structure denoting an RMS record access block.
section_id Unsigned quadword denoting a global section identifier. This identifier specifies
the version of a global section and the criteria to be used in matching that global
section.
section_name Character string denoting a 1- to 43-character global-section name. This character
string can be a logical name, but it must translate to a valid global section name.
system_access_id Unsigned quadword that denotes a system identification value to be associated with
a rights database.
time_name Character string specifying a time value in an OpenVMS format.
transaction_id Unsigned octaword that denotes a unique transaction identifier.

(continued on next page)

B–16 OpenVMS Data Types


OpenVMS Data Types
B.1 OpenVMS Data Types

Table B–1 (Cont.) OpenVMS Usage Data Type Entries


Data Type Definition
uic Unsigned longword denoting a user identification code (UIC). Each UIC is unique
and represents a system user. The UIC identifier contains two high-order bits that
designate format, a member field, and a group field. Member numbers range from
0 to 65534; group numbers range from 1 to 16382. The following diagram depicts
the UIC format:

31 0
00 Group Member

ZK−1905−GE

user_arg On VAX systems, an unsigned longword, and on Alpha systems, an unsigned


quadword denoting a user-defined argument. The longword (VAX) or quadword
(Alpha) is passed to a procedure as an argument, but the contents of the longword
or quadword are defined and interpreted by the user.
varying_arg On VAX systems, an unsigned longword, and on Alpha systems, an unsigned
quadword denoting a varying argument. A variable argument can have variable
types, depending on specifications made for other arguments in the call.
vector_byte_signed Homogeneous array whose elements are all signed bytes.
vector_byte_unsigned Homogeneous array whose elements are all unsigned bytes.
vector_longword_ Homogeneous array whose elements are all signed longwords.
signed
vector_longword_ Homogeneous array whose elements are all unsigned longwords.
unsigned
vector_quadword_ Homogeneous array whose elements are all signed quadwords.
signed
vector_quadword_ Homogeneous array whose elements are all unsigned quadwords.
unsigned
vector_word_signed Homogeneous array whose elements are all signed words.
vector_word_ Homogeneous array whose elements are all unsigned words.
unsigned
word_signed Same as the data type word integer (signed) in Table 17–3.
word_unsigned Same as the data type word (unsigned) in Table 17–3.

B.2 Ada Implementations


Table B–2 lists the OpenVMS data types and their corresponding Ada data type
declarations.

Table B–2 Ada Implementations


OpenVMS Data Types Ada Declarations
access_bit_names STARLET.ACCESS_BIT_NAMES_TYPE
access_mode STARLET.ACCESS_MODE_TYPE
address SYSTEM.ADDRESS
(continued on next page)

OpenVMS Data Types B–17


OpenVMS Data Types
B.2 Ada Implementations

Table B–2 (Cont.) Ada Implementations


OpenVMS Data Types Ada Declarations

address_range STARLET.ADDRESS_RANGE_TYPE
arg_list STARLET.ARG_LIST_TYPE
ast_procedure SYSTEM.AST_HANDLER
boolean STANDARD.BOOLEAN
byte_signed STANDARD.SHORT_SHORT_INTEGER
byte_unsigned SYSTEM.UNSIGNED_BYTE
channel STARLET.CHANNEL_TYPE
char_string STANDARD.STRING
complex_number User-defined record
cond_value CONDITION_HANDLING.COND_VALUE_TYPE
context STARLET.CONTEXT_TYPE
date_time STARLET.DATE_TIME_TYPE
device_name STARLET.DEVICE_NAME_TYPE
ef_cluster_name STARLET.EF_CLUSTER_NAME_TYPE
ef_number STARLET.EF_NUMBER_TYPE
exit_handler_block STARLET.EXIT_HANDLER_BLOCK_TYPE
fab STARLET.FAB_TYPE
file_protection STARLET.FILE_PROTECTION_TYPE
floating_point STANDARD.FLOAT
STANDARD.LONG_FLOAT
STANDARD.LONG_LONG_FLOAT
SYSTEM.F_FLOAT
SYSTEM.D_FLOAT
SYSTEM.G_FLOAT
SYSTEM.H_FLOAT
SYSTEM.IEEE_SINGLE_FLOAT1
SYSTEM.IEEE_DOUBLE_FLOAT1
function_code STARLET.FUNCTION_CODE_TYPE
identifier SYSTEM.UNSIGNED_LONGWORD
1
invo_context_blk User-defined record
1
invo_handle SYSTEM.UNSIGNED_LONGWORD
io_status_block STARLET.IOSB_TYPE
item_list_pair SYSTEM.UNSIGNED_LONGWORD
item_list_2 STARLET.ITEM_LIST_2_TYPE
item_list_3 STARLET.ITEM_LIST_3_TYPE
item_quota_list User-defined record
lock_id STARLET.LOCK_ID_TYPE
lock_status_block STARLET.LOCK_STATUS_BLOCK_TYPE
lock_value_block STARLET.LOCK_VALUE_BLOCK_TYPE
logical_name STARLET.LOGICAL_NAME_TYPE

1 Alpha specific.

(continued on next page)

B–18 OpenVMS Data Types


OpenVMS Data Types
B.2 Ada Implementations

Table B–2 (Cont.) Ada Implementations


OpenVMS Data Types Ada Declarations
longword_signed STANDARD.INTEGER
longword_unsigned SYSTEM.UNSIGNED_LONGWORD
mask_byte SYSTEM.UNSIGNED_BYTE
mask_longword SYSTEM.UNSIGNED_LONGWORD
mask_quadword SYSTEM.UNSIGNED_QUADWORD
mask_word SYSTEM.UNSIGNED_WORD
mechanism_args STARLET.CHFDEF2_TYPE
null_arg SYSTEM.UNSIGNED_LONGWORD
octaword_signed array(1..4) of SYSTEM.UNSIGNED_LONGWORD
octaword_unsigned array(1..4) of SYSTEM.UNSIGNED_LONGWORD
page_protection STARLET.PAGE_PROTECTION_TYPE
procedure SYSTEM.ADDRESS
process_id STARLET.PROCESS_ID_TYPE
process_name STARLET.PROCESS_NAME_TYPE
quadword_signed SYSTEM.UNSIGNED_QUADWORD
quadword_unsigned SYSTEM.UNSIGNED_QUADWORD
rights_holder STARLET.RIGHTS_HOLDER_TYPE
rights_id STARLET.RIGHTS_ID_TYPE
rab STARLET.RAB_TYPE
section_id STARLET.SECTION_ID_TYPE
section_name STARLET.SECTION_NAME_TYPE
system_access_id STARLET.SYSTEM_ACCESS_ID_TYPE
time_name STARLET.TIME_NAME_TYPE
transaction_id array(1..4) of SYSTEM.UNSIGNED_LONGWORD
uic STARLET.UIC_TYPE
user_arg STARLET.USER_ARG_TYPE
varying_arg SYSTEM.UNSIGNED_LONGWORD
vector_byte_signed array(1..n) of STANDARD.SHORT_SHORT_
INTEGER
vector_byte_unsigned array(1..n) of SYSTEM.UNSIGNED_BYTE
vector_longword_signed array(1..n) of STANDARD.INTEGER
vector_longword_unsigned array(1..n) of SYSTEM.UNSIGNED_LONGWORD
vector_quadword_signed array(1..n) of SYSTEM.UNSIGNED_QUADWORD
vector_quadword_unsigned array(1..n) of SYSTEM.UNSIGNED_QUADWORD
vector_word_signed array(1..n) of STANDARD.SHORT_INTEGER
vector_word_unsigned array(1..n) of SYSTEM.UNSIGNED_WORD
word_signed STANDARD.SHORT_INTEGER
word_unsigned SYSTEM.UNSIGNED_WORD

OpenVMS Data Types B–19


OpenVMS Data Types
B.3 Application Programming Language (APL) Implementations

B.3 Application Programming Language (APL) Implementations


Table B–3 lists the OpenVMS data types and their corresponding APL data type
declarations.

Table B–3 APL Implementations


OpenVMS Data Types APL Declarations
access_bit_names na
access_mode /TYPE=BU
address na
address_range na
arg_list na
ast_procedure na
boolean /TYPE=V
byte_signed /TYPE=B
byte_unsigned /TYPE=BU
channel /TYPE=WU
char_string /TYPE=T
complex_number /TYPE=FC
/TYPE=DC
/TYPE=GC
/TYPE=HC
cond_value /TYPE=LU
context na
date_time na
device_name /TYPE=T
ef_cluster_name /TYPE=T
ef_number /TYPE=LU
exit_handler_block na
fab na
file_protection /TYPE=WU
floating_point /TYPE=F
/TYPE=D
/TYPE=G
/TYPE=H
function_code na
identifier na
io_status_block na
item_list_2 na
item_list_3 na
item_list_pair na
item_quota_list na
lock_id /TYPE=LU
(continued on next page)

B–20 OpenVMS Data Types


OpenVMS Data Types
B.3 Application Programming Language (APL) Implementations

Table B–3 (Cont.) APL Implementations


OpenVMS Data Types APL Declarations

lock_status_block na
lock_value_block na
logical_name /TYPE=T
longword_signed /TYPE=L
longword_unsigned /TYPE=LU
mask_byte /TYPE=BU
mask_longword /TYPE=LU
mask_quadword na
mask_word /TYPE=WU
null_arg /TYPE=LU
octaword_signed na
octaword_unsigned na
page_protection /TYPE=LU
procedure na
process_id /TYPE=LU
process_name /TYPE=T
quadword_signed na
quadword_unsigned na
rights_holder na
rights_id /TYPE=LU
rab na
section_id na
section_name /TYPE=T
system_access_id na
time_name /TYPE=T
transaction_id na
uic /TYPE=LU
user_arg /TYPE=LU
varying_arg na
vector_byte_signed /TYPE=B
vector_byte_unsigned /TYPE=BU
vector_longword_signed /TYPE=L
vector_longword_unsigned /TYPE=LU
vector_quadword_signed na
vector_quadword_unsigned na
vector_word_signed /TYPE=W
(continued on next page)

OpenVMS Data Types B–21


OpenVMS Data Types
B.3 Application Programming Language (APL) Implementations

Table B–3 (Cont.) APL Implementations


OpenVMS Data Types APL Declarations

vector_word_unsigned /TYPE=WU
word_signed /TYPE=W
word_unsigned /TYPE=WU

B.4 BASIC Implementations


Table B–4 lists the OpenVMS data types and their corresponding BASIC data
type declarations.

Table B–4 BASIC Implementations


OpenVMS Data Type BASIC Declarations
access_bit_names na
access_mode BYTE (signed)
address LONG
address_range LONG address_range (1)
or
RECORD address_range
LONG beginning_address
LONG ending_address
END RECORD
arg_list na
ast_procedure EXTERNAL LONG ast_proc
boolean LONG
byte_signed BYTE
byte_unsigned BYTE1
channel WORD
char_string STRING
complex_number RECORD complex
REAL real_part
REAL imaginary_part
END RECORD
cond_value LONG
context LONG
date_time RECORD date_time
LONG FILL (2)
END RECORD
device_name STRING
ef_cluster_name STRING
ef_number LONG

1 Although unsigned data types are not directly supported in BASIC, you may substitute the signed
equivalent provided you do not exceed the range of the signed data type.

(continued on next page)

B–22 OpenVMS Data Types


OpenVMS Data Types
B.4 BASIC Implementations

Table B–4 (Cont.) BASIC Implementations


OpenVMS Data Type BASIC Declarations
exit_handler_block RECORD EHCB
LONG flink
LONG handler_addr
BYTE arg_count
BYTE FILL (3)
LONG status_value_addr
END RECORD
fab na
file_protection LONG
floating_point SINGLE
DOUBLE
GFLOAT
HFLOAT
function_code RECORD function-code
WORD major-function
WORD subfunction
END RECORD
identifier LONG
io_status_block RECORD iosb
WORD iosb-field (3)
END RECORD
item_list_2 RECORD item_list_two
GROUP item(15)
VARIANT
CASE
WORD comp_length
WORD code
LONG comp_address
CASE
LONG terminator
END VARIANT
END GROUP
END RECORD
item_list_3 RECORD item_list_3
GROUP item (15)
VARIANT
CASE
WORD buf_len
WORD code
LONG buffer_address
LONG length_address
CASE
LONG terminator
END VARIANT
END GROUP
END RECORD

(continued on next page)

OpenVMS Data Types B–23


OpenVMS Data Types
B.4 BASIC Implementations

Table B–4 (Cont.) BASIC Implementations


OpenVMS Data Type BASIC Declarations
item_list_pair RECORD item_list_pair
GROUP item (15)
VARIANT
CASE
LONG code
LONG value
CASE
LONG terminator
END VARIANT
END GROUP
END RECORD item_list_pair
item_quota_list RECORD item_quota_list
GROUP quota (n)
VARIANT
CASE
BYTE quota_name
LONG value
CASE
BYTE list_end
END VARIANT
END GROUP
END RECORD
lock_id LONG
lock_status_block na
lock_value_block na
logical_name STRING
longword_signed LONG
longword_unsigned LONG1
mask_byte BYTE
mask_longword LONG
mask_quadword RECORD quadword
LONG FILL (2)
END RECORD1
mask_word WORD
null_arg A null argument is indicated by a comma used as a
placeholder in the argument list.
octaword_signed na
octaword_unsigned na
page_protection LONG
procedure EXTERNAL LONG proc
process_id LONG
process_name STRING
quadword_signed RECORD quadword
LONG FILL (2)
END RECORD

1 Although unsigned data types are not directly supported in BASIC, you may substitute the signed
equivalent provided you do not exceed the range of the signed data type.

(continued on next page)

B–24 OpenVMS Data Types


OpenVMS Data Types
B.4 BASIC Implementations

Table B–4 (Cont.) BASIC Implementations


OpenVMS Data Type BASIC Declarations
quadword_unsigned RECORD quadword
LONG FILL (2)
END RECORD1
rights_holder RECORD quadword
LONG FILL (2)
END RECORD1
rights_id LONG
rab na
section_id RECORD quadword
LONG FILL (2)
END RECORD1
section_name STRING
system_access_id RECORD quadword
LONG FILL (2)
END RECORD1
time_name STRING
transaction_id na
uic LONG
user_arg LONG
varying_arg Depends on the application.
vector_byte_signed BYTE array n
vector_byte_unsigned BYTE array n1
vector_longword_signed LONG array n
vector_longword_unsigned LONG array n1
vector_quadword_signed na
vector_quadword_unsigned na
vector_word_signed WORD array n
vector_word_unsigned WORD array n1
word_signed WORD
word_unsigned WORD1
1 Although unsigned data types are not directly supported in BASIC, you may substitute the signed
equivalent provided you do not exceed the range of the signed data type.

B.5 BLISS Implementations


Table B–5 lists the OpenVMS data types and their corresponding BLISS data
type declarations.

Table B–5 BLISS Implementations


OpenVMS Data Types BLISS Declarations
access_bit_names BLOCKVECTOR[32,8,BYTE]
(continued on next page)

OpenVMS Data Types B–25


OpenVMS Data Types
B.5 BLISS Implementations

Table B–5 (Cont.) BLISS Implementations


OpenVMS Data Types BLISS Declarations

access_mode UNSIGNED BYTE


address UNSIGNED LONG
address_range VECTOR[2,LONG,UNSIGNED]
arg_list VECTOR[n,LONG,UNSIGNED]
where n is the number of arguments + 1.
ast_procedure UNSIGNED LONG
boolean UNSIGNED LONG
byte_signed SIGNED BYTE
byte_unsigned UNSIGNED BYTE
channel UNSIGNED WORD
char_string VECTOR[65536,BYTE,UNSIGNED]
complex_number F_Complex: VECTOR[2,LONG]
D_Complex: VECTOR[4,LONG]
G_Complex: VECTOR[4,LONG]
H_Complex: VECTOR[8,LONG]
cond_value UNSIGNED LONG
context UNSIGNED LONG
date_time VECTOR[2,LONG,UNSIGNED]
device_name VECTOR[n,BYTE,UNSIGNED]
where n is the length of the device name.
ef_cluster_name VECTOR[n,BYTE,UNSIGNED]
where n is the length of the event-flag cluster name.
ef_number UNSIGNED LONG
exit_handler_block BLOCK[n,BYTE]
where n is the size of the exit-handler control block.
fab $FAB_DECL (from STARLET.REQ)
file_protection BLOCK[2,BYTE]
floating_point F_Floating: VECTOR[1,LONG]
D_Floating: VECTOR[2,LONG]
G_Floating: VECTOR[2,LONG]
H_Floating: VECTOR[4,LONG]
function_code BLOCK[2,WORD]
identifier UNSIGNED LONG
io_status_block BLOCK[8,BYTE]
item_list_2 BLOCKVECTOR[n,8,BYTE]
where n is the number of the item descriptors + 1.
item_list_3 BLOCKVECTOR[n,12,BYTE]
where n is the number of the item descriptors + 1.
$ITMLST_DECL/$ITMLST_INIT
from STARLET.REQ
item_list_pair BLOCKVECTOR[n,2,LONG]
where n is the number of the item descriptors + 1.
(continued on next page)

B–26 OpenVMS Data Types


OpenVMS Data Types
B.5 BLISS Implementations

Table B–5 (Cont.) BLISS Implementations


OpenVMS Data Types BLISS Declarations

item_quota_list BLOCKVECTOR[n,5,BYTE]
where n is the number of the quota descriptors + 1.
lock_id UNSIGNED_LONG
lock_status_block BLOCK[n,BYTE]
where n is the size of the lock_status_block minus at
least 8.
lock_value_block BLOCK[16,BYTE]
logical_name VECTOR[255,BYTE,UNSIGNED]
longword_signed SIGNED LONG
longword_unsigned UNSIGNED LONG
mask_byte BITVECTOR[8]
mask_longword BITVECTOR[32]
mask_quadword BITVECTOR[64]
mask_word BITVECTOR[16]
null_arg UNSIGNED LONG
octaword_signed VECTOR[4,LONG,UNSIGNED]
octaword_unsigned VECTOR[4,LONG,UNSIGNED]
page_protection UNSIGNED LONG
procedure UNSIGNED LONG
process_id UNSIGNED LONG
process_name VECTOR[n,BYTE,UNSIGNED]
where n is the length of the process name.
quadword_signed VECTOR[2,LONG,UNSIGNED]
quadword_unsigned VECTOR[2,LONG,UNSIGNED]
rights_holder BLOCK[8,BYTE]
rights_id UNSIGNED LONG
rab $RAB_DECL
from STARLET.REQ
section_id VECTOR[2,LONG,UNSIGNED]
section_name VECTOR[n,BYTE,UNSIGNED]
where n is the length of the global section name.
system_access_id VECTOR[2,LONG,UNSIGNED]
time_name VECTOR[n,BYTE,UNSIGNED]
where n is the length of the time value in OpenVMS
format.
transaction_id VECTOR[4,LONG,UNSIGNED]
uic UNSIGNED LONG
user_arg UNSIGNED LONG
varying_arg UNSIGNED LONG
vector_byte_signed VECTOR[n,BYTE,SIGNED]
where n is the size of the array.
(continued on next page)

OpenVMS Data Types B–27


OpenVMS Data Types
B.5 BLISS Implementations

Table B–5 (Cont.) BLISS Implementations


OpenVMS Data Types BLISS Declarations

vector_byte_unsigned VECTOR[n,BYTE,UNSIGNED]
where n is the size of the array.
vector_longword_signed VECTOR[n,LONG,SIGNED]
where n is the size of the array.
vector_longword_unsigned VECTOR[n,LONG,UNSIGNED]
where n is the size of the array.
vector_quadword_signed BLOCKVECTOR[n,2,LONG]
where n is the size of the array.
vector_quadword_unsigned BLOCKVECTOR[n,2,LONG]
where n is the size of the array.
vector_word_signed VECTOR[n,BYTE,SIGNED]
where n is the size of the array.
vector_word_unsigned VECTOR[n,BYTE,UNSIGNED]
where n is the size of the array.
word_signed SIGNED WORD
word_unsigned UNSIGNED WORD

B.6 C and C++ Implementations


Table B–6 lists the OpenVMS data types and their corresponding C and C++ data
type declarations.

Table B–6 C and C++ Implementations


OpenVMS Data Types C and C++ Declarations
access_bit_names User defined1
access_mode unsigned char
address User defined1 *pointer2;4
2;3;4
address_range int *array [2]
arg_list User defined1
ast_procedure Pointer to function2
boolean unsigned long int
byte_signed char
byte_unsigned unsigned char
channel unsigned short int
char_string char array[n]3;5
complex_number User defined1

1 The declaration of a user-defined data structure depends on how the data will be used. Such data
structures can be declared in a variety of ways, each of which is suitable only to specific applications.
2C and C++ pointers are declared with special syntax and are associated with the data type of the
object being pointed to. This object is often user defined.
3 The term array denotes the syntax of a C or C++ array declaration.
4 The data type specified can be changed to any valid C or C++ data type.
5 The size of the array must be substituted for n.

(continued on next page)

B–28 OpenVMS Data Types


OpenVMS Data Types
B.6 C and C++ Implementations

Table B–6 (Cont.) C and C++ Implementations


OpenVMS Data Types C and C++ Declarations
cond_value unsigned long int
context unsigned long int
date_time User defined1
device_name char array[n]3;5
ef_cluster_name char array[n]3;5
ef_number unsigned long int
exit_handler_block User defined1
fab #include <fab.h>
struct FAB
file_protection unsigned short int or user defined1
floating_point float, double, or long double
function_code unsigned long int or user defined1
identifier unsigned long int *pointer2;4
invo_context_blk6 #include <libicb.h>
struct invo_context_blk
invo_handle6 unsigned long int
io_status_block User defined1
item_list_2 User defined1
item_list_3 User defined1
item_list_pair User defined1
item_quota_list User defined1
lock_id unsigned long int
lock_status_block User defined1
lock_value_block User defined1
logical_name char array[n]3;5
longword_signed long int
longword_unsigned unsigned long int
mask_byte unsigned char
mask_longword unsigned long int
mask_quadword User defined1
mask_word unsigned short int
mechanism_args #include <chfdef.h>
struct chf$mech_array
null_arg unsigned long int

1 The declaration of a user-defined data structure depends on how the data will be used. Such data
structures can be declared in a variety of ways, each of which is suitable only to specific applications.
2C and C++ pointers are declared with special syntax and are associated with the data type of the
object being pointed to. This object is often user defined.
3 The term array denotes the syntax of a C or C++ array declaration.
4 The data type specified can be changed to any valid C or C++ data type.
5 The size of the array must be substituted for n.
6 Alpha specific.

(continued on next page)

OpenVMS Data Types B–29


OpenVMS Data Types
B.6 C and C++ Implementations

Table B–6 (Cont.) C and C++ Implementations


OpenVMS Data Types C and C++ Declarations
octaword_signed User defined1
octaword_unsigned User defined1
page_protection unsigned long int
procedure Pointer to function2
process_id unsigned long int
process_name char array[n]3;5
quadword_signed User defined1
quadword_unsigned User defined1
rights_holder User defined1
rights_id unsigned long int
rab #include <rab.h>
struct RAB
section_id User defined1
section_name char array[n]3;5
system_access_id User defined1
time_name char array[n]3;5
transaction_id User defined1
uic unsigned long int
user_arg User defined1
varying_arg User defined1
vector_byte_signed char array[n]3;5
vector_byte_unsigned unsigned char array[n]3;5
vector_longword_signed long int array[n]3;5
vector_longword_unsigned unsigned long int array[n]3;5
vector_quadword_signed User defined1
vector_quadword_unsigned User defined1
vector_word_signed short int array[n]3;5
vector_word_unsigned unsigned short int array[n]3;5
word_signed short int
word_unsigned unsigned short int
1 The declaration of a user-defined data structure depends on how the data will be used. Such data
structures can be declared in a variety of ways, each of which is suitable only to specific applications.
2C and C++ pointers are declared with special syntax and are associated with the data type of the
object being pointed to. This object is often user defined.
3 The term array denotes the syntax of a C or C++ array declaration.
5 The size of the array must be substituted for n.

B.7 COBOL Implementations


Table B–7 lists the OpenVMS data types and their corresponding COBOL data
type declarations.

B–30 OpenVMS Data Types


OpenVMS Data Types
B.7 COBOL Implementations

Table B–7 COBOL Implementations


OpenVMS Data Types COBOL Declarations
access_bit_names na . . . PIC X(128)1
access_mode na . . . PIC X1
The access_mode data type is usually passed BY VALUE
as PIC 9(5) COMP.
address USAGE POINTER
address_range 01 ADDRESS-RANGE
02 BEGINNING-ADDRESS USAGE POINTER
02 ENDING-ADDRESS USAGE POINTER
arg_list na . . . Constructed by the compiler as a result of using
the COBOL CALL statement. An argument list may
be created as follows, but cannot be referenced by the
COBOL CALL statement.

01 ARG-LIST
02 ARG-COUNT PIC S9(5) COMP
02 ARG-BY-VALUE PIC S9(5) COMP
02 ARG-BY-REFERENCE USAGE POINTER
02 VALUE REFERENCE ARG-NAME
. . . continue as needed
ast_procedure 01 AST-PROC PIC 9(5) COMP2
boolean 01 BOOLEAN-VALUE PIC 9(5) COMP2
byte_signed na . . . PIC X1
byte_unsigned na . . . PIC X1
channel 01 CHANNEL PIC 9(4) COMP2
char_string 01 CHAR-STRING PIC X to PIC X(65535)
complex_number na . . . PIC X(n), where n is the length.1
cond_value 01 COND-VALUE PIC 9(5) COMP2
context 01 CONTEXT PIC 9(5) COMP2
date_time na . . . PIC X(16)1
device_name 01 DEVICE-NAME PIC X(n), where n is the length.
ef_cluster_name 01 CLUSTER-NAME PIC X(n), where n is the length.
ef_number 01 EF-NO PIC 9(5) COMP2
exit_handler_block na . . . PIC X(n), where n is the length.1
fab na . . . Too complex for general COBOL use. Most of a
FAB structure can be described by a lengthy COBOL
record description, but such a FAB cannot then be
referenced by a COBOL I-O statement. It is much
simpler to do the I-O completely within COBOL, and let
the COBOL compiler generate the FAB structure or do
the I-O in another language.
file_protection 01 FILE-PROT PIC 9(4) COMP2

1 Most OpenVMS data types not directly supported in COBOL can be represented as an alphanumeric
data item of a certain number of bytes. While COBOL does not interpret the data type, you can use it
to pass objects from one language to another.
2 Although unsigned computational data structures are not directly supported in COBOL, you may
substitute the signed equivalent provided you do not exceed the range of the signed data structure.

(continued on next page)

OpenVMS Data Types B–31


OpenVMS Data Types
B.7 COBOL Implementations

Table B–7 (Cont.) COBOL Implementations


OpenVMS Data Types COBOL Declarations
floating_point 01 F-FLOAT USAGE COMP-1
01 D-FLOAT USAGE COMP-2
The G-float and H-float data types are not supported in
COBOL.
function_code 01 FUNCTION-CODE
02 MAJOR-FUNCTION PIC 9(4) COMP2
02 SUB-FUNCTION PIC 9(4) COMP2
identifier 01 ID PIC 9(5) COMP2
invo_context_blk3 na
3
invo_handle na
io_status_block 01 IOSB
02 COND-VAL PIC 9(4) COMP2
02 BYTE-CNT PIC 9(4) COMP2
02 DEV-INFO PIC 9(5) COMP2
item_list_2 01 ITEM-LIST-TWO
02 ITEM-LIST OCCURS n TIMES
04 COMP-LENGTH PIC S9(4) COMP
04 ITEM-CODE PIC S9(4) COMP
04 COMP-ADDRESS PIC S9(5) COMP
02 TERMINATOR PIC S9(5) COMP VALUE 0
item_list_3 01 ITEM-LIST-3
02 ITEM-LIST OCCURS n TIMES
04 BUF-LEN PIC S9(4) COMP
04 ITEM-CODE PIC S9(4) COMP
04 BUFFER-ADDRESS PIC S9(5) COMP
04 LENGTH-ADDRESS PIC S9(5) COMP
02 TERMINATOR PIC S9(5) COMP VALUE 0
item_list_pair 01 ITEM-LIST-PAIR
02 ITEM-LIST OCCURS n TIMES
04 ITEM-CODE PIC S9(5) COMP
04 ITEM-VALUE PIC S9(5) COMP
02 TERMINATOR PIC S9(5) COMP VALUE 0
item_quota_list na
lock_id 01 LOCK-ID PIC 9(5) COMP2
lock_status_block na
lock_value_block na
logical_name 01 LOG-NAME PIC X TO X(255)
longword_signed 01 LWS PIC S9(5) COMP
longword_unsigned 01 LWU PIC 9(5) COMP2
mask_byte na . . . PIC X1
mask_longword 01 MLW PIC 9(5) COMP2
mask_quadword 01 MQW PIC 9(18) COMP2

1 Most OpenVMS data types not directly supported in COBOL can be represented as an alphanumeric
data item of a certain number of bytes. While COBOL does not interpret the data type, you can use it
to pass objects from one language to another.
2 Although unsigned computational data structures are not directly supported in COBOL, you may
substitute the signed equivalent provided you do not exceed the range of the signed data structure.
3 Alpha specific.

(continued on next page)

B–32 OpenVMS Data Types


OpenVMS Data Types
B.7 COBOL Implementations

Table B–7 (Cont.) COBOL Implementations


OpenVMS Data Types COBOL Declarations
mask_word 01 MW PIC 9(4) COMP2
mechanism_args na
null_arg CALL . . . USING OMITTED or
PIC S9(5) COMP VALUE 0 passed USING BY VALUE
octaword_signed na
octaword_unsigned na
page_protection 01 PAGE-PROT PIC 9(5) COMP2
procedure 01 ENTRY-MASK PIC 9(5) COMP2
process_id 01 PID PIC 9(5) COMP2
process_name 01 PROCESS-NAME PIC X TO X(15)
quadword_signed 01 QWS PIC S9(18) COMP
quadword_unsigned 01 QWU PIC 9(18) COMP2
rights_holder 01 RIGHTS-HOLDER
02 RIGHTS-ID PIC 9(5) COMP2
02 ACCESS-RIGHTS PIC 9(5) COMP2
rights_id 01 RIGHTS-ID PIC 9(5) COMP2
rab na . . . Too complex for general COBOL use. Most of a
RAB structure can be described by a lengthy COBOL
record description, but such a RAB cannot then be
referenced by a COBOL I-O statement. It is much
simpler to do the I-O completely within COBOL, and let
the COBOL compiler generate the RAB structure, or do
the I-O in another language.
section_id 01 SECTION-ID PIC 9(18) COMP2
section_name 01 SECTION-NAME PIC X to X(43)
system_access_id 01 SECTION-ACCESS-ID PIC 9(18) COMP2
time_name 01 TIME-NAME PIC X(n), where n is the length.
transaction_id na
uic 01 UIC PIC 9(5) COMP2
user_arg 01 USER-ARG PIC 9(5) COMP2
varying_arg Depends on the application.
3
vector_byte_signed na . . .
3
vector_byte_unsigned na . . .
3
vector_longword_signed na . . .
3
vector_longword_unsigned na . . .
3
vector_quadword_signed na . . .
3
vector_quadword_unsigned na . . .
3
vector_word_signed na . . .
2 Although unsigned computational data structures are not directly supported in COBOL, you may
substitute the signed equivalent provided you do not exceed the range of the signed data structure.
3 Alpha specific.

(continued on next page)

OpenVMS Data Types B–33


OpenVMS Data Types
B.7 COBOL Implementations

Table B–7 (Cont.) COBOL Implementations


OpenVMS Data Types COBOL Declarations
4
vector_word_unsigned na . . .
word_signed 01 WS PIC S9(4) COMP
word_unsigned 01 WS PIC 9(4) COMP2
2 Although unsigned computational data structures are not directly supported in COBOL, you may
substitute the signed equivalent provided you do not exceed the range of the signed data structure.
4 COBOL does not permit the passing of variable-length data structures.

B.8 FORTRAN Implementations


Table B–8 lists the OpenVMS data types and their corresponding FORTRAN data
type declarations.

Table B–8 FORTRAN Implementations


OpenVMS Data Types FORTRAN Declarations
access_bit_names INTEGER*4(2,32)
or
STRUCTURE /access_bit_names/
INTEGER*4 access_name_len
INTEGER*4 access_name_buf
END STRUCTURE !access_bit_names
RECORD /access_bit_names/ my_names(32)
access_mode BYTE
or
INTEGER*11
address INTEGER*4
address_range INTEGER*4(2)
or
INTEGER*81
or
STRUCTURE /address_range/
INTEGER*4 low_address
INTEGER*4 high_address
END STRUCTURE
arg_list INTEGER*4(n)
or
INTEGER*81 (n)
ast_procedure EXTERNAL
boolean LOGICAL*4
byte_signed BYTE
or
INTEGER*1

1 Alpha specific.

(continued on next page)

B–34 OpenVMS Data Types


OpenVMS Data Types
B.8 FORTRAN Implementations

Table B–8 (Cont.) FORTRAN Implementations


OpenVMS Data Types FORTRAN Declarations
byte_unsigned BYTE2
or
INTEGER*11 , 2

channel INTEGER*2
char_string CHARACTER*n
complex_number COMPLEX*8
COMPLEX*16
cond_value INTEGER*4
context INTEGER*4
date_time INTEGER*4(2)
or
INTEGER*81
device_name CHARACTER*n
ef_cluster_name CHARACTER*n
ef_number INTEGER*4
exit_handler_block STRUCTURE /exhblock/
INTEGER*4 flink
INTEGER*4 exit_handler_addr
BYTE(3) /0/
BYTE arg_count
INTEGER*4 cond_value
! .
! .(optional arguments . . . one argument
! . per longword)
!
END STRUCTURE !cntrlblk

RECORD /exhblock/ myexh_block


fab INCLUDE ’($FABDEF)’
RECORD /fabdef/ myfab
file_protection INTEGER*4
floating_point REAL*43
REAL*83
DOUBLE PRECISION3
REAL*164
function_code INTEGER*4
identifier INTEGER*4
1
invo_context_blk INCLUDE (’LIBICB’)
RECORD /INVO_CONTEXT_BLK/ invo_context_blk
invo_handle1 INTEGER*4

1 Alpha specific.
2 Unsigned data types are not directly supported by FORTRAN. However, in most cases you can
substitute the signed equivalent as long as you do not exceed the range of the signed data structure.
3 The format used by floating-point data in memory is determined by the FORTRAN command qualifier
/FLOAT.
4 The REAL*16 type is used for both H_floating on VAX systems and X_floating on Alpha systems.

(continued on next page)

OpenVMS Data Types B–35


OpenVMS Data Types
B.8 FORTRAN Implementations

Table B–8 (Cont.) FORTRAN Implementations


OpenVMS Data Types FORTRAN Declarations
io_status_block STRUCTURE /iosb/
INTEGER*2 iostat, !return status
2 term_offset, !location of line terminator
2 terminator, !value of terminator
2 term_size !size of terminator
END STRUCTURE

RECORD /iosb/ my_iosb


item_list_2 STRUCTURE /itmlst/
UNION
MAP
INTEGER*2 buflen,code
INTEGER*4 bufadr
END MAP
MAP
INTEGER*4 end_list /0/
END MAP
END UNION
END STRUCTURE !itmlst

RECORD /itmlst/ my_itmlst_2(n)


(Allocate n records, where n is the number of item
codes plus an extra element for the end-of-list item.)
item_list_3 STRUCTURE /itmlst/
UNION
MAP
INTEGER*2 buflen,code
INTEGER*4 bufadr,retlenadr
END MAP
MAP
INTEGER*4 end_list /0/
END MAP
END UNION
END STRUCTURE !itmlst

RECORD /itmlst/ my_itmlst_2(n)


(Allocate n records, where n is the number of item
codes plus an extra element for the end-of-list item.)
item_list_pair STRUCTURE /itmlist_pair/
UNION
MAP
INTEGER*4 code
INTEGER*4 value
END MAP
MAP
INTEGER*4 end_list /0/
END MAP
END UNION
END STRUCTURE !itmlst_pair

RECORD /itmlst_pair/ my_itmlst_pair(n)


(Allocate n records, where n is the number of item
codes plus an extra element for the end-of-list item.)

(continued on next page)

B–36 OpenVMS Data Types


OpenVMS Data Types
B.8 FORTRAN Implementations

Table B–8 (Cont.) FORTRAN Implementations


OpenVMS Data Types FORTRAN Declarations
item_quota_list STRUCTURE /item_quota_list/
MAP
BYTE quota_name
INTEGER*4 quota_value
END MAP
MAP
BYTE end_quota_list
END MAP
END STRUCTURE !item_quota_list
lock_id INTEGER*4
lock_status_block STRUCTURE/lksb/
INTEGER*2 cond_value
INTEGER*2 unused
INTEGER*4 lock_id
BYTE(16)
END STRUCTURE !lock_status_lock
lock_value_block BYTE(16)
logical_name CHARACTER*n
longword_signed INTEGER*4
longword_unsigned INTEGER*42
mask_byte BYTE
or
INTEGER*1
mask_longword INTEGER*4
mask_quadword INTEGER*4(2)
or
INTEGER*81
mask_word INTEGER*2
mechanism_args INCLUDE ’($CHFDEF)’
RECORD /CHFDEF2/ mechargs
null_arg %VAL(0)
octaword_signed INTEGER*4(4)
octaword_unsigned INTEGER*4(4)2
page_protection INTEGER*4
procedure INTEGER*4
process_id INTEGER*4
process_name CHARACTER*n
quadword_signed INTEGER*4(2)
or
INTEGER*81
quadword_unsigned INTEGER*4(2)2
or
INTEGER*81

1 Alpha specific.
2 Unsigned data types are not directly supported by FORTRAN. However, in most cases you can
substitute the signed equivalent as long as you do not exceed the range of the signed data structure.

(continued on next page)

OpenVMS Data Types B–37


OpenVMS Data Types
B.8 FORTRAN Implementations

Table B–8 (Cont.) FORTRAN Implementations


OpenVMS Data Types FORTRAN Declarations
rights_holder INTEGER*4(2)
or
STRUCTURE /rights_holder/
INTEGER*4 rights_id
INTEGER*4 rights_mask
END STRUCTURE !rights_holder
rights_id INTEGER*4
rab INCLUDE ’($RABDEF)’
RECORD /rabdef/ myrab
section_id INTEGER*4(2)
or
INTEGER*81
section_name CHARACTER*n
system_access_id INTEGER*4(2)
or
INTEGER*81
time_name CHARACTER*23
transaction_id INTEGER*4(4)2
uic INTEGER*4
user_arg Any longword quantity
varying_arg INTEGER*4
vector_byte_signed BYTE(n)
vector_byte_unsigned BYTE(n)2
vector_longword_signed INTEGER*4(n)
vector_longword_unsigned INTEGER*4(n)2
vector_quadword_signed INTEGER*4(2,n)
or
INTEGER*8(n1 )
vector_quadword_unsigned INTEGER*4(2,n)2
or
INTEGER*8(n)1 ,2
vector_word_signed INTEGER*2(n)
vector_word_unsigned INTEGER*2(n)2
word_signed INTEGER*2(n)
word_unsigned INTEGER*2(n)2
1 Alpha specific.
2 Unsigned data types are not directly supported by FORTRAN. However, in most cases you can
substitute the signed equivalent as long as you do not exceed the range of the signed data structure.

B.9 Pascal Implementations


Table B–9 lists the OpenVMS data types and their corresponding Pascal data
type declarations.

B–38 OpenVMS Data Types


OpenVMS Data Types
B.9 Pascal Implementations

Table B–9 Pascal Implementations


OpenVMS Data Types Pascal Declarations
access_bit_names PACKED ARRAY [1..32] OF [QUAD] RECORD END;1;2
access_mode [BYTE] 0..3;2
address UNSIGNED;
address_range PACKED ARRAY [1..2] OF UNSIGNED;2
arg_list PACKED ARRAY [1..n] OF UNSIGNED;2
ast_procedure UNSIGNED;
boolean BOOLEAN;3
byte_signed [BYTE] 0128..127;2
byte_unsigned [BYTE] 0..255;2
channel [WORD] 0..65535;2
char_string [CLASS_S] PACKED ARRAY [L..U:INTEGER] OF
CHAR;4
complex_number [LONG(2)] RECORD END; * F_Floating Complex *1;2
[QUAD(2)] RECORD END; * D/G_Floating Complex *
[OCTA(2)] RECORD END; * H_Floating Complex *
cond_value UNSIGNED;
context UNSIGNED;
date_time [QUAD] RECORD END;1;2
device_name [CLASS_S] PACKED ARRAY [L..U:INTEGER] OF
CHAR;4
ef_cluster_name [CLASS_S] PACKED ARRAY [L..U:INTEGER] OF
CHAR;4
ef_number UNSIGNED;
exit_handler_block PACKED ARRAY [1..n] OF UNSIGNED;2
fab FAB$TYPE;5
file_protection [WORD] RECORD END;1;2
floating_point REAL; { F_Floating }
SINGLE; { F_Floating }
DOUBLE; { D_Floating/G_Floating }6
QUADRUPLE; { H_Floating }
function_code UNSIGNED;
identifier UNSIGNED;

1 Thistype is not available in Pascal when an empty record has been inserted. To manipulate the
contents, declare with explicit field components. If you pass an empty record as a parameter to a
Pascal routine, you must use the VAR keyword.
2 Pascalexpects either a type identifier or conformant schema. Declare this under the TYPE
declaration and use the type identifier in the formal parameter declaration.
3 Pascalallocates a byte for a BOOLEAN variable. Use the [LONG] attribute when passing to routines
that expect a longword.
4 This
parameter declaration accepts VARYING OF CHAR or PACKED ARRAY OF CHAR and
produces the CLASS_S descriptor required by system services.
5 The program must inherit the STARLET environment file located in SYS$LIBRARY:STARLET.PEN.
6 If
the {G_Floating} attribute is used in compiling, double-precision variables and expressions are
represented in G_floating format. You can also use the /G_FLOATING command line qualifier. Both
methods default to no G_floating.

(continued on next page)

OpenVMS Data Types B–39


OpenVMS Data Types
B.9 Pascal Implementations

Table B–9 (Cont.) Pascal Implementations


OpenVMS Data Types Pascal Declarations
7
invo_context_blk LIBICB$INFO_CONTEXT_BLK5
7
invo_handle [UNSAFE]INTEGER;
io_status_block [QUAD] RECORD END;1;2
item_list_2 PACKED ARRAY [1..n] OF PACKED RECORD2
CASE INTEGER OF
1: (
FIELD1 : [WORD] 0..65535;
FIELD2 : [WORD] 0..65535;
FIELD3 : UNSIGNED);
2: (
TERMINATOR : UNSIGNED);
END;
item_list_3 PACKED ARRAY [1..n] OF PACKED RECORD2
CASE INTEGER OF
1: (
FIELD1 : [WORD] 0..65535;
FIELD2 : [WORD] 0..65535;
FIELD3 : UNSIGNED;
FIELD4 : UNSIGNED);
2: (
TERMINATOR : UNSIGNED);
END;
item_list_pair PACKED ARRAY [1..n] OF PACKED RECORD2
CASE INTEGER OF
1: (
FIELD1 : INTEGER;
FIELD2 : INTEGER);
2: (
TERMINATOR : UNSIGNED);
END;
item_quota_list PACKED ARRAY [1..n] OF PACKED RECORD2
CASE INTEGER OF
1: (
QUOTA_NAME : [BYTE] 0..255;
QUOTA_VALUE: UNSIGNED);
2: (
QUOTA_TERM : [BYTE] 0..255);
END;
lock_id UNSIGNED;
lock_status_block [BYTE(24)] RECORD END;1;2
lock_value_block [BYTE(16)] RECORD END;1;2
logical_name [CLASS_S] PACKED ARRAY [L..U:INTEGER] OF
CHAR;4

1 Thistype is not available in Pascal when an empty record has been inserted. To manipulate the
contents, declare with explicit field components. If you pass an empty record as a parameter to a
Pascal routine, you must use the VAR keyword.
2 Pascalexpects either a type identifier or conformant schema. Declare this under the TYPE
declaration and use the type identifier in the formal parameter declaration.
4 This
parameter declaration accepts VARYING OF CHAR or PACKED ARRAY OF CHAR and
produces the CLASS_S descriptor required by system services.
5 The program must inherit the STARLET environment file located in SYS$LIBRARY:STARLET.PEN.
7 Alpha specific.

(continued on next page)

B–40 OpenVMS Data Types


OpenVMS Data Types
B.9 Pascal Implementations

Table B–9 (Cont.) Pascal Implementations


OpenVMS Data Types Pascal Declarations
longword_signed INTEGER;
longword_unsigned UNSIGNED;
mask_byte [BYTE,UNSAFE] PACKED ARRAY [1..8] OF BOOLEAN;2
mask_longword [LONG,UNSAFE] PACKED ARRAY [1..32] OF
BOOLEAN;2
mask_quadword [QUAD,UNSAFE] PACKED ARRAY [1..64] OF
BOOLEAN;2
mask_word [WORD,UNSAFE] PACKED ARRAY [1..16] OF
BOOLEAN;2
mechanism_args CHF$TYPE;5
null_arg UNSIGNED;
octaword_signed [OCTA] RECORD END;1;2
octaword_unsigned [OCTA] RECORD END;1;2
page_protection [LONG] 0..7;2
procedure UNSIGNED;
process_id UNSIGNED;
process_name [CLASS_S] PACKED ARRAY [L..U:INTEGER] OF
CHAR;4
quadword_signed [QUAD] RECORD END;1;2
quadword_unsigned [QUAD] RECORD END;1;2
rights_holder [QUAD] RECORD END;1;2
rights_id UNSIGNED;
rab RAB$TYPE;5
section_id [QUAD] RECORD END;1;2
section_name [CLASS_S] PACKED ARRAY [L..U:INTEGER] OF
CHAR;4
system_access_id [QUAD] RECORD END;1;2
time_name [CLASS_S] PACKED ARRAY [L..U:INTEGER] OF
CHAR;4
transaction_id [OCTA] RECORD END;1;2
uic UNSIGNED;
user_arg [UNSAFE] UNSIGNED;
varying_arg [UNSAFE,REFERENCE] PACKED ARRAY
[L..U:INTEGER] OF [BYTE] 0..255;
vector_byte_signed PACKED ARRAY [1..n] OF [BYTE] 0128..127;2
vector_byte_unsigned PACKED ARRAY [1..n] OF [BYTE] 0..255;2

1 Thistype is not available in Pascal when an empty record has been inserted. To manipulate the
contents, declare with explicit field components. If you pass an empty record as a parameter to a
Pascal routine, you must use the VAR keyword.
2 Pascalexpects either a type identifier or conformant schema. Declare this under the TYPE
declaration and use the type identifier in the formal parameter declaration.
4 This
parameter declaration accepts VARYING OF CHAR or PACKED ARRAY OF CHAR and
produces the CLASS_S descriptor required by system services.
5 The program must inherit the STARLET environment file located in SYS$LIBRARY:STARLET.PEN.

(continued on next page)

OpenVMS Data Types B–41


OpenVMS Data Types
B.9 Pascal Implementations

Table B–9 (Cont.) Pascal Implementations


OpenVMS Data Types Pascal Declarations
vector_longword_signed PACKED ARRAY [1..n] OF INTEGER;2
vector_longword_unsigned PACKED ARRAY [1..n] OF UNSIGNED;2
vector_quadword_signed PACKED ARRAY [1..n] OF [QUAD] RECORD END;1;2
vector_quadword_unsigned PACKED ARRAY [1..n] OF [QUAD] RECORD END;1;2
vector_word_signed PACKED ARRAY [1..n] OF [WORD] 032768..32767;2
vector_word_unsigned PACKED ARRAY [1..n] OF [WORD] 0..65535;2
word_signed [WORD] 032768..32767;2
word_unsigned [WORD] 0..65535;2
1 Thistype is not available in Pascal when an empty record has been inserted. To manipulate the
contents, declare with explicit field components. If you pass an empty record as a parameter to a
Pascal routine, you must use the VAR keyword.
2 Pascalexpects either a type identifier or conformant schema. Declare this under the TYPE
declaration and use the type identifier in the formal parameter declaration.

B.10 PL/I Implementations


Table B–10 lists the OpenVMS data types and their corresponding PL/I data type
declarations.

Table B–10 PL/I Implementations


OpenVMS Data Types PL/I Declarations
access_bit_names 1 ACCESS_BIT_NAMES(32),
2 LENGTH FIXED BINARY(15),
2 DTYPE FIXED BINARY(7)
INITIAL((32)DSC$K_DTYPE_T),
2 CLASS FIXED BINARY(7)
INITIAL((32)DSC$K_CLASS_S),
2 CHAR_PTR POINTER;1
The length of the LENGTH field in each element of
the array should correspond to the length of a string
of characters pointed to by the CHAR_PTR field. The
constants DSC$K_CLASS_S and DSC$K_DTYPE_T
can be used by including the module $DSCDEF from
PLI$STARLET.
access_mode FIXED BINARY(7)
(The constants for this type—PSL$C_KERNEL, PSL$C_
EXEC, PSL$C_SUPER, PSL$C_USER—are declared in
module $PSLDEF in PLI$STARLET.)
address POINTER
address_range (2) POINTER1

1 System routines are often written so the parameter passed occupies more storage than the object
requires. For example, some system services have parameters that return a bit value as a longword.
These variables must be declared BIT(32) ALIGNED (not BIT(n) ALIGNED) so that adjacent storage
is not overwritten by return values or used incorrectly as input. (Longword parameters are always
declared BIT(32) ALIGNED.)

(continued on next page)

B–42 OpenVMS Data Types


OpenVMS Data Types
B.10 PL/I Implementations

Table B–10 (Cont.) PL/I Implementations


OpenVMS Data Types PL/I Declarations
arg_list 1 ARG_LIST BASED,
2 ARGCOUNT FIXED BINARY(31),
2 ARGUMENT (X REFER (ARGCOUNT))
POINTER;1
If the arguments are passed by value, you may need
to change the type of the ARGUMENT field of the
structure. Alternatively, you can use the POSINT, INT,
or UNSPEC built-in functions and pseudovariables to
access the data. X should be an expression with a value
in the range 0 to 255 when the structure is allocated.
ast_procedure PROCEDURE or ENTRY2
boolean BIT ALIGNED1
byte_signed FIXED BINARY(7)
byte_unsigned FIXED BINARY(7)3
channel FIXED BINARY(15)
char_string CHARACTER(n)4
complex_number (2) FLOAT BINARY(n) (See floating_point for values
of n.)
cond_value See STS$VALUE in module $STSDEF in
PLI$STARLET.1
context FIXED BINARY(31)
date_time BIT(64) ALIGNED5;6
device_name CHARACTER(n)4
ef_cluster_name CHARACTER(n)4
ef_number FIXED BINARY(31)

1 System routines are often written so the parameter passed occupies more storage than the object
requires. For example, some system services have parameters that return a bit value as a longword.
These variables must be declared BIT(32) ALIGNED (not BIT(n) ALIGNED) so that adjacent storage
is not overwritten by return values or used incorrectly as input. (Longword parameters are always
declared BIT(32) ALIGNED.)
2 AST procedures and those passed as parameters of type ENTRY VALUE or ANY VALUE must be
external procedures. This applies to all system routines that take procedure parameters.
3 This is actually an unsigned integer. This declaration is interpreted as a signed number; use the
POSINT function to determine the actual value.
4 System services require CHARACTER string representation for parameters. Most other system
routines allow either CHARACTER or CHARACTER VARYING. For parameter declarations, n should
be an asterisk (*).
5 PL/I does not support FIXED BINARY numbers with precisions greater than 31. To use larger
values, declare variables to be BIT variables of the appropriate size and use the POSINT and
SUBSTR bits as necessary to access the values, or declare the item as a structure. The RTL routines
LIB$ADDX and LIB$SUBX may be useful if you need to perform arithmetic on these types.
6 Routinesdeclared in PLI$STARLET often use ANY, so you are free to declare the data structure
in the most convenient way for the application. ANY may be necessary in some cases because PL/I
does not allow parameter declarations for some data types used by OpenVMS. (In particular, PL/I
parameters with arrays passed by reference cannot be declared to have nonconstant bounds.)

(continued on next page)

OpenVMS Data Types B–43


OpenVMS Data Types
B.10 PL/I Implementations

Table B–10 (Cont.) PL/I Implementations


OpenVMS Data Types PL/I Declarations
exit_handler_block 1 EXIT_HANDLER_BLOCK BASED,
2 FORWARD_LINK POINTER,
2 HANDLER POINTER,
2 ARGCOUNT FIXED BINARY(31),
2 ARGUMENT (n REFER (ARGCOUNT))
POINTER;1
(Replace n with an expression that yields a value
between 0 and 255 when the structure is allocated.)
fab See module $FABDEF in PLI$STARLET.
file_protection BIT(16) ALIGNED1
floating_point FLOAT BINARY(n)
The values for n are as follows:
1 <= n <= 24 — F_floating
25 <= n <= 53 — D_floating
25 <= n <= 53 — G_floating (with /G_FLOAT)
54 <= n <= 113 — H_floating
function_code BIT(32) ALIGNED
identifier POINTER
7
invo_context_blk %INCLUDE LIBICB
7
invo_handle FIXED BINARY(31)
io_status_block Because the format for I/O status blocks differs with the
system service, you can vary the definitions accordingly.
Some of the common formats are as follows:
1 IOSB_SYS$GETSYI,
2 STATUS FIXED BINARY(31),
2 RESERVED FIXED BINARY(31);
1 IOSB_TTDRIVER_A,
2 STATUS FIXED BINARY(15),
2 BYTE_COUNT FIXED BINARY(15),
2 MBZ FIXED BINARY(31) INITIAL(0);
1 IOSB_TTDRIVER_B,
2 STATUS FIXED BINARY(15),
2 TRANSMIT_SPEED FIXED BINARY(7),
2 RECEIVE_SPEED FIXED BINARY(7),
2 CR_FILL FIXED BINARY(7),
2 LF_FILL FIXED BINARY(7),
2 PARITY_FLAGS FIXED BINARY(7),
2 MBZ FIXED BINARY(7) INITIAL(0);

1 System routines are often written so the parameter passed occupies more storage than the object
requires. For example, some system services have parameters that return a bit value as a longword.
These variables must be declared BIT(32) ALIGNED (not BIT(n) ALIGNED) so that adjacent storage
is not overwritten by return values or used incorrectly as input. (Longword parameters are always
declared BIT(32) ALIGNED.)
7 Alpha specific.

(continued on next page)

B–44 OpenVMS Data Types


OpenVMS Data Types
B.10 PL/I Implementations

Table B–10 (Cont.) PL/I Implementations


OpenVMS Data Types PL/I Declarations
item_list_2 1 ITEM_LIST_2,
2 ITEM(SIZE),
3 COMPONENT_LENGTH FIXED
BINARY(15),
3 ITEM_CODE FIXED BINARY(15),
3 COMPONENT_ADDRESS POINTER,
2 TERMINATOR FIXED BINARY(31)
INITIAL(0);1

(Replace SIZE with the number of items you want.)


item_list_3 1 ITEM_LIST_3,
2 ITEM(SIZE),
3 BUFFER_LENGTH FIXED
BINARY(15),
3 ITEM_CODE FIXED BINARY(15),
3 BUFFER_ADDRESS POINTER,
3 RETURN_LENGTH POINTER,
2 TERMINATOR FIXED BINARY(31)
INITIAL(0);1

(Replace SIZE with the number of items you want.)


item_list_pair 1 ITEM_LIST_PAIR,
2 ITEM(SIZE),
3 ITEM_CODE FIXED BINARY(31),
3 ITEM UNION,
4 INTEGER FIXED BINARY(31),
4 REAL FLOAT BINARY(24),
2 TERMINATOR FIXED BINARY(31)
INITIAL(0);1

(Replace SIZE with the number of items you want.)


item_quota_list 1 ITEM_QUOTA_LIST,
2 QUOTA(SIZE),
3 NAME FIXED BINARY(7),
3 VALUE FIXED BINARY(31),
2 TERMINATOR FIXED BINARY(7)
INITIAL(PQL$_LISTEND);1
(Replace SIZE with the number of quota entries you
want to use. The constant PQL$_LISTEND can be used
by including the module $PQLDEF from PLI$STARLET
or by declaring it GLOBALREF FIXED BINARY(31)
VALUE.)
lock_id FIXED BINARY(31)
lock_status_block 1 LOCK_STATUS_BLOCK,
2 STATUS_CODE FIXED BINARY(15),
2 RESERVED FIXED BINARY(15),
2 LOCK_ID FIXED BINARY(31);1

1 System routines are often written so the parameter passed occupies more storage than the object
requires. For example, some system services have parameters that return a bit value as a longword.
These variables must be declared BIT(32) ALIGNED (not BIT(n) ALIGNED) so that adjacent storage
is not overwritten by return values or used incorrectly as input. (Longword parameters are always
declared BIT(32) ALIGNED.)

(continued on next page)

OpenVMS Data Types B–45


OpenVMS Data Types
B.10 PL/I Implementations

Table B–10 (Cont.) PL/I Implementations


OpenVMS Data Types PL/I Declarations
lock_value_block The declaration of an item of this structure depends on
the use of the structure because the OpenVMS operating
system does not interpret the value.1
logical_name CHARACTER(n)4
longword_signed FIXED BINARY(31)
longword_unsigned FIXED BINARY(31)3
mask_byte BIT(8) ALIGNED
mask_longword BIT(32) ALIGNED
mask_quadword BIT(64) ALIGNED
mask_word BIT(16) ALIGNED
mechanism_args INCLUDE $CHFDEF
Declare mechanism_args like CHF$MECH_ARRAY
null_arg Omit the corresponding parameter in the call. For
example, FOO(A,,B) would omit the second parameter.
octaword_signed BIT(128) ALIGNED5;6
octaword_unsigned BIT(128) ALIGNED5;6
page_protection FIXED BINARY(31) (The constants for this type are
declared in module $PRTDEF in PLI$STARLET.)
procedure PROCEDURE or ENTRY2
process_id FIXED BINARY(31)
process_name CHARACTER(n)4
quadword_signed BIT(64) ALIGNED5;6
quadword_unsigned BIT(64) ALIGNED5;6
rights_holder 1 RIGHTS_HOLDER,
2 RIGHTS_ID FIXED BINARY(31),
2 ACCESS_RIGHTS BIT(32)
ALIGNED;1
rights_id FIXED BINARY(31)
rab See module $RABDEF in PLI$STARLET.1

1 System routines are often written so the parameter passed occupies more storage than the object
requires. For example, some system services have parameters that return a bit value as a longword.
These variables must be declared BIT(32) ALIGNED (not BIT(n) ALIGNED) so that adjacent storage
is not overwritten by return values or used incorrectly as input. (Longword parameters are always
declared BIT(32) ALIGNED.)
2 AST procedures and those passed as parameters of type ENTRY VALUE or ANY VALUE must be
external procedures. This applies to all system routines that take procedure parameters.
3 This is actually an unsigned integer. This declaration is interpreted as a signed number; use the
POSINT function to determine the actual value.
4 System services require CHARACTER string representation for parameters. Most other system
routines allow either CHARACTER or CHARACTER VARYING. For parameter declarations, n should
be an asterisk (*).
5 PL/I does not support FIXED BINARY numbers with precisions greater than 31. To use larger
values, declare variables to be BIT variables of the appropriate size and use the POSINT and
SUBSTR bits as necessary to access the values, or declare the item as a structure. The RTL routines
LIB$ADDX and LIB$SUBX may be useful if you need to perform arithmetic on these types.
6 Routinesdeclared in PLI$STARLET often use ANY, so you are free to declare the data structure
in the most convenient way for the application. ANY may be necessary in some cases because PL/I
does not allow parameter declarations for some data types used by OpenVMS. (In particular, PL/I
parameters with arrays passed by reference cannot be declared to have nonconstant bounds.)

(continued on next page)

B–46 OpenVMS Data Types


OpenVMS Data Types
B.10 PL/I Implementations

Table B–10 (Cont.) PL/I Implementations


OpenVMS Data Types PL/I Declarations
section_id BIT(64) ALIGNED
section_name CHARACTER(n)4
system_access_id BIT(64) ALIGNED
time_name CHARACTER(n)4
transaction_id BIT(128) ALIGNED5;6
uic FIXED BINARY(31)
user_arg ANY
varying_arg ANY with OPTIONS(VARIABLE) on the routine
declaration or with OPTIONAL on the parameter
declaration.
vector_byte_signed (n) FIXED BINARY(7)8
vector_byte_unsigned (n) FIXED BINARY(7)3;8
vector_longword_signed (n) FIXED BINARY(31)8
vector_longword_unsigned (n) FIXED BINARY(31)3;8
5;6;8
vector_quadword_signed (n) BIT(64) ALIGNED
vector_quadword_unsigned (n) BIT(64) ALIGNED3;5;6;8
vector_word_signed (n) FIXED BINARY(15)8
vector_word_unsigned (n) FIXED BINARY(15)3;8
word_signed FIXED BINARY(15)
word_unsigned FIXED BINARY(15)5
3 This is actually an unsigned integer. This declaration is interpreted as a signed number; use the
POSINT function to determine the actual value.
4 System services require CHARACTER string representation for parameters. Most other system
routines allow either CHARACTER or CHARACTER VARYING. For parameter declarations, n should
be an asterisk (*).
5 PL/Idoes not support FIXED BINARY numbers with precisions greater than 31. To use larger
values, declare variables to be BIT variables of the appropriate size and use the POSINT and
SUBSTR bits as necessary to access the values, or declare the item as a structure. The RTL routines
LIB$ADDX and LIB$SUBX may be useful if you need to perform arithmetic on these types.
6 Routinesdeclared in PLI$STARLET often use ANY, so you are free to declare the data structure
in the most convenient way for the application. ANY may be necessary in some cases because PL/I
does not allow parameter declarations for some data types used by OpenVMS. (In particular, PL/I
parameters with arrays passed by reference cannot be declared to have nonconstant bounds.)
8 Forparameter declarations, the bounds must be constant for arrays passed by reference. For arrays
passed by descriptor, *s should be used for the array extent instead. (OpenVMS system routines
almost always take arrays by reference.)

Note
All system services and many system constants and data structures are
declared in PLI$STARLET.TLB.
While the current version of PL/I does not support unsigned fixed binary
numbers or fixed binary numbers with a precision greater than 31, future
versions may support these features. If PL/I is extended to support these
types, declarations in PLISTARLET may change to use the new data
types where appropriate.

OpenVMS Data Types B–47


OpenVMS Data Types
B.11 VAX MACRO Implementations

B.11 VAX MACRO Implementations


Table B–11 lists the OpenVMS data types and their corresponding VAX MACRO
data type declarations.

Table B–11 VAX MACRO Implementations


OpenVMS Data Type VAX MACRO Declarations
access_bit_names .ASCID /name_for_bit0/
.ASCID /name_for_bit1/ . . .
.ASCID /name_for_bit31/
access_mode .BYTE PSL$C_xxxx
address .ADDRESSS virtual_address
address_range .ADDRESS start_address,end_address
arg_list .LONG n_args, arg1, arg2, . . .
ast_procedure .ADDRESS ast_procedure
boolean .LONG 1 or .LONG 0
byte_signed .SIGNED_BYTE byte_value
byte_unsigned .BYTE byte_value
channel .WORD channel_number
char_string .ASCID /string/
complex_number na
cond_value .LONG cond_value
context .LONG 0
date_time .QUAD date_time
device_name .ASCID /ddcu:/
ef_cluster_name .ASCID /ef_cluster_name/
ef_number .LONG ef_number
exit_handler_block .LONG 0
.ADDRESS exit_handler_routine
.LONG 1
.ADDRESS status
STATUS: .BLKL 1
fab MYFAB: $FAB
file_protection .WORD prot_value
floating_point .FLOAT, .G_FLOAT, or .H_FLOAT
function_code .LONG code_mask
identifier .ADDRESSS virtual_address
1
invo_context_blk $LIBICBDEF
1
invo_handle .LONG
io_status_block .QUAD 0
item_list_2 .WORD component_length
.WORD item_code
.ADDRESS component_address

1 Alpha specific.

(continued on next page)

B–48 OpenVMS Data Types


OpenVMS Data Types
B.11 VAX MACRO Implementations

Table B–11 (Cont.) VAX MACRO Implementations


OpenVMS Data Type VAX MACRO Declarations
item_list_3 .WORD buffer_length
.WORD item_code
.ADDRESS buffer_address
.ADDRESS return_length_address
item_list_pair .LONG item_code
.LONG data
item_quota_list .BYTE PQL$_xxxx
.LONG value_for_quota
.BYTE pql$_listend
lock_id .LONG lock_id
lock_status_block .QUAD 0
lock_value_block .BLKB 16
logical_name .ASCID /logical_name/
longword_signed .LONG value
longword_unsigned .LONG value
mask_byte .BYTE mask_byte
mask_longword .LONG mask_longword
mask_quadword .QUAD mask_quadword
mask_word .WORD mask_word
mechanism_args MECH_ARGS: $CHFDEF
null_arg .LONG 0
octaword_signed na
octaword_unsigned .OCTA value
page_protection .LONG page_protection
procedure .ADDRESS procedure
process_id .LONG process_id
process_name .ASCID /process_name/
quadword_signed na
quadword_unsigned .QUAD value
rights_holder .LONG identifier, access_rights_bitmask
rights_id .LONG rights_id
rab MYRAB: $RAB
section_id .LONG sec$k_matxxx, version_number
section_name .ASCID /section_name/
system_access_id .QUAD system_access_id
time_name .ASCID /dd-mmm-yyyy:hh:mm:ss.cc/
transaction_id .OCTA value
uic .LONG uic
user_arg .LONG data
varying_arg Depends on the application.

(continued on next page)

OpenVMS Data Types B–49


OpenVMS Data Types
B.11 VAX MACRO Implementations

Table B–11 (Cont.) VAX MACRO Implementations


OpenVMS Data Type VAX MACRO Declarations

vector_byte_signed .SIGNED_BYTE val1,val2, . . . valn


vector_byte_unsigned .BYTE val1,val2, . . . valn
vector_longword_signed .LONG val1,val2, . . . valn
vector_longword_unsigned .LONG val1,val2, . . . valn
vector_quadword_signed na
vector_quadword_unsigned .QUAD val1, val2, . . . valn
vector_word_signed .SIGNED_WORD val1,val2, . . . valn
vector_word_unsigned .WORD val1,val2, . . . valn
word_signed .SIGNED_WORD value
word_unsigned .WORD value

B.12 RPG II Implementations


Table B–12 lists the OpenVMS data types and their corresponding RPG II data
type declarations.

Table B–12 RPG II Implementations


OpenVMS Data Type RPG II Declarations
access_bit_names na
access_mode Declare as text string of 1 byte. When using this data
structure, you must interpret the ASCII contents of
the string to determine access_mode.
address L1
address_range Q1
arg_list na
ast_procedure L1
boolean na
byte_signed Declare as text string of 1 byte. When using this data
structure, you must interpret the ASCII contents of
the string.
byte_unsigned Same as for byte_signed.1
channel W1
char_string TEXT STRING
complex_number DATA STRUCTURE
cond_value cond_value GIVNG OPCODE
context L1
date_time Q1
device_name TEXT STRING

1 Technically,
RPG II does not support unsigned data structures. However, unsigned information may
be passed using the signed equivalent, provided the contents do not exceed the range of the signed
data structure.

(continued on next page)

B–50 OpenVMS Data Types


OpenVMS Data Types
B.12 RPG II Implementations

Table B–12 (Cont.) RPG II Implementations


OpenVMS Data Type RPG II Declarations
ef_cluster_name TEXT STRING
ef_number L1
exit_handler_block DATA STRUCTURE
fab Implicitly generated by the compiler on your behalf.
You cannot access the fab data structure from an RPG
II program.
file_protection W1
floating_point F
D
function_code F
identifier L1
io_status_block Q
item_list_pair DATA STRUCTURE
item_list_2 DATA STRUCTURE
item_list_3 DATA STRUCTURE
item_quota_list na
lock_id L1
lock_status_block DATA STRUCTURE
lock_value_block DATA STRUCTURE
logical_name TEXT STRING
longword_signed L
longword_unsigned L1
mask_byte Same as for byte_signed1
mask_longword L1
mask_quadword Q1
mask_word W1
null_arg na
octaword_signed DATA STRUCTURE
octaword_unsigned DATA STRUCTURE
page_protection L1
procedure L1
process_id L1
process_name TEXT STRING
quadword_signed Q
quadword_unsigned Q1
rights_holder Q1
rights_id L1

1 Technically,
RPG II does not support unsigned data structures. However, unsigned information may
be passed using the signed equivalent, provided the contents do not exceed the range of the signed
data structure.

(continued on next page)

OpenVMS Data Types B–51


OpenVMS Data Types
B.12 RPG II Implementations

Table B–12 (Cont.) RPG II Implementations


OpenVMS Data Type RPG II Declarations
rab Implicitly generated by the compiler on your behalf.
You cannot access the rab data structure from an RPG
II program.
section_id Q1
section_name TEXT STRING
system_access_id Q1
time_name TEXT STRING
transaction_id DATA STRUCTURE
uic L1
user_arg L1
varying_arg Depends on the application.
vector_byte_signed ARRAY OF TEXT STRING
vector_byte_unsigned ARRAY OF TEXT STRING1
vector_longword_signed ARRAY OF LONGWORD INTEGER (SIGNED) L
vector_longword_unsigned RAY OF LONGWORD INTEGER L1
vector_quadword_signed na
vector_quadword_unsigned na
vector_word_signed ARRAY OF WORD INTEGER (SIGNED) W
vector_word_unsigned ARRAY OF WORD INTEGER W1
word_signed W
word_unsigned W1
1 Technically,
RPG II does not support unsigned data structures. However, unsigned information may
be passed using the signed equivalent, provided the contents do not exceed the range of the signed
data structure.

B.13 SCAN Implementations


Table B–13 lists the OpenVMS data types and their corresponding SCAN data
type declarations.

Table B–13 SCAN Implementations


OpenVMS Data Type SCAN Declarations
access_bit_name FILL(8*32)1
access_mode FILL(1)1
address POINTER

1 FILLis a data type that can always be used. A FILL is an object between 0 and 65K bytes in length.
SCAN does not interpret the contents of an object. Thus, it can be used to pass or return the object to
another language that does understand the type.

(continued on next page)

B–52 OpenVMS Data Types


OpenVMS Data Types
B.13 SCAN Implementations

Table B–13 (Cont.) SCAN Implementations


OpenVMS Data Type SCAN Declarations
address_range RECORD
start: POINTER,
end: POINTER,
END RECORD
arg_list RECORD
count: INTEGER,
arg1: POINTER, ! if by reference
arg2: INTEGER, ! if by value
. . . ! depending on needs
END RECORD
ast_procedure POINTER
boolean BOOLEAN2
byte_signed FILL(1)1
byte_unsigned FILL(1)1
channel FILL(2)1
char_string FIXED STRING(x), where x is the length.
complex_number FILL(x), where x is the length.1
cond_value INTEGER
context INTEGER
date_time FILL(8)1
device_name FIXED STRING(x), where x is the length.
ef_cluster_name FIXED STRING(x), where x is the length.
ef_number INTEGER
exit_handler_block FILL(x), where x is the length.1
fab A FAB data type is too large a structure to include
in this table (see the OpenVMS Record Management
Services Reference Manual); most of the fields can be
described with a SCAN record. However, fab data
structures are simpler to use with less coding errors
when accessed from other languages that have the
record predefined.
file_protection FILL(2)1
floating_point FILL(x), where x is the length.1
function_code INTEGER
identifier POINTER
io_status_block FILL(8)1

1 FILLis a data type that can always be used. A FILL is an object between 0 and 65K bytes in length.
SCAN does not interpret the contents of an object. Thus, it can be used to pass or return the object to
another language that does understand the type.
2 SCAN Boolean is just 1 byte.

(continued on next page)

OpenVMS Data Types B–53


OpenVMS Data Types
B.13 SCAN Implementations

Table B–13 (Cont.) SCAN Implementations


OpenVMS Data Type SCAN Declarations
item_list_2 RECORD
item1: FILL(8),
item2: FILL(8),
...
terminator: INTEGER,
END RECORD1
item_list_3 RECORD
item1: FILL(12),
item2: FILL(12),
...
terminator: INTEGER,
END RECORD1
item_list_pair RECORD
pair_1: RECORD ! 2 integer pair
long1: INTEGER,
long2: INTEGER,
END RECORD,
pair_2: RECORD ! integer-real pair
long1: INTEGER,
long2: FILL(4),
END RECORD,
. . . ! depending on need
terminator: INTEGER,
END RECORD
item_quota_list RECORD
item1: RECORD
type: FILL(1),
value: INTEGER,
END RECORD
item2: RECORD
type: FILL(1),
value: INTEGER,
END RECORD,
...
terminator: FILL(1),
END RECORD1
lock_id INTEGER

1 FILLis a data type that can always be used. A FILL is an object between 0 and 65K bytes in length.
SCAN does not interpret the contents of an object. Thus, it can be used to pass or return the object to
another language that does understand the type.

(continued on next page)

B–54 OpenVMS Data Types


OpenVMS Data Types
B.13 SCAN Implementations

Table B–13 (Cont.) SCAN Implementations


OpenVMS Data Type SCAN Declarations
lock_status_block RECORD
status: FILL(2),
reserved: FILL(2),
ock_id: INTEGER,
END RECORD1
lock_value_block FILL(16)1
logical_name FIXED STRING(x), where x is the length.
longword_signed INTEGER
longword_unsigned INTEGER
mask_byte FILL(1)1
mask_longword INTEGER
mask_quadword RECORD
first_half: INTEGER,
second_half: INTEGER,
END RECORD
mask_word FILL(2)1
null_arg Use asterisk (*) for argument.
octaword_signed FILL(16)1
octaword_unsigned FILL(16)1
page_protection INTEGER
procedure POINTER
process_id INTEGER
process_name FIXED STRING(x), where x is the length.
quadword_signed FILL(8)1
quadword_unsigned FILL(8)1
rights_holder RECORD
rights_id: INTEGER,
bitmask: INTEGER,
END RECORD
rights_id INTEGER
rab A rab data type is too large a structure to include
in this table (see the OpenVMS Record Management
Services Reference Manual); most of the fields can be
described with a SCAN record. However, RAB data
structures are simpler to use with less coding errors
when accessed from other languages that have the
record predefined.
second_name FILL(8)1
section_name FIXED STRING(x), where x is the length.

1 FILLis a data type that can always be used. A FILL is an object between 0 and 65K bytes in length.
SCAN does not interpret the contents of an object. Thus, it can be used to pass or return the object to
another language that does understand the type.

(continued on next page)

OpenVMS Data Types B–55


OpenVMS Data Types
B.13 SCAN Implementations

Table B–13 (Cont.) SCAN Implementations


OpenVMS Data Type SCAN Declarations
system_access_id FILL(8)1
time_name FIXED STRING(x), where x is the length.
transaction_id FILL(16)1
uic INTEGER
user_arg INTEGER
varying_arg INTEGER
vector_byte_signed FILL(x), where x is the length.1
vector_byte_unsigned FILL(x), where x is the length.1
vector_longword_signed FILL(4*x), where x is the length.1
vector_longword_unsigned FILL(4*x), where x is the length.1
vector_quadword_signed FILL(8*x), where x is the length.1
vector_quadword_unsigned FILL(8*x), where x is the length.1
vector_word_signed FILL(2*x), where x is the length.1
vector_word_unsigned FILL(2*x), where x is the length.1
word_signed FILL(2)1
word_unsigned FILL(2)1
1 FILLis a data type that can always be used. A FILL is an object between 0 and 65K bytes in length.
SCAN does not interpret the contents of an object. Thus, it can be used to pass or return the object to
another language that does understand the type.

B–56 OpenVMS Data Types


C
Distributed Name Service (VAX Only)

This chapter describes the Digital Distributed Name Service (DECdns) Clerk by
introducing the functions of the DECdns (SYS$DNS) system service and various
run-time library routines. It is divided into the following sections:
Section C.1 describes how to use the portable application programming interface
and the operating system’s system service and run-time library interface.
Section C.2 describes how to use the SYS$DNS system service.
Section C.3 describes how to use the DCL command DEFINE.

C.1 DECdns Clerk System Service


The DECdns Clerk (SYS$DNS) system service provides applications with a
means of assigning networkwide names to system resources. Applications can
use DECdns to name such resources as printers, files, disks, nodes, servers, and
application databases. Once an application has named a resource using DECdns,
the name is available for all users of the application.
The SYS$DNS system service supports two programming interfaces:
• Portable application programming interface
• System service and run-time library (RTL)
Portable Application Interface
Application designers should select an interface for their application based on
programming language, application base, and the specific requirements of their
application.
The portable interface provides support for applications written in the C
programming language, and it provides a high-level interface with easy-to-use
methods of creating and maintaining DECdns names. Use the portable interface
for applications that must be portable between VAX systems and the Compaq
Tru64 UNIX operating system.
The portable interface is documented in the Guide to Programming with DECdns.
VAX System Services and RTL Routines
The VAX system services and run-time library routines can be used by
applications written in the high-level and midlevel languages listed in the preface
of this document. However, applications that use these interfaces are limited to
the VAX system environment. Use the system service when an application meets
any of the following requirements:
• The application needs the full capabilities, flexibility, and functions of
asynchronous support.
• The application will run as part of a privileged shareable image on the
operating system.

Distributed Name Service (VAX Only) C–1


Distributed Name Service (VAX Only)
C.1 DECdns Clerk System Service

• The application is not written in the C programming language.


The SYS$DNS system service is documented in the OpenVMS System Services
Reference Manual. Before using this system service, familiarize yourself with
the basic operating principles, terms, and definitions used by DECdns. You can
gain a working knowledge of DECdns by reading about the following topics in the
Guide to Programming with DECdns:
• DECdns component operation
• Namespace directories, objects, soft links, groups, and clearinghouses
• DECdns name syntax
• Attributes
• Clerk caching
• Setting confidence and timeouts
• Recommendations for DECdns application programmers
By understanding these topics, you can proceed more easily with this chapter,
which provides an introduction to the DECdns system service and run-time
library routines and discusses the following topics:
• Functions provided by the service and routines
• How to use the SYS$DNS system service

C.1.1 Using the DECdns System Service and Run-Time Library Routines
You can use the SYS$DNS system service and run-time library routines together
to assign, maintain, and retrieve DECdns names. This section describes the
capabilities of each interface.
C.1.1.1 Using the SYS$DNS System Service
DECdns provides a single system service call (SYS$DNS) to create, delete, modify,
and retrieve DECdns names from a namespace. The SYS$DNS system service
completes asynchronously; that is, it returns to the client immediately after
making a name service call. The status returned to the client indicates whether a
request was queued successfully to the name service.
The SYS$DNSW system service is the synchronous equivalent of SYS$DNS. The
SYS$DNSW call is identical to SYS$DNS in every way except that SYS$DNSW
returns to the caller after the operation completes.
The SYS$DNS call has two main parameters:
• A function code that identifies the particular service to perform
• An item list that specifies all the parameters for the required function
The system service provides the following functions:
• Create and delete DECdns names in the namespace
• Enumerate DECdns names in a particular directory
• Add, read, remove, and test attributes and attribute values
• Add, create, remove, restore, and update directories
• Create, remove, and resolve soft links
• Create and remove groups

C–2 Distributed Name Service (VAX Only)


Distributed Name Service (VAX Only)
C.1 DECdns Clerk System Service

• Add, remove, and test members in a group


• Parse names to convert string format names to DECdns opaque format names
and back to string
You specify item codes as either input or output parameters in the item list.
Input parameters modify functions, set context, or describe the information to be
returned. Output parameters return the requested information.
You can specify the following in input item codes:
• An attribute name and type
• The class of a DECdns name and, optionally, a class filter
• The class version of a DECdns name
• A confidence setting to indicate whether the request should be serviced from
the clerk’s cache or from a server
• An indication that the application will repeat a read call, which forces caching
of recently read data
• A name or timestamp that sets the context from which to begin or restart
enumerating or reading
• The name and type of an object, directory, group, member, clearinghouse, or
soft link, and the ability to suppress the namespace nickname from the full
name
• A simple or full name in opaque or string format
• A request to search subgroups for a member
• An operation, either adding or deleting an attribute
• A value for an attribute
• A pointer to the address of the next character in a full or simple name
• A timeout period to wait for a call to complete
• An expiration time and extension time for soft links
The output item codes return the following information:
• A creation timestamp for an object
• A set of child directories, soft links, attribute names, attribute values, or
object names
• An opaque simple or full name
• A string name and length
• A resolved soft link
• A name or timestamp context variable that indicates the last directory, object,
soft link, or attribute that was enumerated or read

Distributed Name Service (VAX Only) C–3


Distributed Name Service (VAX Only)
C.1 DECdns Clerk System Service

C.1.1.2 Using the Run-Time Library Routines


You can use the DECdns run-time library routines to manipulate output from the
SYS$DNS system service. The routines provide the following functions:
• Remove a value from a set returned by an enumeration or read system service
function
• Compare, append, concatenate, and count opaque names that were created
with the system service
• Convert addresses
To read a single attribute value using the system service and run-time library
routines, use the following routines:
• DNS$_ENUMERATE_OBJECTS function code to enumerate objects
• DNS$REMOVE_FIRST_SET_VALUE run-time library routine to remove the
first set value
• DNS$_READ_ATTRIBUTE function code to read the first set value
You can also use the system service and run-time library routines together to add
an opaque simple name to a full name by performing the following steps:
1. Obtain a string full name from a user.
2. Use the system service DNS$_PARSE_FULLNAME_STRING function code to
convert the string name to opaque format.
3. Use the DNS$_APPEND_SIMPLE_TO_RIGHT run-time library routine to
add an opaque simple name to the end of the full name.

C.2 Using the SYS$DNS System Service Call


The following sections describe how to create and modify an object, and then how
to read attributes and enumerate names and attributes in the namespace.
Each section contains a code example. These code examples are all contained
in the sample program that resides on your distribution medium under the file
name SYS$EXAMPLES:SYS$DNS_SAMPLE.C.

C.2.1 Creating Objects


Applications that use DECdns can create an object in the namespace for
each resource used by the application. You can create objects using either
the SYS$DNS or the SYS$DNSW system service.
A DECdns object consists of a name and its associated attributes. When you
create the object, you must assign a class and a class version. You can modify
the object to hold additional attributes, such as class-specific attributes, on an
as-needed basis.
Note that applications can use objects that are created by other applications.
To create an object in the namespace with SYS$DNS:
1. Prompt the user for a name.
The name that an application assigns to an object should come from a
user, a configuration file, a system logical name, or some other source. The
application never assigns an object’s name because the namespace structure
is uncertain. The name the application receives from the user is in string
format.

C–4 Distributed Name Service (VAX Only)


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

2. Use the SYS$DNS parse function to convert the full name string into an
opaque format. Specify the DNS$_NEXTCHAR_PTR item code to obtain the
length of the opaque name.
3. Optionally, reserve an event flag so you can check for completion of the
service.
4. Build an item list that contains the following elements:
• The opaque name for the object (resulting from the translation in step 2)
• The class name given by the application, which should contain the facility
code
• The class version assigned by the application
• An optional timeout value that specifies when the call expires
5. Optionally, provide the address of the DECdns status block to receive status
information from the name service.
6. Optionally, provide the address of the asynchronous system trap (AST) service
routine. AST routines allow a program to continue execution while waiting
for parts of the program to complete.
7. Optionally, supply a parameter to pass to the AST routine.
8. Call the create object function and provide all the parameters supplied in
steps 1 through 7.
If a clerk call is not complete when timeout occurs, then the call completes with
an error. The error is returned in the DECdns status block.
An application should check for errors that are returned; it is not enough to check
the return of the SYS$DNS call itself. You need to check the DECdns status
block to be sure no errors are returned by the DECdns server.
The following routine, written in C, shows how to create an object in the
namespace with the synchronous service SYS$DNSW. The routine demonstrates
how to construct an item list.
#include <dnsdef.h>
#include <dnsmsg.h>
/*
* Parameters:
* class_name = address of the opaque simple name of the class
* to assign to the object
* class_len = length (in bytes) of the class opaque simple name
* object_name= address of opaque full name of the object
* to create in the namespace.
* object_len = length (in bytes) of the opaque full name of the
* object to create
*/
create_object(class_name, class_len, object_name, object_len)
unsigned char *class_name; /*Format is a DECdns opaque simple name*\
unsigned short class_len;
unsigned char *object_name; /*Format is a DECdns opaque simple name*\
unsigned short object_len;
{
struct $dnsitmdef createitem[4]; /* Item list used by system service */
struct $dnscversdef version; /* Version assigned to the object */
struct $dnsb iosb; /* Used to determine DECdns server status */
int status; /* Status return from system service */

Distributed Name Service (VAX Only) C–5


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

/*
* Construct the item list that creates the object:
*/
createitem[0].dns$w_itm_size = class_len; !
createitem[0].dns$w_itm_code = dns$_class;
createitem[0].dns$a_itm_address = class_name;
createitem[1].dns$w_itm_size = object_len; "
createitem[1].dns$w_itm_code = dns$_objectname;
createitem[1].dns$a_itm_address = object_name;
version.dns$b_c_major = 1; #
version.dns$b_c_minor = 0;
createitem[2].dns$w_itm_size = sizeof(struct $dnscversdef); $
createitem[2].dns$w_itm_code = dns$_version;
createitem[2].dns$a_itm_address = &version;
*((int *)&createitem[3]) = 0; %
status = sys$dnsw(0, dns$_create_object, &createitem, &iosb, 0, 0); &
if(status == SS$_NORMAL)
{
status = iosb.dns$l_dnsb_status; ’
}
return(status);
}
! The first entry in the item list is the address of the opaque simple name that
represents the class of the object.
" The second entry is the address of the opaque full name for the object.
# The next step is to build a version structure that indicates the version of the
object. In this case, the object is version 1.0.
$ The third entry is the address of the version structure that was just built.
% A value of 0 terminates the item list.
& The next step is to call the system service to create the object.
’ Check to see that both the system service and DECdns were able to perform
the operation without error.

C.2.2 Modifying Objects and Their Attributes


After you create objects that identify resources, you can add or modify attributes
that describe properties of the object. There is no limit imposed on the number of
attributes an object can have.
You modify an object whenever you need to add an attribute or attribute value,
change an attribute value, or delete an attribute or attribute value. When you
modify an attribute, DECdns updates the timestamp contained in the DNS$UTS
attribute for that attribute.
To modify an attribute or attribute value, use the DNS$_MODIFY_ATTRIBUTE
function code. Specify the attribute name in the input item code along with the
following required input item codes:
• DNS$_ATTRIBUTETYPE to specify a set-valued (DNS$K_SET) or single-
valued (DNS$K_SINGLE) attribute
• DNS$_MODOPERATION to specify that the value is being added (DNS$K_
PRESENT) or deleted (DNS$K_ABSENT)

C–6 Distributed Name Service (VAX Only)


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

Use the DNS$_MODVALUE item code to specify the value of the attribute. Note
that the DNS$_MODVALUE item code must be specified to add a single-valued
attribute. You can specify a null value for a set-valued attribute. DECdns
modifies attribute values in the following way:
• If the attribute exists and you specify an attribute value, the attribute value
is removed from a set-valued attribute. All other values are unaffected. For a
single-valued attribute, DECdns removes the attribute and its value from the
name.
• If you do not specify an attribute value, DECdns removes the attribute and
all values of the attribute for both set-valued and single-valued attributes.
To delete an attribute, use the DNS$_MODOPERATION item code.
The following is an example of how to use the DNS$_MODIFY_ATTRIBUTE
function code to add a new member to a group object. To do this, you add the new
member to the DNS$Members attribute of the group object. Use the following
function codes:
• Specify the group object (DNS$_ENTRY) and type (DNS$_LOOKINGFOR).
The type should be specified as object (DNS$K_OBJECT).
• Use DNS$_MODOPERATION to add a member to the DNS$Members
attribute (DNS$_ATTRIBUTENAME), which is a set-valued attribute (DNS$_
ATTRIBUTETYPE).
• Specify the new member object name in DNS$_MODVALUE.
• Use another DNS$_MODIFY_ATTRIBUTE call to assign access rights for the
new member to the DNS$ACS attribute of the member object.
Perform the following steps to modify an object with SYS$DNSW:
1. Build an item list that contains the following elements:
• Opaque name of the object you are modifying
• Type of object
• Operation to perform
• Type of attribute you are modifying
• Attribute name
• Value being added to the attribute
2. Supply any of the optional parameters described in Section C.2.1.
3. Call the modify attribute function, supplying the parameters established in
steps 1 and 2.

Distributed Name Service (VAX Only) C–7


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

The following example, written in C, shows how to add a set-valued attribute and
a value to an object:
#include <dnsdef.h>
#include <dnsmsg.h>
/*
* Parameters:
* obj_name = address of opaque full name of object
* obj_len = length of opaque full name of object
* att_name = address of opaque simple name of attribute to create
* att_len = length of opaque simple name of attribute
* att_value= value to associate with the attribute
* val_len = length of added value (in bytes)
*/
add_attribute(obj_name, obj_len, att_name, att_len, att_value, val_len)
unsigned char *obj_name;
unsigned short obj_len;
unsigned char *att_name;
unsigned short att_len;
unsigned char *att_value;
unsigned short val_len;
main() {
struct $dnsitmdef moditem[7]; /* Item list for $DNSW */
unsigned char objtype = dns$k_object; /* Using objects */
unsigned char opertype = dns$k_present; /* Adding an object */
unsigned char attype = dns$k_set; /* Attribute will be type set */
struct $dnsb iosb; /* Used to determine DECdns status */
int status; /* Status of system service */
/*
* Construct the item list to add an attribute to an object.
*/
moditem[0].dns$w_itm_size = obj_len;
moditem[0].dns$w_itm_code = dns$_entry;
moditem[0].dns$a_itm_address = obj_name; !
moditem[1].dns$w_itm_size = sizeof(char);
moditem[1].dns$w_itm_code = dns$_lookingfor;
moditem[1].dns$a_itm_address = &objtype; "
moditem[2].dns$w_itm_size = sizeof(char);
moditem[2].dns$w_itm_code = dns$_modoperation;
moditem[2].dns$a_itm_address = &opertype; #
moditem[3].dns$w_itm_size = sizeof(char);
moditem[3].dns$w_itm_code = dns$_attributetype;
moditem[3].dns$a_itm_address = &attype; $
moditem[4].dns$w_itm_size = att_len;
moditem[4].dns$w_itm_code = dns$_attributename;
moditem[4].dns$a_itm_address = att_name; %
moditem[5].dns$w_itm_size = val_len;
moditem[5].dns$w_itm_code = dns$_modvalue;
moditem[5].dns$a_itm_address = att_value; &
*((int *)&moditem[6]) = 0; ’
/*
* Call $DNSW to add the attribute to the object.
*/
status = sys$dnsw(0, dns$_modify_attribute, &moditem, &iosb, 0, 0);(

C–8 Distributed Name Service (VAX Only)


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

if(status == SS$_NORMAL)
{
status = iosb.dns$l_dnsb_status; )
}
return(status);
}
! The first entry in the item list is the address of the opaque full name of the
object.
" The second entry shows that this is an object, not a soft link or child directory
pointer.
# The third entry is the operation to perform. The program adds an attribute
with its value to the object.
$ The fourth entry is the attribute type. The attribute has a set of values
rather than a single value.
% The fifth entry is the opaque simple name of the attribute being added.
& The sixth entry is the value associated with the attribute.
’ A value of 0 terminates the item list.
( A call is made to the SYS$DNSW system service to perform the operation.
) A check is made to see that both the system service and DECdns performed
the operation without error.

C.2.3 Requesting Information from DECdns


Once an application adds its objects to the namespace and modifies the names to
contain all necessary attributes, the application is ready to use the namespace.
An application can request that the DECdns Clerk either read attribute
information stored with an object or list all the application’s objects that are
stored in a particular directory. An application might also need to resolve all soft
links in a name in order to identify a target.
To request information from DECdns, use the read or enumerate function codes,
as follows:
• The DNS$_READ_ATTRIBUTE function reads and returns a set whose
members are the values of the specified attribute.
• The DNS$_ENUMERATE functions return a list of names for attributes,
child directories, objects, and soft links.
C.2.3.1 Using the Distributed File Service (DFS)
The VAX Distributed File Service (DFS) uses DECdns for resource naming.
This section gives an example of the DNS$_READ_ATTRIBUTE call as used by
DFS. The DFS application uses DECdns to give the operating system’s users
the ability to use remote operating system disks as if the disks were attached
to their local VAX system. The DFS application creates DECdns names for the
operating system’s directory structures (a directory and all of its subdirectories).
Each DFS object in the namespace references a particular file access point. DFS
creates each object with a class attribute of DFS$ACCESSPOINT and modifies
the address attribute (DNS$Address) of each object to hold the DECnet node
address where the directory structures reside. As a final step in registering its
resources, DFS creates a database that maps DECdns names to the appropriate
operating system directory structures.

Distributed Name Service (VAX Only) C–9


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

Whenever the DFS application receives the following mount request, DFS sends a
request for information to the DECdns Clerk:
MOUNT ACCESS_POINT dns-name vms-logical-name
To read the address attribute of the access point object, the DFS application
performs the following steps:
1. Translates the DECdns name that is supplied through the user to opaque
format using the SYS$DNS parse function
2. Reads the class attribute of the object with the $DNS read attribute function,
indicating that there is a second call to read other attributes of the object
3. Makes a second call to the SYS$DNS read attribute function to read the
address attribute of the object
4. Sends the DECdns name to the DFS server, which looks up the disk on which
the access point is located
5. Verifies that the DECdns name is valid on the DFS server
The DFS client and DFS server now can communicate to complete the mount
function.
C.2.3.2 Reading Attributes from DNS
When requesting information from DNS, an application always takes an object
name from the user, translates the name into opaque format, and passes it in an
item list to the DECdns Clerk.
Each read request returns a set of attribute values. The DNS$_READ_
ATTRIBUTE service uses a context item code called DNS$_CONTEXTVARTIME
to maintain context when reading the attribute values. The context item code
saves the last member that is read from the set. When the next read call is
issued, the item code sets the context to the next member in the set, reads it, and
returns it. The context item code treats single-valued attributes as though they
were a set of one.
If an enumeration call returns DNS$_MOREDATA, not all matching names or
attributes have been enumerated. If you receive this message, you should make
further calls, setting DNS$_CONTEXTVARTIME to the last value returned until
the procedure returns SS$_NORMAL.
The following program, written in C, shows how an application reads an object
attribute. The SYS$DNSW service uses an item list to return a set of objects.
Then the application calls a run-time library routine to read each value in the
set.
#include <dnsdef.h>
#include <dnsmsg.h>
/*
* Parameters:
* opaque_objname = address of opaque full name for the object
* containing the attribute to be read
* obj_len = length of opaque full name of the object
* opaque_attname = address of the opaque simple name of the
* attribute to be read
* attname_len = length of opaque simple name of attribute
*/

C–10 Distributed Name Service (VAX Only)


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

read_attribute(opaque_objname, obj_len, opaque_attname, attname_len)


unsigned char *opaque_objname;
unsigned short obj_len;
unsigned char *opaque_attname;
unsigned short attname_len;
{
struct $dnsb iosb; /* Used to determine DECdns status */
char objtype = dns$k_object; /* Using objects */
struct $dnsitmdef readitem[6]; /* Item list for system service */
struct dsc$descriptor set_dsc, value_dsc, newset_dsc, cts_dsc;
unsigned char attvalbuf[dns$k_maxattribute]; /* To hold the attribute */
/* values returned from extraction routine. */
unsigned char attsetbuf[dns$k_maxattribute]; /* To hold the set of */
/* attribute values after the return from $DNSW. */
unsigned char ctsbuf[dns$k_cts_length]; /* Needed for context of multiple reads */
int read_status; /* Status of read attribute routine */
int set_status; /* Status of remove value routine */
int xx; /* General variable used by print routine */
unsigned short setlen; /* Contains current length of set structure */
unsigned short val_len; /* Contains length of value extracted from set */
unsigned short cts_len; /* Contains length of CTS extracted from set */
/* Construct an item list to read values of the attribute. */ !
readitem[0].dns$w_itm_code = dns$_entry;
readitem[0].dns$w_itm_size = obj_len;
readitem[0].dns$a_itm_address = opaque_objname;
readitem[1].dns$w_itm_code = dns$_lookingfor;
readitem[1].dns$w_itm_size = sizeof(char);
readitem[1].dns$a_itm_address = &objtype;
readitem[2].dns$w_itm_code = dns$_attributename;
readitem[2].dns$a_itm_address = opaque_attname;
readitem[2].dns$w_itm_size = attname_len;
readitem[3].dns$w_itm_code = dns$_outvalset;
readitem[3].dns$a_itm_ret_length = &setlen;
readitem[3].dns$w_itm_size = dns$k_maxattribute;
readitem[3].dns$a_itm_address = attsetbuf;
*((int *)&readitem[4]) = 0;
do "
{
read_status = sys$dnsw(0, dns$_read_attribute, &readitem, &iosb, 0, 0);
if(read_status == SS$_NORMAL)
{
read_status = iosb.dns$l_dnsb_status;
}
if((read_status == SS$_NORMAL) || (read_status == DNS$_MOREDATA))
{
do
{
set_dsc.dsc$w_length = setlen;
set_dsc.dsc$a_pointer = attsetbuf; /* Address of set */
value_dsc.dsc$w_length = dns$k_simplenamemax;
value_dsc.dsc$a_pointer = attvalbuf; /* Buffer to hold */
/* attribute value */
cts_dsc.dsc$w_length = dns$k_cts_length;
cts_dsc.dsc$a_pointer = ctsbuf; /* Buffer to hold value’s CTS*/

Distributed Name Service (VAX Only) C–11


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

newset_dsc.dsc$w_length = dns$k_maxattribute;
newset_dsc.dsc$a_pointer = attsetbuf; /* Same buffer for */
/* each call */
set_status = dns$remove_first_set_value(&set_dsc, &value_dsc,
# &val_len, &cts_dsc,
&cts_len, &newset_dsc,
&setlen);
if(set_status == SS$_NORMAL)
{ $
readitem[4].dns$w_itm_code = dns$_contextvartime;
readitem[4].dns$w_itm_size = cts_len;
readitem[4].dns$a_itm_address = ctsbuf;
*((int *)&readitem[5]) = 0;
printf("\tValue: "); %
for(xx = 0; xx < val_len; xx++)
printf("%x ", attvalbuf[xx]);
printf("\n");
}
else if (set_status != 0)
{
printf("Error %d returned when removing value from set\n",
set_status);
exit(set_status);
}
} while(set_status == SS$_NORMAL);
}
else
{
printf("Error reading attribute = %d\n", read_status);
exit(read_status);
}
} while(read_status == DNS$_MOREDATA);
}
! The item list contains five entries:
• Opaque full name of the object with the attribute the program wants to
read
• Type of object to access
• Opaque simple name of the attribute to read
• Address of the buffer containing the set of values returned by the read
operation
• A value of 0 to terminate the item list
" The loop repeatedly calls the SYS$DNSW service to read the values of the
attribute because the first call might not return all the values. The loop
executes until $DNSW returns something other than DNS$_MOREDATA.
# The DNS$REMOVE_FIRST_SET_VALUE routine extracts a value from the
set.
$ This attribute name may be the context the routine uses to read additional
attributes. The attribute’s creation timestamp (CTS), not its value, provides
the context.
% Finally, display the value in hexadecimal format. (You could also take the
attribute name and convert it to a printable format before displaying the
result.)

C–12 Distributed Name Service (VAX Only)


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

See the discussion about setting confidence in the Guide to Programming with
DECdns for information about obtaining up-to-date data on read requests.
C.2.3.3 Enumerating DECdns Names and Attributes
The enumerate functions return DECdns names for objects, child directories, soft
links, groups, or attributes in a specific directory. Use either the asterisk (*) or
question mark (?) wildcard to screen enumerated items. DECdns matches any
single character against the specified wildcard.
Enumeration calls return a set of simple names or attributes. If an enumeration
call returns DNS$_MOREDATA, not all matching names or attributes have been
enumerated. If you receive this message, use the context-setting conventions
that are described for the DNS$_READ_ATTRIBUTE call. You should make
further calls, setting DNS$_CONTEXTVARNAME to the last value returned until
the procedure returns SS$_NORMAL. For more information, see the SYS$DNS
system service in the OpenVMS System Services Reference Manual: A–GETUAI.
The following program, written in C, shows how an application can read the
objects in a directory with the SYS$DNS system service. The values that
DECdns returns from read and enumerate functions are in different structures.
For example, an enumeration of objects returns different structures than an
enumeration of child directories. To clarify how to use this data, the sample
program demonstrates how to parse any set that the enumerate objects function
returns with a run-time library routine in order to remove the first value from
the set. The example also demonstrates how the program takes each value from
the set.

#include <dnsdef.h>
#include <dnsmsg.h>
/*
* Parameters:
* fname_p : opaque full name of the directory to enumerate
* fname_len : length of full name of the directory
*/
struct $dnsitmdef enumitem[4]; /* Item list for enumeration */
unsigned char setbuf[100]; /* Values from enumeration */
struct $dnsb enum_iosb; /* DECdns status information */
int synch_event; /* Used for synchronous AST threads */
unsigned short setlen; /* Length of output in setbuf */
enumerate_objects(fname_p, fname_len)
unsigned char *fname_p;
unsigned short fname_len;
{
int enumerate_objects_ast();
int status; /* General routine status */
int enum_status; /* Status of enumeration routine */
/* Set up item list */
enumitem[0].dns$w_itm_code = dns$_directory; /* Opaque directory name */
enumitem[0].dns$w_itm_size = fname_len;
enumitem[0].dns$a_itm_address = fname_p;
enumitem[1].dns$w_itm_code = dns$_outobjects; /* output buffer */
enumitem[1].dns$a_itm_ret_length = &setlen;
enumitem[1].dns$w_itm_size = 100;
enumitem[1].dns$a_itm_address = setbuf;
*((int *)&enumitem[2]) = 0; /* Zero terminate item list */
status = lib$get_ef(&synch_event); !

Distributed Name Service (VAX Only) C–13


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

if(status != SS$_NORMAL)
{
printf("Could not get event flag to synch AST threads\n");
exit(status);
}
enum_status = sys$dns(0, dns$_enumerate_objects, &enumitem,
" &enum_iosb, enumerate_objects_ast, setbuf);
if(enum_status != SS$_NORMAL) #
{
printf("Error enumerating objects = %d\n", enum_status);
exit(enum_status);
}
status = sys$synch(synch_event, &enum_iosb); $
if(status != SS$_NORMAL)
{
printf("Synchronization with AST threads failed\n");
exit(status);
}
}
/* AST routine parameter: */
/* outbuf : address of buffer that contains enumerated names. */
%
unsigned char objnamebuf[dns$k_simplenamemax]; /* Opaque object name */
enumerate_objects_ast(outbuf)
unsigned char *outbuf;
{
struct $dnsitmdef cvtitem[3]; /* Item list for class name */
struct $dnsb iosb; /* Used for name service status information */
struct dsc$descriptor set_dsc, value_dsc, newset_dsc;
unsigned char simplebuf[dns$k_simplestrmax]; /* Object name string */
int enum_status; /* The status of the enumeration itself */
int status; /* Used for checking immediate status returns */
int set_status; /* Status of remove value routine */
unsigned short val_len; /* Length of set value */
unsigned short sname_len; /* Length of object name */
enum_status = enum_iosb.dns$l_dnsb_status; /* Check status */
if((enum_status != SS$_NORMAL) && (enum_status != DNS$_MOREDATA))
{
printf("Error enumerating objects = %d\n", enum_status);
sys$setef(synch_event);
exit(enum_status);
}
do
{
/*
* Extract object names from output buffer one
* value at a time. Set up descriptors for the extraction.
*/
set_dsc.dsc$w_length = setlen; /* Contains address of */
set_dsc.dsc$a_pointer = setbuf; /* the set whose values */
/* are to be extracted */
value_dsc.dsc$w_length = dns$k_simplenamemax;
value_dsc.dsc$a_pointer = objnamebuf; /* To contain the */
/* name of an object */
/* after the extraction */
newset_dsc.dsc$w_length = 100; /* To contain a new */
newset_dsc.dsc$a_pointer = setbuf; /* set structure after */
/* the extraction. */

C–14 Distributed Name Service (VAX Only)


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

/* Call yRTL routine to extract the value from the set */


set_status = dns$remove_first_set_value(&set_dsc, &value_dsc, &val_len,
0, 0, &newset_dsc, &setlen);
if(set_status == SS$_NORMAL)
{ &
cvtitem[0].dns$w_itm_code = dns$_fromsimplename;
cvtitem[0].dns$w_itm_size = val_len;
cvtitem[0].dns$a_itm_address = objnamebuf;
cvtitem[1].dns$w_itm_code = dns$_tostringname;
cvtitem[1].dns$w_itm_size = dns$k_simplestrmax;
cvtitem[1].dns$a_itm_address = simplebuf;
cvtitem[1].dns$a_itm_ret_length = &sname_len;
*((int *)&cvtitem[2]) = 0;
status = sys$dnsw(0, dns$_simple_opaque_to_string, &cvtitem,
&iosb, 0, 0);
if(status == SS$_NORMAL)
status = iosb.dns$l_dnsb_status; /* Check for errors */
if(status != SS$_NORMAL) /* If error, terminate processing */
{
printf("Converting object name to string returned %d\n",
status);
exit(status);
}
else
{
printf("%.*s\n", sname_len,simplebuf);
}
enumitem[2].dns$w_itm_code = dns$_contextvarname; ’
enumitem[2].dns$w_itm_size = val_len;
enumitem[2].dns$a_itm_address = objnamebuf;
*((int *)&enumitem[3]) = 0;
}
else if (set_status != 0)
{
printf("Error %d returned when removing value from set\n",
set_status);
exit(set_status);
}
} while(set_status == SS$_NORMAL);
if(enum_status == DNS$_MOREDATA)
{ (
enum_status = sys$dns(0, dns$_enumerate_objects, &enumitem,
&enum_iosb, enumerate_objects_ast, setbuf);
if(enum_status != SS$_NORMAL) /* Check status of $DNS */
{
printf("Error enumerating objects = %d\n", enum_status);
sys$setef(synch_event);
}
}
else
{ )
sys$setef(synch_event);
}
}
! Get an event flag to synchronize the execution of AST threads.
" Use the system service to enumerate the object names.
# Check the status of the system service itself before waiting for threads.

Distributed Name Service (VAX Only) C–15


Distributed Name Service (VAX Only)
C.2 Using the SYS$DNS System Service Call

$ Use the SYS$SYNCH call to make sure the DECdns Clerk has completed and
that all threads have finished executing.
% After enumerating objects, SYS$DNS calls an AST routine. The routine
shows how DNS$REMOVE_FIRST_SET_VALUE extracts object names from
the set returned by the DNS$_ENUMERATE_OBJECTS function.
& Use an item list to convert the opaque simple name to a string name so you
can display it to the user. The item list contains the following entries:
• Address of the opaque simple name to be converted
• Address of the buffer that will hold the string name
• A value of 0 to terminate the item list
’ This object name may provide the context for continuing the enumeration.
Append the context variable to the item list so the enumeration can continue
from this name if there is more data.
( Use the system service to enumerate the object names as long as there is
more data.
) Set the event flag to indicate that all AST threads have completed and that
the program can terminate.

C.3 Using the DCL Command DEFINE with DECdns Logical Names
When the DECdns Clerk is started on the operating system, the VAX system
creates a unique logical name table for DECdns to use in translating full names.
This logical name table, called DNS$SYSTEM, prevents unintended interaction
with other system logical names.
To define systemwide logical names for DECdns objects, you must have the
appropriate privileges to use the DCL command DEFINE. Use the DEFINE
command to create the logical RESEARCH.PROJECT_DISK, for example, by
entering the following DCL command:
$ DEFINE/TABLE=DNS$SYSTEM RESEARCH "ENG.RESEARCH"
When parsing a name, the SYS$DNS service specifies the logical name
DNS$LOGICAL as the table it uses to translate a simple name into a full name.
This name translates to DNS$SYSTEM (by default) to access the systemwide
DECdns logical name table.
To define process or job logical names for SYS$DNS, you must create a process
or job table and redefine DNS$LOGICAL as a search list, as in the following
example (note that elevated privileges are required to create a job table):
$ CREATE /NAME_TABLE DNS_PROCESS_TABLE
$ DEFINE /TABLE=LNM$PROCESS_DIRECTORY DNS$LOGICAL -
_$DNS_PROCESS_TABLE,DNS$SYSTEM
Once you have created the process or job table and redefined DNS$LOGICAL,
you can create job-specific logical names for DECdns by using the DCL command
DEFINE, as follows:
$ DEFINE /TABLE=DNS_PROCESS_TABLE RESEARCH "ENG.RESEARCH.MYGROUP"

C–16 Distributed Name Service (VAX Only)


Index
Alignment, Vol 1, 15–1
A natural, Vol 1, 15–2
on OpenVMS Alpha systems, Vol 1, 6–3
Absolute time, Vol 2, 27–1
on OpenVMS VAX systems, Vol 1, 6–3
in system format, Vol 2, 27–6
OpenVMS Alpha systems, Vol 1, 15–3
Access, physical I/O, Vol 2, 23–6
OpenVMS VAX, Vol 1, 15–3
Access and protection
system services, Vol 1, 15–10
checking, Vol 2, 32–10
with BLISS compiler, Vol 1, 15–5
Access control entries with Compaq C compiler, Vol 1, 15–4
See ACEs with Compaq Fortran compiler, Vol 1, 15–6
Access control lists with compilers, Vol 1, 15–4
See ACLs with MACRO-32 compiler, Vol 1, 15–6
Access entry, in argument descriptions, Vol 2, with OpenVMS Debugger, Vol 1, 15–9
17–8 with PCA, Vol 1, 15–10
Access mask, Vol 2, 31–25 with tools, Vol 1, 15–9
Access methods, to argument data, Vol 2, 17–8 with VEST translator, Vol 1, 15–8
Access modes, Vol 2, 20–2 Alignment attribute, Vol 1, 14–11
effect on AST delivery, Vol 1, 8–10 Alpha architecture, Vol 1, 1–4
processor, Vol 2, B–2 Alpha platforms, Vol 1, 1–4
specifying, Vol 2, 20–3, 32–10 Alpha processors, Vol 1, 1–3
with AST, Vol 1, 8–6 APL (Application Programming Language), Vol 1,
Access name table, Vol 2, 31–25 1–11
access_bit_names data type, Vol 2, B–2 data type declarations, Vol 2, B–20
access_mode data type, Vol 2, B–2 implementation table, Vol 2, B–20
ACEs (access control entries) Applications
creating, Vol 2, 31–25, 31–26 distributed, Vol 1, 1–6
maintaining, Vol 2, 31–25, 31–26 graphical user interface, Vol 1, 1–20
translating, Vol 2, 31–25, 31–26 OpenVMS, Vol 1, 1–3
ACLs (access control lists), Vol 2, 31–2 portable, Vol 1, 1–6
Ada, Vol 1, 1–11 real-time, Vol 1, 1–20
data type declarations, Vol 2, B–17 Architecture
implementation table, Vol 2, B–17 Alpha, Vol 1, 1–4
address data type, Vol 2, B–2 CISC, Vol 1, 1–4
Addresses, virtual memory, Vol 2, 26–3 RISC, Vol 1, 1–4
Address space VAX, Vol 1, 1–4
allocating by page, Vol 1, 12–6, 13–8 Area extension size, Vol 1, 14–9
allocating in zones, Vol 1, 14–6 Argument information (AI) format, Vol 2, 18–9
deallocating by page, Vol 1, 12–6, 13–8, 14–2 Argument lists, Vol 2, 17–7, 18–9
zones, Vol 1, 14–6 creating, Vol 2, A–4
address_range data type, Vol 2, B–2 for AST service routine, Vol 1, 8–8
Affinity, types of, Vol 1, 4–35 for condition handler, Vol 1, 9–27
Affinity mechanism, Vol 1, 4–32 generic macro generated, Vol 2, A–1
AI (argument information), format, Vol 2, 18–9 using macros, Vol 2, A–2
AI (artificial intelligence), Vol 1, 1–12 Argument passing
Algorithms, for memory allocation, Vol 1, 14–7 for RTL routines, Vol 2, 19–4
Aligning data, Vol 2, 28–4 for system services, Vol 2, 20–4
mechanisms, Vol 2, 18–11
by descriptor, Vol 2, 18–16

Index–1
Argument passing Attributes (cont’d)
mechanisms (cont’d) Resource, Vol 2, 31–5
by reference, Vol 2, 18–14 Subsystem, Vol 2, 31–5
by value, Vol 2, 18–13
Arguments, Vol 2, 17–7
specifying, Vol 2, A–4
B
Arguments, mechanism vector, Vol 1, 9–35 Balance set, swapping, Vol 1, 12–12, 13–12
Arguments heading, in routine documentation, BASIC
Vol 2, 17–6 Compaq BASIC for OpenVMS Alpha, Vol 1,
arg_list data type, Vol 2, B–2 1–11
Arithmetic exceptions, on Alpha systems, Vol 1, data type declarations, Vol 2, B–22
9–13 implementation table, Vol 2, B–22
Arrays VAX BASIC, Vol 1, 1–11
mechanism, Vol 1, 9–35 BIOLM (buffered I/O limit) quota, Vol 2, 23–3
virtual address, Vol 1, 12–8, 13–10 32-bit descriptors, Vol 1, 11–2
ASCII (American Standard Code for Information 64-bit descriptors, Vol 1, 11–2
Interchange) 32-bit item list formats, Vol 1, 11–5
time, Vol 2, 27–7 64-bit item list formats, Vol 1, 11–6
Assemblers, Vol 1, 1–11 32-bit item lists, Vol 1, 11–5
ASSIGN command, Vol 2, 32–3 64-bit item lists, Vol 1, 11–6
AST routines, Vol 1, 8–1 BLISS
ASTs (asynchronous system traps), Vol 1, 1–17, data type declarations, Vol 2, B–25
2–20, 8–1; Vol 2, 24–21 implementation table, Vol 2, B–25
See also Synchronization BLISS-32, Vol 1, 1–11
access mode, Vol 1, 8–6 BLISS-64, Vol 1, 1–11
blocking, Vol 1, 7–14, 7–20 BLISS compiler
call frame, Vol 1, 8–3 alignment, Vol 1, 15–5
declaring, Vol 1, 8–2 consequences of noncompliant code, Vol 1, 6–9
delivery, Vol 1, 8–6, 8–8 Blocking ASTs
example, Vol 1, 8–10 description, Vol 1, 7–14
execution, Vol 1, 8–1 using, Vol 1, 7–20
in target process, Vol 1, 4–26 Block size options, Vol 1, 14–10
parameter, Vol 1, 8–9 Boolean data type, Vol 2, B–2
process wait state, Vol 1, 8–13 Boolean value flag, Vol 2, B–2
queuing, Vol 1, 8–2 Boot CPU, Vol 1, 5–1
quota, Vol 2, 23–3 Booting, an SMP system, Vol 1, 5–1
reentrant code, Vol 1, 8–3 Borders, virtual display, Vol 2, 22–12
service routine, Vol 1, 8–8 Boundary tags, Vol 1, 14–8
shared data access, Vol 1, 8–3 Broadcast messages, Vol 2, 22–43
system service, Vol 1, 8–2 buffer data type, Vol 2, B–2
writing, Vol 1, 8–2 Buffered I/O, operations, Vol 2, 27–18
ASTs delivery Buffer object management, Vol 2, 23–50
kernel threads, Vol 1, 8–11 Buffer objects, Fast I/O, Vol 2, 23–49
AST synchronization, shared data, Vol 1, 8–4 buffer_length data type, Vol 2, B–2
ast_procedure data type, Vol 2, B–2 BYPASS privilege, Vol 2, 23–5
Asynchronous input/output, Vol 2, 23–21 byte_signed data type, Vol 2, B–2
Asynchronous system services, Vol 2, 20–5 BYTLM (buffered I/O byte count) quota, Vol 2,
23–3
Asynchronous system traps
See ASTs
Atomic instructions, effect on synchronization, Vol C
1, 6–5 C
Atomicity, definition, Vol 1, 6–3 Compaq C for OpenVMS Alpha, Vol 1, 1–11
Atomic memory reference, Vol 1, 6–3 data type declarations, Vol 2, B–28
Attributes implementation table, Vol 2, B–28
Dynamic, Vol 2, 31–5 VAX C, Vol 1, 1–11
Holder Hidden, Vol 2, 31–5
Name Hidden, Vol 2, 31–5
No Access, Vol 2, 31–5

Index–2
C++, Vol 1, 1–11 Command language interpreter, Vol 1, 2–4
data type declarations, Vol 2, B–28 See CLI
implementation table, Vol 2, B–28 Common areas, per-process, Vol 1, 3–6
Caching, Vol 1, 7–20 Common blocks
Callable system routines, Vol 1, 1–15 aligning, Vol 2, 28–4
Call entry installing as a shared image, Vol 2, 26–6
for RTL, Vol 2, 19–4 interprocess, Vol 2, 26–6
for system service, Vol 2, 20–3 modifying, Vol 1, 3–6
Call-frame condition handlers, Vol 1, 9–24 Common event flag clusters, Vol 1, 6–25
Call frames, Vol 2, 18–3 permanent, Vol 1, 6–27
ASTs, Vol 1, 8–3 temporary, Vol 1, 6–27
exit handlers, Vol 1, 9–74 Compaq C++ compiler, consequences of
Calling ASTs, Vol 1, 8–7 noncompliant code, Vol 1, 6–9
Calling sequence, system routine, Vol 2, 18–5 Compaq C compiler
Calling standard, Vol 1, 1–9, 11–28; Vol 2, 19–1 alignment, Vol 1, 15–4
conventions, Vol 2, 18–1 consequences of noncompliant code, Vol 1, 6–9
Call stacks, unwinding, Vol 1, 9–46 Compaq COBOL, Vol 1, 1–11
Capabilities mechanism, Vol 1, 4–32 Compaq DECwindows Motif, Vol 2, 22–7
Capability masks creating WSA pseudo workstation devices, Vol
CPU, Vol 1, 4–34 2, 22–8
process, Vol 1, 4–34 height and width restrictions, Vol 2, 22–8
Capability types, Vol 1, 4–33 Compaq DECwindows Motif for OpenVMS
Catchall handlers, Vol 1, 9–25, 9–43 software, programming libraries and tools,
Chaining, Vol 2, 24–5 Vol 1, 1–19
item lists, Vol 1, 11–4 Compaq Extended Math Library for OpenVMS,
Change-mode handlers, Vol 1, 9–11 Vol 1, 1–17
channel data type, Vol 2, B–3 Compaq Fortran compiler
Channels, Vol 1, 3–10 alignment, Vol 1, 15–6
assigning I/O, Vol 2, 23–11 Compaq language implementation tables
deassigning, Vol 2, 23–24
See Implementation tables
Character string routines, Vol 2, 24–14
Compaq POSIX Threads Library, Vol 1, 1–15,
translation routines, Vol 2, 24–14
2–18
Character strings, Vol 2, B–3
.H file support, Vol 2, 21–2
char_string data type, Vol 2, B–3
Comparing 32-bit and 64-bit item lists, Vol 1,
Checking access and protection of logical name
11–4
tables, Vol 2, 32–10
Compatibility mode handlers, Vol 1, 9–11
$CHFDEF2 macro, Vol 1, 9–27
Compilers, Vol 1, 1–11
$CHFDEF macro, Vol 1, 9–27
alignment, Vol 1, 15–4
CISC, architecture, Vol 1, 1–4
complex_number data type, Vol 2, B–3
Class scheduler, Vol 1, 4–36
Components, of item lists, Vol 2, B–12
Class scheduler database, Vol 1, 4–40
Condition codes
Class_schedule, SYSMAN command, Vol 1, 4–37
chaining, Vol 1, 9–53
CLI (command language interpreter), Vol 1, 2–4;
signaling, Vol 1, 9–33
Vol 2, 24–2
SS$_EXQUOTA, Vol 1, 9–21
CLI access routine, Vol 2, 24–2
SS$_NOPRIV, Vol 1, 9–21
Client/server computing, Vol 1, 1–6
Condition handlers, Vol 2, 17–11
Clients, Vol 1, 1–6
Clocks, setting system, Vol 2, 27–11 See also Signal argument vectors
Clusterwide logical name tables, Vol 2, 32–6, argument list, Vol 1, 9–27
32–8, 32–9 arithmetic, Vol 1, 9–16
CMS, Vol 1, 1–15 call frame, Vol 1, 9–24
COBOL catchall, Vol 1, 9–25, 9–43
data type declarations, Vol 2, B–30 condition code, Vol 1, 9–65
implementation table, Vol 2, B–30 continuing execution of, Vol 1, 9–64
Command Definition Utility (CDU), Vol 1, 1–14, debugging, Vol 1, 9–70
1–19 default, Vol 1, 9–42
establishing, Vol 1, 9–5
example, Vol 1, 9–69

Index–3
Condition handlers (cont’d) Condition values
exiting, Vol 1, 9–66; Vol 2, B–7 returned (cont’d)
last-chance, Vol 1, 9–43 in I/O status block, Vol 2, 17–12
last-chance exception vector, Vol 1, 9–25 in mailbox, Vol 2, 17–12
mechanism argument vectors, Vol 1, 9–35 in R0, Vol 2, 17–4
primary exception vector, Vol 1, 9–24 signaled in register, Vol 2, 17–6, 17–12
resignaling, Vol 1, 9–64 RTL symbols, Vol 2, 19–6
searching for, Vol 1, 9–24 severity, Vol 1, 9–19
secondary exception vectors, Vol 1, 9–24 signaled, Vol 2, 17–6, 17–12
signal argument array, Vol 1, 9–32 symbolic codes, Vol 2, 20–8
software supplied, Vol 1, 9–41 testing, Vol 2, 20–8, 20–9
specifying, Vol 1, 9–4 Condition Values Returned heading, Vol 2, 17–11
traceback, Vol 1, 9–25, 9–42 cond_value data type, Vol 2, B–6
types, Vol 1, 9–41 context data type, Vol 2, B–7
types of action, Vol 1, 9–45 Control actions, inhibiting, Vol 2, 22–42
unwinding, Vol 1, 9–64 Coordinated Universal Time
use of, Vol 1, 9–27 See UTC system services
user-supplied, Vol 1, 9–41 CPU characteristics
writing, Vol 1, 9–63 SMP system, Vol 1, 5–1
Condition handling, Vol 1, 9–3 CPUs (central processing units)
See also Condition handlers affinity scheduling, Vol 1, 4–32
See also Condition Handling Facility capabilities scheduling, Vol 1, 4–32
See also Condition values class scheduling, Vol 1, 4–36
See also Exception conditions CPU-specific pages, Vol 1, 12–1
See also Exceptions Create Mailbox and Assign Channel system service
See also Message utility (MESSAGE) See also SYS$CREMBX system service
alignment fault reporting, Vol 1, 9–15 $CRFCTLTABLE macro, Vol 2, 25–1, 25–2
arithmetic exceptions, Vol 1, 9–13 $CRFFIELDEND macro, Vol 2, 25–1, 25–4
continuing, Vol 1, 9–45 $CRFFIELD macro, Vol 2, 25–1, 25–3
displaying messages, Vol 1, 9–49 Cross-Reference routines, Vol 2, 25–1
GOTO unwind, Vol 1, 9–45 C system( ) call, Vol 1, 2–6
hardware exception conditions, Vol 1, 9–12 Ctrl/C key sequence, Vol 2, 22–33
logging error messages, Vol 1, 9–6 Ctrl/Y key sequence, Vol 2, 22–33
logging error messages to a file, Vol 1, 9–55 Ctrl/Z key sequence, Vol 2, 22–5, 23–31
mechanism argument vectors, Vol 1, 9–35, Current procedure, Vol 1, 9–48
9–37 Current time, Vol 2, 27–9
mechanism array format, Vol 1, 9–37 Cursor movement, Vol 2, 22–21
resignaling, Vol 1, 9–45, 9–67
return status, Vol 1, 9–21 D
run-time library support routines, Vol 1, 9–17
signal argument vectors, Vol 1, 9–33 Data
signaling a condition, Vol 1, 9–45 aligning, Vol 2, 28–4
stack traceback, Vol 1, 9–6 interprocess, Vol 2, 26–6
stack unwind, Vol 1, 9–6, 9–45 sharing, Vol 2, 26–6
unwinding, Vol 1, 9–67 Data alignment, Vol 1, 15–1
user-defined messages, Vol 1, 9–6 exception reporting, Vol 1, 9–15
VAX hardware exceptions, Vol 1, 9–12 Databases, record, Vol 2, 28–12
Condition Handling Facility (CHF), Vol 1, 9–41 Data Cells, Vol 1, 2–23
definition, Vol 1, 9–1 Data management, Vol 1, 1–20
function, Vol 1, 9–4 Data types, Vol 2, 17–7, B–1
Conditions Ada declarations, Vol 2, B–17
for exception, Vol 1, 9–6 APL declarations, Vol 2, B–20
Condition values, Vol 1, 9–18 to 9–20, 9–31; Vol BASIC declarations, Vol 2, B–22
2, 18–22, 20–7, B–6 BLISS declarations, Vol 2, B–25
definition, Vol 1, 9–63 C++ declarations, Vol 2, B–28
information provided by, Vol 2, 20–8 C declarations, Vol 2, B–28
returned, Vol 2, 17–12 COBOL declarations, Vol 2, B–30
Fortran declarations, Vol 2, B–34

Index–4
Data types (cont’d) Default logical name tables
MACRO declarations, Vol 2, B–48 group, Vol 2, 32–6
OpenVMS, Vol 2, B–1, B–2 job, Vol 2, 32–5
standard, Vol 2, 17–7 process, Vol 2, 32–4
usage, Vol 2, 17–6 quotas, Vol 2, 32–15
Pascal declarations, Vol 2, B–38 system, Vol 2, 32–6
PL/I declarations, Vol 2, B–42 Default zone, Vol 1, 14–12
RPG II declarations, Vol 2, B–50 DEFINE command, Vol 2, 32–3
SCAN declarations, Vol 2, B–52 /DELETE qualifier
symbolic code, Vol 2, 17–7 LIBRARY command, Vol 2, 26–2
Date and time format logical names, Vol 2, 27–29 Delta/XDelta Debugger (DELTA/XDELTA), Vol 1,
Date format logical names, Vol 2, 27–29 to 27–30 1–13
Dates Delta time, Vol 2, 27–1
64-bit system format, Vol 2, 27–1 example, Vol 2, 27–6
128-bit system format, Vol 2, 27–36 in system format, Vol 2, 27–6
getting current system, Vol 2, 27–10 Descriptors
Smithsonian base, Vol 2, 27–1 class, Vol 2, 18–19
Date/time formats, Vol 2, 27–22 class codes, Vol 2, 17–10
Date/time manipulation, converting, Vol 2, 27–7 data type, Vol 2, 18–19
date_time data type, Vol 2, B–7 fields, Vol 2, 18–16
Deadlock detection, Vol 1, 7–8 Detached processes, Vol 1, 2–1
Debuggers, Vol 1, 1–13 creating, Vol 1, 2–13
Debugging debugging, Vol 1, 2–15
BUGCHECKFATAL, Vol 1, 1–14 Developing application programs, Vol 1, 1–7
condition handler, Vol 1, 9–70 Device drivers
CPUSPINWAIT, Vol 1, 1–14 last channel deassign, Vol 2, 23–4
detached process, Vol 1, 2–15 SHARE privilege, Vol 2, 23–4
exit handler, Vol 1, 9–70 Devices
MULTIPROCESSING, Vol 1, 1–14 allocating, Vol 2, 23–32
POOLCHECK, Vol 1, 1–14 deallocating, Vol 2, 23–33
subprocess, Vol 1, 2–15 default name, Vol 2, 23–28
SYSTEM_CHECK, Vol 1, 1–14 getting information about, Vol 2, 23–28
DECdns call, timeout, Vol 2, C–5 implicit allocation, Vol 2, 23–33
DECdns naming conventions names, Vol 2, 23–27
defining logicals, Vol 2, C–16 ownership, Vol 2, 23–4
logical names, Vol 2, C–16 protection, Vol 2, 23–5
DECdns objects SHARE privilege, Vol 2, 23–4
creating, Vol 2, C–4 Device types, Vol 2, 23–29
reading attributes, Vol 2, C–10 device_name data type, Vol 2, B–7
DECdtm services DIOLM (direct I/O limit)
aborted, Vol 2, 29–1 quota, Vol 2, 23–3
atomic, Vol 2, 29–1 Direct I/O, Vol 2, 27–18
committed, Vol 2, 29–1 Directives
distributed transaction, Vol 2, 29–1 See also Message utility (MESSAGE)
introduction to programming, Vol 2, 29–1 .END, Vol 1, 9–59
support for transaction processing, Vol 1, 1–18 .FACILITY, Vol 1, 9–58
DECforms, Vol 2, 22–2 .SEVERITY, Vol 1, 9–59
Declaring ASTs, Vol 1, 8–2 .TITLE, Vol 1, 9–60
DEClinks, Vol 1, 1–20 Directory logical name tables
DECset, Vol 1, 1–20 process, Vol 2, 32–3
DEC Text Processing Utility (DECTPU), Vol 2, system, Vol 2, 32–3
22–1 Directory table quotas, Vol 2, 32–15
DECTPU, Vol 1, 1–10 Disk files, opening, Vol 1, 12–14, 13–14
DECW$TERM_PORT example program, Vol 1, Disk volumes
2–15 mounting, Vol 2, 23–34
Deep directories, Vol 2, 28–2 Dispatcher, exception, Vol 1, 9–24

Index–5
Distributed computing, Vol 1, 1–6 Escape sequences, read, Vol 2, 23–31
Distributed environments, Vol 1, 1–6 EV6 Alpha processor, Vol 1, 6–9
Distributed processing, Vol 1, 1–5 EVE (Extensible Versatile Editor), Vol 1, 1–10
Documentation format Event flag clusters
See System routine documentation deleting, Vol 1, 6–27
Double-width characters disassociating, Vol 1, 6–27
See also Screen management specifying name for, Vol 1, 6–26
See also Virtual displays Event flags, Vol 1, 1–17, 2–20, 6–20
specifying, Vol 2, 22–21 See also Synchronization
Dynamic attributes, Vol 2, 31–5 allocation of, Vol 2, 24–17
Dynamic memory allocation, Vol 1, 12–5 clearing, Vol 1, 6–31
cluster, Vol 1, 6–21; Vol 2, B–7
common, Vol 1, 6–21
E for interprocess communication, Vol 1, 3–8
Echo local, Vol 1, 3–2, 6–21
terminal, Vol 2, 22–40 number, Vol 2, B–7
terminators, Vol 2, 22–25 numbers, Vol 1, 6–21
Editors, Vol 1, 1–10 setting, Vol 1, 6–31
EDT, Vol 1, 1–10 specifying, Vol 1, 6–22
EVE, Vol 1, 1–10 wait, Vol 1, 6–29
TECO, Vol 1, 1–10 Event flag service, example using, Vol 1, 6–34
vi (POSIX), Vol 1, 1–10 Event flag zero (0), Vol 1, 6–23
EFN 128 event flag Exception conditions, Vol 1, 9–2, 9–6; Vol 2,
EFN$C_ENF, Vol 1, 6–22, 6–23 17–11
ef_cluster_name data type, Vol 2, B–7 returning condition value, Vol 1, 9–7
ef_number data type, Vol 2, B–7 signaling, Vol 1, 9–6, 9–7, 9–16, 9–28, 9–49
.END directive, Vol 1, 9–59 Exceptions
ENQLM process limit, Vol 1, 7–9 definition, Vol 1, 9–2
Enqueue process limit quota, Vol 1, 7–9 dispatcher, Vol 1, 9–24
Entry masks, Vol 2, B–15 floating-point underflow, Vol 1, 9–16
Entry points handling by run-time library, Vol 1, 9–15
CALL entry points, Vol 2, 19–4, 20–4 type, Vol 1, 9–6
RTL names, Vol 2, 19–3 EXE$READ_PROCESS routine, Vol 1, 4–43 to
Environments 4–45
client/server, Vol 1, 1–6 EXE$WRITE_PROCESS routine, Vol 1, 4–45 to
common code, Vol 1, 1–9 4–47
common language, Vol 1, 1–9 Execution context, Vol 1, 2–2
computing, Vol 1, 1–5 Executive images
distributed, Vol 1, 1–6 linking, Vol 1, 4–51 to 4–52
hyperinformation, Vol 1, 1–20 loading, Vol 1, 4–52 to 4–56
open system, Vol 1, 1–5 unloading, Vol 1, 4–56 to 4–58
production systems, Vol 1, 1–5 writing, Vol 1, 4–48 to 4–50
EOF (end-of-file), Vol 2, 22–5 Executive mode
Equivalence names ASTs, Vol 1, 8–12
defining, Vol 2, 32–2 Executive stack, Vol 1, 2–22
format convention, Vol 2, 32–17 Exit handlers, Vol 1, 4–70, 9–74; Vol 2, 23–31
Error checking, Vol 2, 20–9 debugging, Vol 1, 9–77
Error handling establishing, Vol 1, 9–75
See Condition handling writing, Vol 1, 9–77
Error recovery, Vol 2, 23–11 Exits
Error returns, Vol 2, 18–22 See also Exit handlers
Errors forced, Vol 1, 4–70
returning condition value, Vol 2, 18–22 image, Vol 1, 4–68, 9–74
signaling condition value, Vol 2, 18–23 exit_handler_block data type, Vol 2, B–7
Errors, signaling, Vol 1, 9–5 Explanatory text
in argument documentation, Vol 2, 17–10
in routine documentation, Vol 2, 17–4

Index–6
Explicit affinity, Vol 1, 4–35 Floating-point overflow, Vol 1, 9–16
Extended address space, Vol 1, 13–3, 13–4 Floating-Point Registers and Execution Data
physical address space, Vol 1, 13–3 Blocks
virtual address space, Vol 1, 13–4 See FREDs
Extended file names, Vol 2, 28–2 Floating-point register usage, Vol 2, 18–3
Extended File Specifications, Vol 2, 28–2 Floating-point underflow, Vol 1, 9–16
Extents, defining section, Vol 1, 12–15, 13–15 floating_point data type, Vol 2, B–8
/EXTRACT qualifier Forced exit, Vol 1, 4–70
LIBRARY command, Vol 2, 26–2 Foreign commands, Vol 2, 24–3
Foreign devices, Vol 2, 23–5
F Foreign volumes, Vol 2, 23–4, 23–6
Format convention of equivalence names, Vol 2,
FAB data type, Vol 2, B–7 32–17
FABs (file access blocks), Vol 2, 28–15, B–7 Format convention of logical names, Vol 2, 32–17
.FACILITY directive, Vol 1, 9–58 Format heading, Vol 2, 17–2
Facility identifiers, Vol 2, 31–4
See also System routine documentation
FAO argument, signaling, Vol 1, 9–62
Fortran
FAO parameter, specifying, Vol 1, 9–62
Compaq Fortran 90, Vol 1, 1–12
Fast I/O, Vol 2, 23–48 to 23–51
Compaq Fortran for OpenVMS Alpha, Vol 1,
benefits, Vol 2, 23–48
1–11
buffer objects, Vol 2, 23–49
Compaq Fortran for OpenVMS VAX, Vol 1,
Fast Path, Vol 2, 23–48, 23–51 to 23–52
1–11
File access, protection, Vol 2, B–8
data type declarations, Vol 2, B–34
File access blocks implementation table, Vol 2, B–34
See FABs FREDs (Floating-Point Registers and Execution
File access strategies, Vol 2, 28–2 Data Blocks), Vol 1, 2–22
File attributes, Vol 2, 28–1 Function codes, Vol 2, 23–10
Files Function modifiers, Vol 2, 23–11
attributes, Vol 2, 28–1, 28–2 IO$M_INHERLOG, Vol 2, 23–6
complete access, Vol 2, 28–2 types of
discrete records access, Vol 2, 28–2 IO$M_DATACHECK, Vol 2, 23–11
mapping, Vol 2, 28–4 IO$M_INHRETRY, Vol 2, 23–11
record-by-record access, Vol 2, 28–2 Function value returns, for RTL routines, Vol 2,
sequential, Vol 2, 28–12 19–6
sequential and indexed access, Vol 2, 28–2 function_code data type, Vol 2, B–11
File terminators, Vol 2, 23–31
file_protection data type, Vol 2, B–8
Fixed-size stack frames, Vol 2, 18–5 G
Flags Global sections, Vol 1, 12–16, 13–16; Vol 2, 26–9,
See also Event flags B–16
Flag words, bit mask, Vol 2, B–14 characteristics, Vol 1, 12–16, 13–16
Floating-point numbers, Vol 2, B–3 to B–11 definition, Vol 1, 12–13, 13–13
D_floating complex, Vol 2, B–3 for interprocess communication, Vol 1, 3–8
D_floating standard, Vol 2, B–9 mapping, Vol 1, 12–20, 13–19
F_floating complex, Vol 2, B–3 multiprocessing, Vol 1, 6–19
F_floating standard, Vol 2, B–8 name, Vol 1, 12–17, 13–17
G_floating complex, Vol 2, B–4 paging file, Vol 1, 12–21, 13–20
G_floating standard, Vol 2, B–9 permanent, Vol 2, 26–13
H_floating complex, Vol 2, B–4 temporary, Vol 2, 26–13
H_floating standard, Vol 2, B–10 writable, Vol 1, 6–19
S_floating complex, Vol 2, B–5 Global symbols, Vol 2, 26–4
S_floating standard, Vol 2, B–10 signaling with, Vol 1, 9–61
T_floating complex, Vol 2, B–5 GMT (Greenwich Mean Time), Vol 2, 27–36
T_floating standard, Vol 2, B–11 GOTO unwind operations, Vol 1, 9–49
X_floating complex, Vol 2, B–6 Granularity
X_floating standard, Vol 2, B–11 of resources, Vol 1, 7–3
on OpenVMS Alpha systems, Vol 1, 6–3

Index–7
Granularity (cont’d) I/O channel indexes, Vol 2, B–3
on OpenVMS VAX systems, Vol 1, 6–3 I/O channels, Vol 2, 23–11
Graphical interfaces, creating, Vol 1, 1–20 deassigning, Vol 2, 23–24
Group logical name tables, Vol 2, 32–6 I/O completion
recommended test, Vol 2, 23–18
H status, Vol 2, 23–23
synchronizing, Vol 2, 23–13
Handlers, change and compatibility modes, Vol 1, I/O functions
9–11 codes, Vol 2, 23–10, 23–13
Hardware process control blocks modifier, Vol 2, 23–11
See HWPCBs I/O operations
Hardware registers logical, Vol 2, 23–6
for Alpha, Vol 2, 18–2 overview, Vol 2, 23–2
for VAX, Vol 2, 18–1 physical, Vol 2, 23–5
.H files quotas, privileges, and protection, Vol 2, 23–2
from SYS$STARLET_C.TLB to support Compaq virtual, Vol 2, 23–6
POSIX Threads Library, Vol 2, 21–2 I/O performance
provided by SYS$STARLET_C.TLB, Vol 2, Fast I/O, Vol 2, 23–48
21–2 Fast Path, Vol 2, 23–48
Hibernation, Vol 1, 4–63 I/O requests
alternate method, Vol 1, 4–66 canceling, Vol 2, 23–26
and AST, Vol 1, 8–13 queuing, Vol 2, 23–12
compared with suspension, Vol 1, 4–64 I/O services
High-performance sort, Vol 1, 1–19 asynchronous version, Vol 2, 23–19
Holder Hidden attribute, Vol 2, 31–5 synchronous version, Vol 2, 23–19
Holder records, Vol 2, 31–8 I/O status blocks
adding, Vol 2, 31–12 See IOSBs
format, Vol 2, 31–9 I/O system services, Vol 1, 1–18
modifying, Vol 2, 31–14 ICBs (invocation context blocks), Vol 2, B–12
removing, Vol 2, 31–16 ICC system services, Vol 1, 3–21
HWPCBs (hardware process control blocks), Vol 1, identifier data type, Vol 2, B–11
2–21, 2–22 Identifier names, translating, Vol 2, 31–11
Hyperinformation environment, Vol 1, 1–20 Identifier records, Vol 2, 31–8
adding to rights database, Vol 2, 31–12
I format, Vol 2, 31–8
modifying, Vol 2, 31–13
I/O (input/output)
removing from rights database, Vol 2, 31–16
asynchronous, Vol 2, 23–21
Identifiers, Vol 2, 31–1, 31–2
checking device type, Vol 2, 23–29
adding to rights database, Vol 2, 31–12
complex, Vol 2, 22–2
attributes, Vol 2, 31–4, 31–5
echo, Vol 2, 22–40
defining, Vol 2, 31–1
exit handler, Vol 2, 23–31
determining holders of, Vol 2, 31–13
lowercase, Vol 2, 22–42
facility, Vol 2, 31–4
reading a single line, Vol 2, 22–4
format, Vol 2, 31–2
reading several lines, Vol 2, 22–5
general, Vol 2, 31–2
screen updates, Vol 2, 22–31
global sections, Vol 2, B–16
simple, Vol 2, 22–2
new attributes, Vol 2, 31–5
status, Vol 2, 23–22
removing from rights database, Vol 2, 31–16
synchronous, Vol 2, 23–19
rights, Vol 2, B–16
terminator, Vol 2, 22–4
rights database, Vol 2, B–16
end of file, Vol 2, 23–31
system-defined, Vol 2, 31–3
record, Vol 2, 23–31
UIC, Vol 2, 31–3
timeout, Vol 2, 22–41
user, Vol 2, B–16, B–17
unsolicited input, Vol 2, 22–36
Identifier values, translating, Vol 2, 31–11
uppercase, Vol 2, 22–42
If states, composed input, Vol 2, 22–29
using SYS$QIO system service, Vol 2, 23–23
using SYS$QIOW system service, Vol 2, 23–23
writing simple character data, Vol 2, 22–6

Index–8
IMAGELIB.OLB file, Vol 2, 26–5 Interprocess communication (cont’d)
Image rundown, Vol 1, 9–74 mailboxes, Vol 1, 3–8
Image rundown, effect on logical names, Vol 2, using, Vol 1, 3–8
32–5 shareable logical names, Vol 2, 32–16
Images Interprocess control, Vol 1, 3–1
exit, Vol 1, 4–68 Interrupt priority level, Vol 1, 6–7
exiting, Vol 1, 9–74 See IPL
for subprocess, Vol 1, 2–12 Interrupt requests, SMP systems, Vol 1, 5–2
loading site-specific, Vol 2, 31–30 Intra-Cluster communications, Vol 1, 3–1, 3–21
rundown activity, Vol 1, 4–69 clients, Vol 1, 3–26
shareable, Vol 2, 26–3 concepts, Vol 1, 3–22
Image sections, Vol 1, 12–26, 13–23 design considerations, Vol 1, 3–23
Impersonation services, Vol 2, 31–20 programming considerations, Vol 1, 3–25
Implementation tables servers, Vol 1, 3–25
Ada, Vol 2, B–17 Intraprocess communication, Vol 1, 3–1
APL, Vol 2, B–20 common area, Vol 1, 3–6
BASIC, Vol 2, B–22 global symbols, Vol 1, 3–5
BLISS, Vol 2, B–25 Invocation context blocks
C and C++, Vol 2, B–28 See ICBs
COBOL, Vol 2, B–30 Invocation handles, Vol 2, B–12
Fortran, Vol 2, B–34 invo_context_blk data type, Vol 2, B–12
MACRO language, Vol 2, B–48 invo_handle data type, Vol 2, B–12
OpenVMS usage, Vol 2, B–1 IOSBs (I/O status blocks), Vol 1, 8–4; Vol 2, B–12
Pascal, Vol 2, B–38 in synchronization, Vol 2, 23–13
PL/I, Vol 2, B–42 return condition value field, Vol 2, 23–23
RPG II, Vol 2, B–50 io_status_block data type, Vol 2, B–12
SCAN, Vol 2, B–52 IPL (interrupt priority level), Vol 1, 6–7
Implicit affinity, Vol 1, 4–35 Item lists
IM semaphore, Vol 1, 6–17 chaining, Vol 1, 11–4
Initialization segments, Vol 1, 11–5
argument list, Vol 2, 33–5 item_list_2 data type, Vol 2, B–12
volume item_list_3 data type, Vol 2, B–13
from within a program, Vol 2, 23–36 item_list_pair data type, Vol 2, B–13
within a program item_quota_list data type, Vol 2, B–13
example, Vol 2, 23–36
Initialization routines
declaring, Vol 2, 33–6 J
dispatching, Vol 2, 33–7 Jacket routines, Vol 2, 24–1
options, Vol 2, 33–7 Job logical name tables, Vol 2, 32–5, 32–15
INITIALIZATION_ROUTINE macro, Vol 1, 4–50 JSB call format, Vol 2, 17–4
Inner mode (IM) semaphore, Vol 1, 6–17 JSB entry points, Vol 2, 19–6
Inner mode access, Vol 1, 2–20
Inner mode ASTs, Vol 1, 8–12
Inner mode synchronization, Vol 1, 6–17
K
Input address arrays, Vol 1, 12–8, 13–9 Kernel mode ASTs, Vol 1, 8–12
Instruction memory barriers, Vol 1, 6–16 Kernel stacks, Vol 1, 2–22
Instructions, queue, Vol 1, 6–20 Kernel thread blocks, Vol 1, 2–21
Integer and floating-point routines, Vol 2, 24–12 See KTBs
Integer register usage, Vol 2, 18–2 Kernel threads
Interlocked instructions, Vol 1, 6–6, 6–15, 6–20 advantages, Vol 1, 2–17
Interlocked memory instructions, using, Vol 1, 6–9 AST delivery, Vol 1, 8–11
Internal file identifiers, Vol 2, 32–17 definition, Vol 1, 2–17
Interpreters, Vol 1, 1–11 execution, Vol 1, 4–63
Interprocess communication, Vol 1, 3–1, 3–7 hibernating, Vol 1, 4–63
event flags, Vol 1, 3–8 model, Vol 1, 2–19
global sections, Vol 1, 3–8 priority, Vol 1, 4–32
lock management services, Vol 1, 3–8 region, Vol 1, 2–22
logical names, Vol 1, 3–8 scheduling, Vol 1, 4–32

Index–9
Kernel threads (cont’d) LIB$FFS, Vol 2, 24–10
suspending, Vol 1, 4–63 LIB$FILE_SCAN system routine, Vol 2, 24–22,
Keypads, reading from, Vol 2, 22–26 24–23
Key tables, reading from, Vol 2, 22–29 LIB$FILE_SCAN_END system routine, Vol 2,
KTBs (kernel thread blocks), Vol 1, 2–21 24–23
LIB$FIND_FILE system routine, Vol 2, 24–22
L LIB$FIND_FILE_END system routine, Vol 2,
24–22
Languages
LIB$FIND_VM_ZONE routine, Vol 1, 14–7
ANSI/ISO, Vol 1, 1–6
LIB$FIXUP_FLT routine, Vol 1, 9–73
compilers, Vol 1, 1–11
LIB$FLT_UNDER procedure call, Vol 2, 18–14
Last-chance exception vectors, Vol 1, 9–25
LIB$FLT_UNDER routine, Vol 1, 9–16
LDR$LOAD_IMAGE routine, Vol 1, 4–53 to 4–56
LIB$FREE_EF system routine, Vol 2, 24–16
LDR$UNLOAD_IMAGE routine, Vol 1, 4–56 to
LIB$FREE_LUN system routine, Vol 2, 24–16
4–58
LIB$FREE_TIMER routine, Vol 2, 27–19
LIB$ADDX routine, Vol 2, 27–7
LIB$FREE_VM routine, Vol 1, 12–4, 13–6
LIB$ADD_TIME routine, Vol 2, 27–7
LIB$FREE_VM_PAGE routine, Vol 1, 12–4, 13–6
LIB$ASN_WTH_MBX routine, Vol 1, 3–10
LIB$GETJPI system routine, Vol 1, 4–9
LIB$AST_IN_PROG routine, Vol 2, 24–22
LIB$GETQUI routine, Vol 2, 27–21
LIB$ATTACH routine, Vol 2, 24–9
LIB$GET_COMMON routine, Vol 1, 3–6; Vol 2,
LIB$CALLG routine, Vol 2, 24–15
24–5
LIB$CONVERT_DATE_STRING system routine,
LIB$GET_DATE_FORMAT system routine, Vol 2,
Vol 2, 27–33
27–34
LIB$CRC routine, Vol 2, 24–16
LIB$GET_EF system routine, Vol 2, 24–16
LIB$CRC_TABLE routine, Vol 2, 24–16
LIB$GET_FOREIGN routine, Vol 2, 24–3
LIB$CREATE_DIR routine, Vol 2, 24–22
LIB$GET_INPUT procedure call, Vol 2, 19–4
LIB$CREATE_USER_VM_ZONE routine, Vol 1,
LIB$GET_INPUT routine, Vol 2, 22–4 to 22–6
14–12, 14–16
example, Vol 2, 22–4
LIB$CREATE_VM_ZONE routine, Vol 1, 14–7,
obtaining several lines of input, Vol 2, 22–5
14–16
obtaining single line of input, Vol 2, 22–4
LIB$CRF_INS_KEY, Vol 2, 25–1
prompt, Vol 2, 22–4
LIB$CRF_INS_REF, Vol 2, 25–1
LIB$GET_LUN system routine, Vol 2, 24–16
LIB$CRF_OUTPUT, Vol 2, 25–1
LIB$GET_SYMBOL routine, Vol 2, 24–8
LIB$CURRENCY system routine, Vol 2, 24–20
LIB$GET_VM routine, Vol 1, 12–4, 13–6
LIB$DATE_TIME routine, Vol 2, 27–9
LIB$GET_VM_PAGE routine, Vol 1, 12–4, 13–6
LIB$DAY routine, Vol 2, 27–5
LIB$INITIALIZE routine, Vol 2, 33–1
LIB$DAY_OF_WEEK system routine, Vol 2, 27–9
LIB$INIT_DATE_TIME_CONTEXT system
LIB$DECODE_FAULT routine, Vol 1, 9–73
routine, Vol 2, 27–24
LIB$DEC_OVER routine, Vol 1, 9–16
LIB$INIT_TIMER routine, Vol 2, 27–19
LIB$DELETE_LOGICAL routine, Vol 2, 24–8
LIB$INSERT_TREE routine, Vol 2, 24–29
LIB$DELETE_SYMBOL routine, Vol 2, 24–8
LIB$INSQHI system routine, Vol 2, 24–13
LIB$DELETE_VM_ZONE routine, Vol 1, 14–7,
LIB$INSQTI system routine, Vol 2, 24–13
14–13
LIB$INSV system routine, Vol 2, 24–10
LIB$DIGIT_SEP system routine, Vol 2, 24–20
LIB$INT_OVER routine, Vol 1, 9–16
LIB$DISABLE_CTRL routine, Vol 2, 24–9
LIB$LOCC system routine, Vol 2, 24–14
LIB$DO_COMMAND routine, Vol 2, 24–7
LIB$LOOKUP_TREE routine, Vol 2, 24–29
LIB$DT_FORMAT logical name, Vol 2, 27–24,
LIB$LP_LINES system routine, Vol 2, 24–20
27–29
LIB$MATCHC system routine, Vol 2, 24–14
LIB$DT_INPUT_FORMAT logical name, Vol 2,
LIB$MATCH_COND routine, Vol 1, 9–34, 9–65,
27–24
9–73
LIB$EMUL system routine, Vol 2, 24–12
LIB$MOVC3 system routine, Vol 2, 24–14
LIB$ENABLE_CTRL routine, Vol 2, 24–9
LIB$MOVC5 system routine, Vol 2, 24–14
LIB$ESTABLISH routine, Vol 1, 9–4, 9–41
LIB$MOVTC system routine, Vol 2, 24–14
LIB$EXTV system routine, Vol 2, 24–10
LIB$MOVTUC system routine, Vol 2, 24–14
LIB$EXTZV system routine, Vol 2, 24–10
LIB$MULTF_DELTA_TIME routine, Vol 2, 27–7
LIB$FFC system routine, Vol 2, 24–10
LIB$MULT_DELTA_TIME routine, Vol 2, 27–7

Index–10
LIB$PUT_COMMON routine, Vol 1, 3–6; Vol 2, LIBRARY command
24–5 /CREATE qualifier, Vol 2, 26–2
LIB$PUT_OUTPUT routine, Vol 2, 22–4 /DELETE qualifier, Vol 2, 26–3
example, Vol 2, 22–7 /EXTRACT qualifier, Vol 2, 26–3
writing simple output, Vol 2, 22–6 /LIST qualifier, Vol 2, 26–2
LIB$RADIX_POINT system routine, Vol 2, 24–20 /REPLACE qualifier, Vol 2, 26–2
LIB$REMQHI system routine, Vol 2, 24–13 Line editing, inhibiting, Vol 2, 22–42
LIB$REMQTI system routine, Vol 2, 24–13 Linkage sections, Vol 1, 12–11
LIB$RESERVE_EF system routine, Vol 2, 24–16 Linker utility, Vol 1, 1–12
LIB$RESET_VM_ZONE routine, Vol 1, 14–6, Linker utility, searching object libraries, Vol 2,
14–13 26–2
LIB$REVERT routine, Vol 1, 9–4, 9–5 LINK/SHAREABLE command, Vol 2, 26–7
LIB$RUN_PROGRAM routine, Vol 2, 24–5 /LIST qualifier
LIB$SCANC system routine, Vol 2, 24–14 LIBRARY command, Vol 2, 26–2
LIB$SET_LOGICAL routine, Vol 2, 24–8 LNK$LIBRARY routine, Vol 2, 26–2
LIB$SET_SYMBOL routine, Vol 2, 24–8 See also Libraries
LIB$SHOW_TIMER procedure call, Vol 2, 19–2 See also Linker utility (LINK)
LIB$SHOW_TIMER routine, Vol 2, 27–19 Load-locked instructions, Vol 1, 6–8, 6–20
LIB$SHOW_VM_ZONE routine, Vol 1, 14–7 Local buffer caching, with lock management
LIB$SIGNAL procedure call, Vol 2, 19–2 service, Vol 1, 7–20
LIB$SIGNAL routine, Vol 1, 9–3, 9–5, 9–16, 9–28, Local symbols, Vol 2, 26–4
9–34, 9–35, 9–36, 9–50, 9–57, 9–64 signaling with, Vol 1, 9–61
generating signals, Vol 1, 9–30 LOCKIDTBL_MAX parameter, Vol 1, 7–10
invoking, Vol 1, 9–30 Lock limits, Vol 1, 7–8
LIB$SIG_TO_RET routine, Vol 1, 9–71 Lock management system services
establishing, Vol 1, 9–72 for interprocess communication, Vol 1, 3–8
LIB$SIG_TO_STOP routine, Vol 1, 9–72 Lock manager, Vol 1, 7–1; Vol 2, B–13
LIB$SIM_TRAP routine, Vol 1, 9–64, 9–71 See also Synchronization and Distributed lock
LIB$SKPC system routine, Vol 2, 24–14 manager
LIB$SPANC system routine, Vol 2, 24–14 ENQLM quota, Vol 1, 7–9
LIB$SPAWN routine, Vol 2, 24–9 LOCKIDTBL size, Vol 1, 7–10
LIB$STAT_TIMER routine, Vol 2, 27–19 resource hash table quota, Vol 1, 7–10
LIB$STOP routine, Vol 1, 9–3, 9–5, 9–7, 9–28, sub-resource and sub-lock quota, Vol 1, 7–9
9–34, 9–36, 9–45, 9–50, 9–57, 9–64 Lock quotas, Vol 1, 7–8
generating signals, Vol 1, 9–30 Lock requests
LIB$SUBX routine, Vol 2, 27–7 queuing, Vol 1, 7–6
LIB$SUB_TIME routine, Vol 2, 27–7 queuing a lock request, Vol 1, 7–10
LIB$TRAVERSE_TREE routine, Vol 2, 24–29 synchronizing, Vol 1, 7–12
LIB$VERIFY_VM_ZONE routine, Vol 1, 14–7 Locks
Librarian utility (LIBRARIAN), Vol 1, 1–12 choice of mode, Vol 1, 7–5
Libraries concept of, Vol 1, 7–2
default object, Vol 2, 26–2 conversion, Vol 1, 7–7, 7–14, 7–15
macro, Vol 2, 26–3, 26–5 deadlock detection, Vol 1, 7–8
message object module, Vol 1, 9–60 dequeuing, Vol 1, 7–18
object, Vol 2, 26–2, 26–5 level, Vol 1, 7–5
adding modules, Vol 2, 26–2 mode, Vol 1, 7–5
creating, Vol 2, 26–2 Lock status blocks, Vol 1, 7–13
deleting a module, Vol 2, 26–2 Lock value blocks
extracting a module, Vol 2, 26–2 description, Vol 1, 7–17
listing modules, Vol 2, 26–2 using, Vol 1, 7–20
replacing modules, Vol 2, 26–2 Lock values, Vol 2, B–13
system default, Vol 2, 26–2 lock_id data type, Vol 2, B–13
user default, Vol 2, 26–2 lock_status_block data type, Vol 2, B–13
system default, Vol 2, 26–5 lock_value_block data type, Vol 2, B–14
text, Vol 2, 26–3 Logical I/Os
user default, Vol 2, 26–5 operations, Vol 2, 23–6
privilege, Vol 2, 23–4, 23–5, 23–6

Index–11
Logical names, Vol 2, 23–27, C–16
attributes, Vol 2, 32–13
creating with SYS$CRELNM, Vol 2, 32–18
M
defining, Vol 2, 32–2 MACRO
deleting with SYS$DELLNM, Vol 2, 32–21 MACRO-32 Compiler, Vol 1, 1–12
format convention, Vol 2, 32–17 MACRO-64 Assembler, Vol 1, 1–12
image rundown, Vol 2, 32–5 MACRO–32 compiler
LIB$DT_FORMAT, Vol 2, 27–24 alignment, Vol 1, 15–6
LIB$DT_INPUT_FORMAT, Vol 2, 27–24 consequences of noncompliant code, Vol 1, 6–9
multivalued, Vol 2, 32–2 MACRO–64 assembler, consequences of
superseding, Vol 2, 32–13 noncompliant code, Vol 1, 6–9
SYS$LANGUAGE, Vol 2, 27–24 MACRO language
translating, Vol 2, 32–11 data type declarations, Vol 2, B–48
translating with SYS$TRNLNM, Vol 2, 32–22 generating argument lists, Vol 2, A–1
Logical names, for interprocess communication, implementation table, Vol 2, B–48
Vol 1, 3–8 VAX MACRO, Vol 1, 1–12
Logical name system service calls Macro libraries, Vol 2, 26–5
SYS$CRELNM system service, Vol 2, 32–18 Macros
SYS$CRELNT system service, Vol 2, 32–21 calling system services, Vol 2, A–5
SYS$DELLNM system service, Vol 2, 32–21 expansion, Vol 2, A–4
SYS$TRNLNM system service, Vol 2, 32–22 generating argument list
Logical name table names and search lists, Vol 2, CALLG instruction, Vol 2, A–6
32–7 CALLS instruction, Vol 2, A–6
Logical name tables system services, Vol 2, 20–1, A–1
clusterwide, Vol 2, 32–6, 32–8 Magnetic tapes
creating with SYS$CRELNT, Vol 2, 32–21 initializing within a program, Vol 2, 23–36
default, Vol 2, 32–4 example, Vol 2, 23–36
directory, Vol 2, 32–3 Mailboxes, Vol 1, 3–8, 3–10; Vol 2, 20–2, 23–39
group, Vol 2, 32–6 creating, Vol 1, 3–9
job, Vol 2, 32–5 for interprocess communication, Vol 1, 3–8
predefined logical names, Vol 2, 32–3 input/output
process, Vol 2, 32–4 asynchronous, Vol 1, 3–11
process-private, Vol 2, 32–8 immediate, Vol 1, 3–11
quotas, Vol 2, 32–15 synchronous, Vol 1, 3–11
search list, Vol 2, 32–8 using SYS$QIO, Vol 1, 3–11
modifying, Vol 2, 32–8 using SYS$QIOW, Vol 1, 3–11
shareable, Vol 2, 32–8 name, Vol 2, 23–43
system, Vol 2, 32–6 permanent, Vol 1, 3–9
types, Vol 2, 32–3 protection, Vol 2, 23–4
user-defined, Vol 2, 32–8 reading data from, Vol 1, 3–11
Logical unit numbers, allocating, Vol 2, 24–16 system, Vol 2, 23–43
logical_name data type, Vol 2, B–14 messages, Vol 2, 23–44
LOGINOUT temporary, Vol 1, 3–9
creating SYS$LOGIN logical name, Vol 1, 2–8 termination, Vol 1, 4–74
creating SYS$LOGIN_DEVICE logical name, writing data to, Vol 1, 3–11
Vol 1, 2–8 Management
creating SYS$SCRATCH logical name, Vol 1, data, Vol 1, 1–20
2–8 system, Vol 1, 1–5
LOGINOUT sample program, Vol 1, 2–8 Mapped files, Vol 2, 28–4
longword_signed data type, Vol 2, B–14 closing, Vol 2, 28–11
longword_unsigned data type, Vol 2, B–14 saving, Vol 2, 28–11
LSE/SCA, Vol 1, 1–10 mask_byte data type, Vol 2, B–14
mask_longword data type, Vol 2, B–14
mask_quadword data type, Vol 2, B–14
mask_word data type, Vol 2, B–14
Mathematical functions, Vol 1, 1–16

Index–12
MAXBOBMEN Middleware services, Vol 1, 1–8
SYSGEN parameter, Vol 2, 23–50 client/server software, Vol 1, 1–7
MAXBOBS0S1 Mixed-language programming, calling conventions,
SYSGEN parameter, Vol 2, 23–50 Vol 2, 18–1
MAXBOBS2 MMS, Vol 1, 1–15
SYSGEN parameter, Vol 2, 23–50 Modularity, virtual displays, Vol 2, 22–31
Mechanism argument vectors, Vol 1, 9–28, 9–35, MOUNT privilege, Vol 2, 23–4
9–63; Vol 2, B–14 MTH$SIN_R4, Vol 2, 19–6
on Alpha systems, Vol 1, 9–37 Multiple execution contexts, Vol 1, 2–17
on VAX systems, Vol 1, 9–35 Multiprocess applications
Mechanism arrays, format, Vol 1, 9–37 synchronizing, Vol 1, 6–18
Mechanism entry, in argument descriptions, Vol 2, Multiprocessor environment, Vol 1, 6–19
17–9 See also Synchronization
mechanism_args data type, Vol 2, B–14 scheduling, Vol 1, 6–18
Memory Multistreamed work load, Vol 1, 6–19
allocating algorithms, Vol 1, 14–7
allocating and freeing blocks, Vol 1, 14–1
allocating and freeing pages, Vol 1, 14–1 N
barriers, Vol 1, 6–16 Name Hidden attribute, Vol 2, 31–5
instructions, Vol 1, 6–16 Name services, Vol 2, 32–1, C–1
locking page into, Vol 1, 12–12, 13–13 Namespaces, listing information, Vol 2, C–13
reads and writes $name_G macro, Vol 2, A–6
on VAX systems, Vol 1, 6–4 $name_G macro call, Vol 2, A–7
reads and writes on Alpha systems, Vol 1, 6–5 $name_S macro, Vol 2, A–6
Memory fragmentation, Vol 1, 14–2 $name_S macro call, Vol 2, A–6
Memory management system services, Vol 1, NARGS keyword, Vol 2, A–4
12–3, 13–5 National Character Set (NCS) utility, Vol 1, 1–15
Memory-resident global sections, Vol 1, 12–26 Natural alignment, Vol 1, 15–2
Menus performance, Vol 1, 15–2
creating with SMG$ routines, Vol 2, 22–23 Network management, Vol 1, 1–5
reading, Vol 2, 22–25 No Access attribute, Vol 2, 31–5
Messages Null devices, Vol 2, 23–29
chaining, Vol 1, 9–53 null_arg data type, Vol 2, B–14
displaying, Vol 1, 9–50 Numeric time, Vol 2, 27–7
logging, Vol 1, 9–56
system, Vol 2, 20–10
Message text, specifying variables in, Vol 1, 9–60
O
Message utility (MESSAGE), Vol 1, 1–14, 1–19, Object files, Vol 1, 1–11
9–56 to 9–63 Object libraries, Vol 2, 26–2, 26–5
accessing message object module, Vol 1, 9–60 adding a module, Vol 2, 26–2
associating messages with exception conditions, creating, Vol 2, 26–2
Vol 1, 9–57 deleting a module, Vol 2, 26–2
compiling message file, Vol 1, 9–60 extracting a module, Vol 2, 26–2
creating a message object library, Vol 1, 9–60 including message object module, Vol 1, 9–60
.END directive, Vol 1, 9–59 listing modules, Vol 2, 26–2
.FACILITY directive, Vol 1, 9–58 replacing a module, Vol 2, 26–2
facility name, Vol 1, 9–58 Object-oriented programming, Vol 1, 1–11
facility number, Vol 1, 9–59 Objects
FAO parameters, Vol 1, 9–62 DECdns, Vol 2, C–4
/FAO_COUNT qualifier, Vol 1, 9–60 modifying, Vol 2, C–6
logging messages, Vol 1, 9–56 protected, Vol 2, 31–23
message object module, Vol 1, 9–60 octaword_signed data type, Vol 2, B–14
message text, Vol 1, 9–59 octaword_unsigned data type, Vol 2, B–14
message text variables, Vol 1, 9–60 Open standards, Vol 1, 1–2
modifying a message source file, Vol 1, 9–61 Open systems, Vol 1, 1–5
.SEVERITY directive, Vol 1, 9–59 Open systems environment, Vol 1, 1–5
source module, Vol 1, 9–58
.TITLE directive, Vol 1, 9–60

Index–13
OpenVMS Alpha operating systems, Vol 1, 1–4 Partial sections, Vol 1, 12–27
migrating to, Vol 1, 1–4 Pascal, Vol 1, 1–12
OpenVMS Alpha System-Code Debugger, Vol 1, data type declarations, Vol 2, B–38
1–13 implementation table, Vol 2, B–38
OpenVMS Cluster systems, ICC programming, Passing mechanisms, Vol 2, 17–9
Vol 1, 3–21 by descriptor, Vol 2, 18–16
OpenVMS Debugger (debugger), Vol 1, 1–13 code, Vol 2, 17–10
OpenVMS Debugger utility, Vol 1, 15–3 by reference, Vol 2, 18–14
alignment, Vol 1, 15–9 by value, Vol 2, 18–13
OpenVMS RMS for arrays, Vol 2, 18–18
See RMS for scalars, Vol 2, 18–18
OpenVMS systems for strings, Vol 2, 18–18
compatibility, Vol 1, 1–3 Pasteboards, Vol 2, 22–10
compliance with open standards, Vol 1, 1–2 creating, Vol 2, 22–11
configurations, Vol 1, 1–3 deleting, Vol 2, 22–11
debugger, Vol 1, 1–13 ID, Vol 2, 22–32
description, Vol 1, 1–2 sharing, Vol 2, 22–32
open systems capability, Vol 1, 1–5 Patch utility (PATCH), Vol 1, 1–15
software, Vol 1, 1–3 PATHWORKS, client/server environment, Vol 1,
system services, Vol 1, 1–17 1–7
OpenVMS usage entry, Vol 2, B–1 PCA (performance and coverage analyzer), Vol 1,
in argument descriptions, Vol 2, 17–6 15–10
alignment, Vol 1, 15–3
OpenVMS usage implementation table
PCBs (process control blocks), Vol 1, 2–21
See Implementation tables Performance, measurement routine, Vol 2, 24–17
OpenVMS utility routines, Vol 1, 1–18 Per Kernel Thread Stacks, Vol 1, 2–22
OPS5, Vol 1, 1–12 Per-process common areas, Vol 1, 3–6
Outer mode ASTs, Vol 1, 8–12 Persona, Vol 2, 31–19
Output formatting control routine, Vol 2, 24–20 Persona extensions, Vol 2, 31–22
Overview of the OpenVMS Operating System, Vol Per-thread security, Vol 2, 31–21
1, 1–2 Per-thread security model, Vol 2, 31–21
PFNs (page frame numbers), Vol 1, 13–5
P PHDs (process headers), Vol 1, 2–21
Physical device names, Vol 2, B–7
P0 space, Vol 1, 2–22
Physical I/Os
definition, Vol 1, 10–2
access checks, Vol 2, 23–6
P1 space, Vol 1, 2–22, 2–23
operations, Vol 2, 23–5
definition, Vol 1, 10–2
privilege, Vol 2, 23–3, 23–5, 23–6
Page access, Vol 2, B–15
Physical names, Vol 2, 23–27
Page faults, Vol 2, 27–18
PID (process identifier), non-existent process, Vol
Page frame sections, Vol 1, 12–26, 13–24
2, 23–12
Pagelets, Vol 1, 12–1
PID numbers, Vol 1, 4–3, 4–6
Pages, Vol 1, 12–2, 13–3
definition, Vol 1, 4–6, 4–9
copy-on-reference, Vol 1, 12–16, 13–16
referencing remote processes, Vol 1, 4–9
demand-zero, Vol 1, 12–16, 13–16
PL/I
locking into memory, Vol 1, 12–12, 13–13
Compaq PL/I for OpenVMS Alpha, Vol 1, 1–12
owner, Vol 1, 12–10, 13–10
data type declarations, Vol 2, B–42
ownership and protection, Vol 1, 12–10, 13–10
implementation table, Vol 2, B–42
Page table entries VAX PL/I, Vol 1, 1–12
See PTEs Platforms
page_protection data type, Vol 2, B–15 Alpha, Vol 1, 1–4
Paging file sections, Vol 1, 12–22, 13–20 VAX, Vol 1, 1–4
global, Vol 1, 12–21, 13–20 Pointers, 64-bit support, Vol 1, 11–28, 11–29
PALcode (privileged architecture library) code, Vol Portability, applications, Vol 1, 1–6
1, 6–16, 15–3 Portable applications, on VAX and Alpha
Parent lock, Vol 1, 7–16 platforms, Vol 1, 1–5

Index–14
Predefined logical name Processes (cont’d)
LNM$FILE_DEV, Vol 2, 32–8 modifying name, Vol 1, 4–41
Primary exception vector, Vol 1, 9–24 obtaining information about, Vol 1, 4–9
Printers example, Vol 1, 4–9
device widths, Vol 2, 22–6 processes on specific nodes, Vol 1, 4–21,
Private sections, definition, Vol 1, 12–13, 13–13 4–22
synchronously, Vol 1, 4–23
Privileged architecture library code
using LIB$GETJPI routine, Vol 1, 4–5
See PALcode using PIDs, Vol 1, 4–5, 4–9
Privileged shareable images using process name, Vol 1, 4–6, 4–9
creating, Vol 2, 30–1 using SYS$GETJPI system service, Vol 1,
definition, Vol 2, 30–1 4–5
Privileges using SYS$GETJPIW system service, Vol
BYPASS, Vol 2, 23–5 1, 4–5
defined by access mode, Vol 2, 20–2 one process, Vol 1, 4–9
I/O operations, Vol 2, 23–2 priority
logical I/Os, Vol 2, 23–4 to 23–6 modifying, Vol 1, 4–32
MOUNT, Vol 2, 23–4 privileges
physical I/Os, Vol 2, 23–3, 23–5, 23–6 setting, Vol 1, 4–31
SHARE, Vol 2, 23–4, 23–12 scheduling, Vol 1, 4–32
SS$_NOPRIV, Vol 1, 9–21 spawned, Vol 1, 2–1
SYSTEM, Vol 2, 23–5 subprocess, Vol 1, 2–1
system services, Vol 2, 20–2 suspending, Vol 1, 4–63, 4–67
Procedure call format, Vol 2, 17–3 swapping, Vol 1, 12–12, 13–12
Procedure calls, testing for successful completion, SYS$PROCESS_SCAN system service
Vol 2, 18–22, 20–9 item lists
procedure data type, Vol 2, B–15 using to specify selection criteria about
Procedures processes, Vol 1, 4–16, 4–20
function code, Vol 2, B–11 using with remote procedures, Vol 1,
operation, Vol 2, B–11 4–24
procedure value, Vol 2, 18–8 item-specific flags to control selection
representation, Vol 2, 18–8 information, Vol 1, 4–16
Procedure values, Vol 2, 18–8, B–15 search, Vol 1, 4–14
Process, directory tables, Vol 2, 32–3 termination mailboxes, Vol 1, 4–74
Process contexts wildcard search, Vol 1, 4–12
accessing, Vol 1, 4–42 to 4–58 Process Header (PHD), Vol 1, 2–21
reading, Vol 1, 4–43 to 4–45
Process identification numbers
using with $GETJPI system service, Vol 1, 4–9
See PID numbers
writing, Vol 1, 4–45 to 4–47
Processing, distributed, Vol 1, 1–5
Process controls, Vol 1, 4–1
Process logical name tables, Vol 2, 32–4
Processes
Process names
See also SYS$GETJPI system service
length of for remote processes, Vol 1, 4–6
See also SYS$PROCESS_SCAN system service obtain information about remote processes
communicating between, Vol 1, 3–7 example, Vol 1, 4–12
communicating within, Vol 1, 3–1 specifying for local processes, Vol 1, 4–6
using logical names, Vol 1, 3–2 specifying for remote processes, Vol 1, 4–6
using symbols, Vol 1, 3–5 using to obtain information about remote
creating processes, Vol 1, 4–6, 4–9, 4–20
restrictions, Vol 1, 4–3 Processors
deleting, Vol 1, 4–71, 4–74 Alpha, Vol 1, 1–3
detached, Vol 1, 2–1, 2–13 VAX, Vol 1, 1–3
disabling swap mode, Vol 1, 12–12, 13–12 Process-private space
disallowing swapping, Vol 1, 12–12, 13–12 definition, Vol 1, 10–2
execution, Vol 1, 4–63 Process rights lists, Vol 2, 31–1
hibernating, Vol 1, 4–63 Process searches, Vol 1, 4–9 to 4–23
identification, Vol 1, 4–3 obtaining information about, Vol 1, 4–9
lock information, Vol 1, 4–30 searching on all nodes, Vol 1, 4–22
modes of execution, Vol 1, 2–2 searching on specific nodes, Vol 1, 4–21

Index–15
Process searches (cont’d) Quotas, Vol 2, B–13
using item lists AST, Vol 2, 23–3
with remote procedures, Vol 1, 4–24 buffered I/O, Vol 2, 23–3
using item-specific flags to control selection buffered I/O byte count, Vol 2, 23–3
information, Vol 1, 4–16 default logical name table, Vol 2, 32–15
using SYS$PROCESS_SCAN system service direct I/O, Vol 2, 23–3
item list, Vol 1, 4–17 directory table, Vol 2, 32–15
using SYS$PROCESS_SCAN system service I/O operations, Vol 2, 23–2
item list to specify processes job logical name table, Vol 2, 32–15
example, Vol 1, 4–20 logical name tables, Vol 2, 32–15
using SYS$PROCESS_SCAN system service SS$_EXQUOTA condition value, Vol 1, 9–21
item list to specify selection criteria about system service resources, Vol 2, 20–2
processes, Vol 1, 4–20 user-defined logical name table, Vol 2, 32–16
using wildcard on local system, Vol 1, 4–12
Process structure, Vol 1, 2–19
process_id data type, Vol 2, B–15 R
process_name data type, Vol 2, B–15 RAB64 (64-bit record access blocks)
Production systems, OpenVMS capabilities, Vol 1, data structure, Vol 1, 11–14
1–5 macros, Vol 1, 11–16
Program decomposition, Vol 1, 6–19 RAB64$PQ_x fields, Vol 1, 11–15
Program execution RAB64$Q_x fields, Vol 1, 11–15
See also Synchronization RAB data type, Vol 2, B–16
specifying a time, Vol 1, 4–59, 4–60 RABs (record access blocks), Vol 2, 28–15, B–16
timed intervals, Vol 1, 4–61 Read and write operations, ordering, Vol 1, 6–4
Programming Read-modify-write operations, atomic, Vol 1, 6–5
modular techniques, Vol 1, 1–9 Record access blocks
software development tools, Vol 1, 1–9 See RABs
to standards, Vol 1, 1–9 Records, I/O, Vol 2, 28–12
Programming environment, Vol 1, 1–7 Records, RMS, Vol 1, 1–21
Programming examples, calling system services, Reentrant code, ASTs, Vol 1, 8–3
Vol 2, 20–11 Registers
Program regions, Vol 1, 12–6, 13–8 data, Vol 2, 17–5
Prompt for input, with LIB$GET_INPUT routine, for returns, Vol 2, 17–4, 17–12
Vol 2, 22–4 Register usage
Protection for Alpha, Vol 2, 18–2
by access mode, Vol 2, 20–2 for VAX, Vol 2, 18–1
devices, Vol 2, 23–5 /REPLACE qualifier
I/O operations, Vol 2, 23–2 LIBRARY command, Vol 2, 26–2
mailboxes, Vol 2, 23–4 Resource attributes, Vol 2, 31–5
volumes, Vol 2, 23–4 Resource granularity, in lock, Vol 1, 7–3
Protection, page, Vol 1, 12–10, 13–10 Resource quotas, system services, Vol 2, 20–2
Protection masks, Vol 2, 23–4 Resources
$PRTDEF macro, Vol 2, B–15 lock management concept, Vol 1, 7–2
PTEs (page table entries) name, Vol 1, 7–4
extended addresses, Vol 1, 13–5 Resource wait mode, system service, Vol 2, 20–6
Return address arrays, Vol 1, 12–8, 13–9
Q Return conditions, wait, Vol 2, 20–6
Return condition values, Vol 2, 19–6, 20–7
quadword_signed data type, Vol 2, B–15 Returns, Vol 2, 17–12
quadword_unsigned data type, Vol 2, B–15 call frame, Vol 2, 18–5
Queue access routines, Vol 2, 24–13 condition value, Vol 2, 18–22
Queue information, obtaining, Vol 2, 27–21 errors, Vol 2, 18–22
Queues, Vol 2, 24–12 function value, Vol 2, 18–22
lock management, Vol 1, 7–6 I/O status, Vol 2, B–12
self-relative, Vol 2, 24–12 in I/O status block, Vol 2, 17–12
Queuing ASTs, Vol 1, 8–2 in mailbox, Vol 2, 17–12
object, Vol 2, B–11
RTL routines, Vol 2, 19–6

Index–16
Returns (cont’d) Run-time library routines (cont’d)
signaled in register, Vol 2, 17–12 accessing operating system components, Vol 2,
system service condition value, Vol 2, 20–7 24–1
Returns heading, in routine documentation, Vol 2, accessing VAX instruction set, Vol 2, 24–9
17–4 calling, Vol 2, 19–1, 19–3
Return status, Vol 1, 9–21 entry point, Vol 2, 19–3, 19–4, 19–6, 20–4
from signal, Vol 1, 9–72 integer and floating-point, Vol 2, 24–12
Return symbols interaction with operating system, Vol 2, 24–1
for RTL routines, Vol 2, 19–6 jacket routine, Vol 2, 24–1
Rights databases, Vol 2, 31–1, 31–8, 31–16 manipulating character string, Vol 2, 24–14
adding to, Vol 2, 31–12 names, Vol 2, 19–3
default protection, Vol 2, 31–9 on Alpha systems, Vol 1, 9–17
elements of, Vol 2, 31–10 output formatting control, Vol 2, 24–20
holder record, Vol 2, 31–8 performance measurement, Vol 2, 24–17
identifier records, Vol 2, 31–8 queue access, Vol 2, 24–12
initializing, Vol 2, 31–9 return status, Vol 1, 9–21
keys, Vol 2, 31–9 system service access, Vol 2, 24–1
modifying, Vol 2, 31–13, 31–14, 31–16 variable-length bit field instruction, Vol 2,
Rights identifiers 24–10
See Identifiers
Rights lists S
process, Vol 2, 31–19
system, Vol 2, 31–19 S0 space, definition, Vol 1, 10–2
rights_holder data type, Vol 2, B–16 SCAN
rights_id data type, Vol 2, B–16 data type declarations, Vol 2, B–52
RISC architecture, Vol 1, 1–4 implementation table, Vol 2, B–52
RMS, Vol 1, 1–8, 1–20 Schedulers
callback, Vol 1, 2–18
See also RAB64
OpenVMS, Vol 1, 2–18
files and records, Vol 1, 1–21
POSIX Threads Library, Vol 1, 2–18
interface enhancements, Vol 1, 11–13
Scheduling, Vol 1, 2–20
opening file for mapping, Vol 1, 12–14, 13–14
Screen management, Vol 2, 22–9
routines, Vol 1, 1–21
utilities, Vol 1, 1–21 See also Key tables
RMS, structures, Vol 2, 28–15 See also Pasteboards
RMS files, Vol 1, 1–21 See also Video attributes
Routines See also Viewports
callable system, Vol 1, 1–15 See also Virtual displays
calling, Vol 2, 19–1 See also Virtual keyboards
high-performance sort, Vol 1, 1–19 deleting text, Vol 2, 22–23
how to call, Vol 2, 19–3 double-width characters, Vol 2, 22–20, 22–21
processwide resource allocation, Vol 2, 24–16 drawing lines, Vol 2, 22–22
RTL, Vol 1, 1–16 inserting characters, Vol 2, 22–20
variable-length bit field, Vol 2, 24–10 menus
RPG II creating, Vol 2, 22–23
data type declarations, Vol 2, B–50 reading, Vol 2, 22–25
implementation table, Vol 2, B–50 types of, Vol 2, 22–23
RTL jacket handler, Vol 1, 9–71 reading data, Vol 2, 22–24
RTL routines scrolling, Vol 2, 22–21
See Run-time library routines setting background color, Vol 2, 22–11
RTLs (run-time libraries) setting screen dimensions, Vol 2, 22–11
condition handling, Vol 1, 9–1 video attributes, Vol 2, 22–22
routines, Vol 1, 1–16 viewports, Vol 2, 22–19
Run-time libraries Scrolling instructions, Vol 2, 22–21
See RTLs Search lists, defining, Vol 2, 32–2
Run-time library routines Search operations, Vol 2, 31–16
accessing command language interpreter, Vol
2, 24–2

Index–17
Secondary exception vectors, Vol 1, 9–24 SMG$CHANGE_RENDITION routine, Vol 2,
Sections, Vol 1, 12–12, 13–13 22–17
characteristic, Vol 1, 12–15, 13–15 SMG$CHANGE_VIEWPORT routine, Vol 2,
creating, Vol 1, 12–13, 13–14 22–19
defining extent, Vol 1, 12–15, 13–15 SMG$CHANGE_VIRTUAL_DISPLAY routine, Vol
deleting, Vol 1, 12–25, 13–23; Vol 2, 28–11 2, 22–17
global, Vol 2, 26–9 SMG$CHECK_FOR_OCCLUSION routine, Vol 2,
global paging file, Vol 1, 12–21, 13–20 22–14
image, Vol 1, 12–26, 13–23 SMG$CREATE_KEY_TABLE routine, Vol 2,
mapping, Vol 1, 12–18, 13–18; Vol 2, 28–4 22–29
page frame, Vol 1, 12–26, 13–24 SMG$CREATE_MENU routine, Vol 2, 22–24
paging, Vol 1, 12–22, 12–23, 13–20, 13–21 SMG$CREATE_PASTEBOARD routine, Vol 2,
private, Vol 2, 28–6 22–10
releasing, Vol 1, 12–25, 13–23 SMG$CREATE_SUBPROCESS routine, Vol 2,
sharing data, Vol 1, 12–24, 13–22 22–18
unmapping, Vol 1, 12–25, 13–23 SMG$CREATE_VIEWPORT routine, Vol 2, 22–19
updating, Vol 2, 28–11 SMG$CREATE_VIRTUAL_DISPLAY routine, Vol
writing back, Vol 1, 12–25, 13–23 2, 22–10
section_id data type, Vol 2, B–16 SMG$CREATE_VIRTUAL_KEYBOARD routine,
section_name data type, Vol 2, B–16 Vol 2, 22–25
Security model, Vol 2, 31–21 SMG$DELETE_CHARS routine, Vol 2, 22–23
Security profiles SMG$DELETE_LINE routine, Vol 2, 22–23
displaying, Vol 2, 31–24 SMG$DELETE_MENU routine, Vol 2, 22–24
modifying, Vol 2, 31–24 SMG$DELETE_PASTEBOARD routine, Vol 2,
Segments, item lists, Vol 1, 11–5 22–11
Sequential files SMG$DELETE_SUBPROCESS routine, Vol 2,
creating, Vol 2, 28–12 22–18
updating, Vol 2, 28–13 SMG$DELETE_VIEWPORT routine, Vol 2, 22–19
Servers, Vol 1, 1–6 SMG$DELETE_VIRTUAL_DISPLAY routine, Vol
Service routines 2, 22–16
AST, Vol 1, 8–8 SMG$DRAW_CHARACTER routine, Vol 2, 22–22
SET BREAK debugger command, /HANDLER SMG$DRAW_CHAR routine, Vol 2, 22–20
qualifier, Vol 1, 9–70 SMG$DRAW_LINE routine, Vol 2, 22–22
SET DISPLAY command SMG$DRAW_RECTANGLE routine, Vol 2, 22–22
creating WSA pseudo workstation devices, Vol SMG$ENABLE_UNSOLICITED_INPUT routine,
2, 22–8 Vol 2, 22–36
.SEVERITY directive, Vol 1, 9–59 SMG$END_DISPLAY_UPDATE routine, Vol 2,
Shareable images, Vol 2, 26–3 22–31
privileged, Vol 2, 30–1 SMG$ERASE_CHARS routine, Vol 2, 22–23
Shareable logical names, interprocess SMG$ERASE_COLUMN routine, Vol 2, 22–23
communication, Vol 2, 32–16 SMG$ERASE_DISPLAY routine, Vol 2, 22–23
Shared data SMG$ERASE_LINE routine, Vol 2, 22–23
access, Vol 1, 8–3 SMG$ERASE_PASTEBOARD routine, Vol 2,
AST synchronization, Vol 1, 8–4 22–11
Shared files, Vol 2, 26–13 SMG$EXECUTE_COMMAND routine, Vol 2,
SHARE privilege, Vol 2, 23–4, 23–12 22–18
Sharing data, RMS shared files, Vol 2, 26–13 SMG$HOME_CURSOR routine, Vol 2, 22–19
Signal argument vectors, Vol 1, 9–28, 9–32, 9–63 SMG$INSERT_CHARS routine, Vol 2, 22–20
Signaling, Vol 1, 9–33 SMG$INSERT_LINE routine, Vol 2, 22–21
changing to return status, Vol 1, 9–72 SMG$LABEL_BORDER routine, Vol 2, 22–12
SMG$ADD_KEY_DEF routine, Vol 2, 22–29 SMG$LIST_PASTING_ORDER routine, Vol 2,
SMG$BEGIN_DISPLAY_UPDATE routine, Vol 2, 22–16
22–31 SMG$MOVE_TEXT routine, Vol 2, 22–17
SMG$CHANGE_PBD_CHARACTERISTICS SMG$MOVE_VIRTUAL_DISPLAY routine, Vol 2,
routine, Vol 2, 22–11 22–15

Index–18
SMG$PASTE_VIRTUAL_DISPLAY routine, Vol 2, SS$_ALIGN exception, Vol 1, 9–12
22–10 signal array format, Vol 1, 9–15
SMG$POP_VIRTUAL_DISPLAY routine, Vol 2, SS$_HPARITH exception, Vol 1, 9–12
22–32 signal array format, Vol 1, 9–13
SMG$PUT_CHARS routine, Vol 2, 22–20 Stack frames, Vol 2, 18–3
SMG$PUT_CHARS_HIGHWIDE routine, Vol 2, Stacks
22–20 for Alpha procedure calls, Vol 2, 18–5
SMG$PUT_CHARS_MULTI routine, Vol 2, 22–20 for VAX procedure calls, Vol 2, 18–3
SMG$PUT_CHARS_WIDE routine, Vol 2, 22–20 Stack usage, Vol 2, 18–3, 18–5
SMG$PUT_LINE routine, Vol 2, 22–21 Standards, open, Vol 1, 1–2
SMG$PUT_LINE_MULTI routine, Vol 2, 22–21 STARLET.OLB file, Vol 2, 26–2, 26–5
SMG$PUT_LINE_WIDE routine, Vol 2, 22–21 STARLET data structures and definitions
SMG$PUT_WITH_SCROLL routine, Vol 2, 22–21 for C programmers, Vol 2, 21–1
SMG$READ_COMPOSED_LINE routine, Vol 2, Store-conditional instructions, Vol 1, 6–8
22–29 Sublock, Vol 1, 7–16
SMG$READ_FROM_DISPLAY routine, Vol 2, Subprocesses, Vol 1, 2–1
22–25 connecting to using LIB$ATTACH routine, Vol
SMG$READ_KEYSTROKE routine, Vol 2, 22–24 2, 24–9
SMG$READ_STRING routine, Vol 2, 22–25 creating
SMG$REPASTE_VIRTUAL_DISPLAY routine, with LIB$SPAWN, Vol 1, 2–3
Vol 2, 22–15 with SMG$ routines, Vol 2, 22–18
SMG$RESTORE_PHYSICAL_SCREEN routine, with SYS$CREPRC, Vol 1, 2–6
Vol 2, 22–31 creation of using LIB$SPAWN routine, Vol 2,
SMG$RETURN_CURSOR_POS routine, Vol 2, 24–9
22–19 debugging, Vol 1, 2–15
SMG$SAVE_PHYSICAL_SCREEN routine, Vol 2, disk and directory default, Vol 1, 2–12
22–31 image, Vol 1, 2–12
SMG$SCROLL_DISPLAY_AREA routine, Vol 2, input, output, and error device, Vol 1, 2–7
22–21 priority setting, Vol 1, 4–32
SMG$SCROLL_VIEWPORT routine, Vol 2, 22–19 Subsystem attribute, Vol 2, 31–5
SMG$SELECT_FROM_MENU routine, Vol 2, Supervisor mode ASTs, Vol 1, 8–12
22–24 Supervisor stack, Vol 1, 2–22
SMG$SET_BROADCAST_TRAPPING routine, Vol Suspension, Vol 1, 4–63, 4–67
2, 22–43 compared with hibernation, Vol 1, 4–64
SMG$SET_CURSOR_ABS routine, Vol 2, 22–19 Swapping
SMG$SET_CURSOR_REL routine, Vol 2, 22–19 by suspension, Vol 1, 4–67
SMG$SET_DISPLAY_SCROLL_REGION routine, Symbolic codes, for condition values, Vol 2, 20–8
Vol 2, 22–21 Symbolic definition macros, Vol 2, A–4
SMG$SET_PHYSICAL_CURSOR routine, Vol 2, Symbolic names, for argument lists, Vol 2, A–4
22–19 Symbols
SMG$UNPASTE_VIRTUAL_DISPLAY routine, defining, Vol 2, 26–3
Vol 2, 22–16 global, Vol 2, 26–4
SMP (symmetric multiprocessing), Vol 1, 5–1 local, Vol 2, 26–4
goals, Vol 1, 5–2 referring to, Vol 2, 26–3
Software development life cycle, Vol 1, 1–9 storage, Vol 2, 26–3
Software development tools, Vol 1, 1–8 unresolved, Vol 2, 26–4
Software programs, developing, Vol 1, 1–7 Symmetric Multiprocessing
Sort/Merge utility, high-performance routines, Vol interrupt requests, Vol 1, 5–2
1, 1–19 tightly coupled, Vol 1, 5–1
Special modes for debugging, Vol 1, 1–14 Symmetric Multiprocessing (SMP), Vol 1, 5–1
Specifying access modes of logical names, Vol 2, Synchronization
32–10 asynchronous system traps, Vol 1, 8–1
Specifying attributes of logical names, Vol 2, definition of, Vol 1, 6–1
32–13 hardware-level, Vol 1, 6–7
SRM_CHECK tool inner mode, Vol 1, 6–17
location on kit, Vol 1, 6–9 passing control to another image, Vol 1, 4–67
using to analyze code, Vol 1, 6–9 software-level, Vol 1, 6–16
using detached processes, Vol 1, 4–59

Index–19
Synchronization (cont’d) SYS$DCLAST system service, example, Vol 1,
using events flags, Vol 1, 6–20 8–10
using process priority, Vol 1, 6–18 SYS$DCLCMH system service, Vol 1, 9–3
using spin locks, Vol 1, 6–19 SYS$DCLEXH system service, Vol 1, 9–75
using subprocesses, Vol 1, 4–59 SYS$DELETE_BUFOBJ system service, Vol 2,
Synchronous input/output, Vol 2, 23–19 23–49, 23–51
Synchronous system services, Vol 2, 20–5 SYS$DELPRC system service, Vol 1, 4–74
SYS$ABORT_TRANS system service, Vol 2, 29–2 SYS$DELTVA system service, Vol 2, 28–11
SYS$ABORT_TRANSW system service, Vol 2, SYS$DEQ system service, example, Vol 1, 7–19
29–2, 29–3 SYS$DGBLSC system service, Vol 1, 13–16
SYS$ADD_HOLDER system service, Vol 2, 31–12 SYS$DISMOU system service, Vol 2, 23–36
SYS$ADD_IDENT system service, Vol 2, 31–12 SYS$DLCEFC system service, Vol 1, 6–27
SYS$ADJWSL system service, Vol 1, 12–11, 13–11 SYS$DNS system service, Vol 2, C–1
SYS$ALLOC system service SYS$END_TRANS system service, Vol 2, 29–2
example, Vol 2, 23–33 SYS$END_TRANSW system service, Vol 2, 29–2,
SYS$ASCEFC system service, Vol 1, 6–25 29–3
SYS$ASCTIM system service, Vol 2, 27–6 SYS$ENQ system service, example, Vol 1, 7–11
example, Vol 2, 27–10 SYS$ERROR logical name, Vol 1, 2–7, 2–8, 2–10,
SYS$ASCTOID system service, Vol 2, 31–11 4–69, 9–42, 9–50, 9–55; Vol 2, 32–4
SYS$ASCUTC system service, Vol 2, 27–2 to 27–4 SYS$EXIT system service, Vol 1, 4–69
SYS$ASSIGN system service, Vol 2, 23–12 SYS$EXPREG system service, Vol 1, 12–6, 13–8
example, Vol 2, 23–11 example, Vol 1, 12–6, 13–8
SYS$BINTIM system service, Vol 2, 27–2 to 27–4, SYS$FAO system service, Vol 1, 9–42, 9–50, 9–55;
27–6 Vol 2, 27–2 to 27–4
SYS$BINUTC system service, Vol 2, 27–2 to 27–4 example, Vol 2, 23–38
SYS$BRKTHRU system service, Vol 2, 22–43 SYS$FIND_HELD system service, Vol 2, 31–13,
SYS$CANCEL system service 31–16
example, Vol 2, 23–26 SYS$FIND_HOLDER system service, Vol 2,
SYS$CANTIM system service, Vol 2, 27–13 31–13, 31–16
example, Vol 2, 27–16 SYS$FORCEX system service
SYS$CANWAK system service, Vol 2, 27–13, example, Vol 1, 4–70
27–17 SYS$FORMAT_ACL system service, Vol 2, 31–25,
SYS$CHECK_ACCESS system service, Vol 2, 31–26
31–29 SYS$GETDVI system service, Vol 2, 23–29
SYS$CHECK_PRIVILEGE system service, Vol 2, SYS$GETDVIW system service, Vol 2, 23–29
31–30 SYS$GETJPI system service, Vol 1, 4–5, 4–9
SYS$CHKPRO system service, Vol 2, 31–29 See also SYS$PROCESS_SCAN system service
SYS$CLREF system service, Vol 1, 6–31 AST in target process, Vol 1, 4–26
SYS$COMMAND logical name, Vol 2, 32–4 buffer, Vol 1, 4–24, 4–25
SYS$CPU_CAPABILITIES system service, Vol 1, control flags, Vol 1, 4–26
4–34 item list
SYS$CREATE system service, Vol 2, 28–10 specifying criteria to select processes
SYS$CREATE_BUFOBJ_64 system service, Vol 2, example, Vol 1, 4–20
23–49, 23–51 item-specific flags, Vol 1, 4–16
SYS$CREATE_RDB system service, Vol 2, 31–9 obtaining information about all processes on the
SYS$CREATE_USER_PROFILE system service, local system, Vol 1, 4–9 to 4–14
Vol 2, 31–29 obtaining information about one process, Vol 1,
SYS$CREMBX system service, Vol 1, 2–8, 3–9, 4–9
4–76 obtaining information with wildcard search
SYS$CREPRC system service, example, Vol 1, example, Vol 1, 4–13
2–12 packing information in buffers, Vol 1, 4–24,
SYS$CRETVA system service, Vol 1, 12–8, 13–9 4–25
SYS$CRMPSC system service, Vol 2, 28–4, 28–5 searching for processes on all nodes, Vol 1,
SYS$DACEFC system service, Vol 1, 6–27 4–22
SYS$DALLOC system service, Vol 2, 23–33 searching for processes on specific nodes, Vol 1,
SYS$DASSGN system service, Vol 2, 23–12, 28–11 4–21, 4–22
example, Vol 2, 23–24 searching for selected processes, Vol 1, 4–14
specifying buffer size, Vol 1, 4–24, 4–25

Index–20
SYS$GETJPI system service (cont’d) SYS$IO_PERFORM, Vol 2, 23–51
specifying criteria to select processes SYS$IO_SETUP, Vol 2, 23–51
example, Vol 1, 4–20 SYS$LANGUAGE logical name, Vol 2, 27–24
swapping processes, Vol 1, 4–26 SYS$LCKPAG system service, Vol 1, 12–12, 13–12
synchronizing calls, Vol 1, 4–21, 4–22, 4–23 SYS$LKWSET system service, Vol 1, 12–11,
using item lists, Vol 1, 4–16, 4–24 13–12
with remote procedures, Vol 1, 4–24 SYS$LOGIN logical name, Vol 1, 2–8
using multiple $PROCESS_SCAN service SYS$LOGIN_DEVICE logical name, Vol 1, 2–8
contexts, Vol 1, 4–23 SYS$MGBLSC system service, Vol 2, 26–9
using SYS$PROCESS_SCAN system service SYS$MOD_HOLDER system service, Vol 2, 31–14
item list to specify selection criteria about SYS$MOD_IDENT system service, Vol 2, 31–13
processes, Vol 1, 4–16, 4–20 SYS$MOUNT system service, Vol 2, 23–34
item-specific flags to control selection SYS$NUMTIM system service, Vol 2, 27–2 to
information, Vol 1, 4–16 27–4, 27–7
search, Vol 1, 4–14 SYS$NUMUTC system service, Vol 2, 27–2 to
using SYS$PROCESS_SCAN system service 27–4
item list to specify selection criteria about SYS$OPEN system service, Vol 2, 28–10
processes, Vol 1, 4–17 SYS$OUTPUT logical name, Vol 1, 2–3, 2–7, 2–8,
using wildcards, Vol 1, 4–9 to 4–14 4–69, 8–5, 9–42, 9–50, 9–55; Vol 2, 22–2,
example, Vol 1, 4–13 22–4, 22–6, 22–34, 24–18, 32–4, 32–17
using wildcards as pidadr, Vol 1, 4–9 default value, Vol 2, 22–3
SYS$GETLKI system service, Vol 1, 4–30 example, Vol 1, 2–4, 2–10; Vol 2, 22–7
SYS$GETMSG system service, Vol 1, 9–50 redefining value, Vol 2, 22–3
SYS$GETQUI system service, Vol 2, 27–21 using with LIB$GET_INPUT routine, Vol 2,
SYS$GETSYI system service, Vol 2, 27–21 22–4
SYS$GETTIM system service, Vol 2, 27–2 to 27–4, using with LIB$PUT_OUTPUT routine, Vol 2,
27–10 22–4
SYS$GETUTC system service, Vol 2, 27–2 to 27–4 SYS$PARSE_ACL system service, Vol 2, 31–25,
SYS$GET_ALIGN_FAULT_DATA system service, 31–26
Vol 1, 15–10 SYS$PERM_DIS_ALIGN_FAULT_REPORT
SYS$GET_SECURITY system service, Vol 2, system service, Vol 1, 15–10
31–25, 31–26 SYS$PERM_REPORT_ALIGN_FAULT system
SYS$GET_SYS_ALIGN_FAULT_DATA system service, Vol 1, 15–10
service, Vol 1, 15–11 SYS$PROCESS_AFFINITY system service, Vol 1,
SYS$GOTO_UNWIND system service, Vol 1, 4–36
9–45, 9–49 SYS$PROCESS_CAPABILITIES system service,
SYS$HIBER system service, Vol 1, 4–65 Vol 1, 4–34
example, Vol 1, 4–66 SYS$PROCESS_SCAN system service, Vol 1, 4–5,
SYS$IDTOASC system service, Vol 2, 31–11, 4–9
31–16 See also SYS$GETJPI system service
SYS$INIT_SYS_ALIGN_FAULT_REPORT system obtaining information about processes on nodes,
service, Vol 1, 15–11 Vol 1, 4–22 to 4–23
SYS$INIT_VOL system service, Vol 2, 23–36 obtaining information about processes on
example, Vol 2, 23–36 specific nodes, Vol 1, 4–21, 4–22
SYS$INPUT logical name, Vol 1, 2–3, 2–7, 2–8, searching nodes, Vol 1, 4–22
4–69, 8–5; Vol 2, 22–2, 22–4, 22–34, 26–7, searching on specific nodes, Vol 1, 4–21
32–4, 32–17 setting up multiple contexts, Vol 1, 4–23
default value, Vol 2, 22–3 termination mailboxes, Vol 2, 23–44
example, Vol 1, 2–4, 2–8, 2–10; Vol 2, 22–5, using item lists, Vol 1, 4–16 to 4–24
22–33, 24–4, 24–29 with remote procedures, Vol 1, 4–24
redefining value, Vol 2, 22–3 using item lists to specify selection criteria
using with LIB$GET_INPUT routine, Vol 2, about processes, Vol 1, 4–16, 4–17, 4–20
22–4 example, Vol 1, 4–20
using with LIB$PUT_OUTPUT routine, Vol 2, using item-specific flags to control selection
22–4 information, Vol 1, 4–16
SYS$IO_CLEANUP, Vol 2, 23–51 SYS$PURGWS system service, Vol 1, 13–12

Index–21
SYS$PUTMSG system service, Vol 1, 9–6, 9–42, SYS$ULWSET system service, Vol 1, 12–11,
9–50, 9–55 13–12
SYS$QIO system service, Vol 2, 23–12 SYS$UNWIND system service, Vol 1, 9–45, 9–47,
example, Vol 2, 23–13 9–49, 9–64, 9–67, 9–72
SYS$REM_HOLDER system service, Vol 2, 31–16 example, Vol 1, 9–48
SYS$REM_IDENT system service, Vol 2, 31–16 SYS$UPDSEC system service, Vol 2, 28–11
SYS$SCHDWK system service, Vol 2, 27–13, SYS$WAITFR system service, Vol 1, 6–29
27–16, 27–17 SYS$WAKE system service, Vol 1, 4–65
canceling, Vol 2, 27–17 example, Vol 1, 4–66
example, Vol 2, 27–17 SYS$WFLAND system service, Vol 1, 6–29
request, Vol 2, 27–16 SYS$WFLOR system service, Vol 1, 6–29
SYS$SCRATCH logical name, Vol 1, 2–8 SYSGEN parameter
SYS$SETEF system service, Vol 1, 6–31 MAXBOBMEN, Vol 2, 23–50
SYS$SETEXV system service, Vol 1, 9–24 MAXBOBS0S1, Vol 2, 23–50
example, Vol 1, 9–4 MAXBOBS2, Vol 2, 23–50
SYS$SETIME system service, Vol 2, 27–11 SYSMAN command, class_schedule, Vol 1, 4–37
SYS$SETIMR system service SYSPRV privilege, Vol 2, 23–5
example with ASTs, Vol 1, 8–7 System, directory table, Vol 2, 32–3
routines, Vol 2, 27–13 System clock, setting, Vol 2, 27–11
SYS$SETPRN system service, Vol 1, 4–41 System Dump Analyzer (SDA) utility, Vol 1, 1–15
SYS$SETPRT system service, Vol 1, 12–10 System information
SYS$SETPRV system service, Vol 1, 4–31 See Timers statistics
SYS$SETRWM system service, Vol 2, 23–2 System library, Vol 2, 20–1, A–1
SYS$SETSWM system service, Vol 1, 12–12, System logical name tables, Vol 2, 32–6
13–12 System macro library, default, Vol 2, 20–8
example, Vol 1, 12–12, 13–12 System management, Vol 1, 1–5
SYS$SET_IMPLICIT_AFFINITY system service, System messages, Vol 2, 20–10
Vol 1, 4–35 System objects, access, Vol 2, B–16
SYS$SET_RESOURCE_DOMAIN system service, System routine documentation, Vol 2, 17–1
Vol 1, 7–4 Arguments heading, Vol 2, 17–6
SYS$SET_SECURITY system service, Vol 2, access entry, Vol 2, 17–8
31–25, 31–26 mechanism entry, Vol 2, 17–9
SYS$STARLET_C.TLB OpenVMS usage entry, Vol 2, 17–6
adherence to conventions, Vol 2, 21–2 text entry, Vol 2, 17–10
functional equivalency to STARLETSD.TLB, type entry, Vol 2, 17–7
Vol 2, 21–1 Condition Values Returned heading, Vol 2,
impact on use of ‘‘variant_struct’’ and ‘‘variant_ 17–11
union’’, Vol 2, 21–1 returns, Vol 2, 17–11, 17–12
potential impact on LIB structures, Vol 2, 21–1 returns in I/O status block, Vol 2, 17–12
potential impact on RMS structures, Vol 2, returns in mailbox, Vol 2, 17–12
21–1 returns signaled, Vol 2, 17–12
providing .H files, Vol 2, 21–2 Format heading, Vol 2, 17–2
SYS$START_ALIGN_FAULT_REPORT system explanatory text, Vol 2, 17–4
service, Vol 1, 15–10 JSB call format, Vol 2, 17–4
SYS$START_TRANS system service, Vol 2, 29–2 procedure call format, Vol 2, 17–3
SYS$START_TRANSW system service, Vol 2, Returns heading, Vol 2, 17–4
29–2, 29–3 condition values, Vol 2, 17–4
SYS$STOP_ALIGN_FAULT_REPORT system System routine returns, register data, Vol 2, 17–5
service, Vol 1, 15–10 System routines
SYS$STOP_SYS_ALIGN_FAULT_REPORT system callable, Vol 1, 1–8
service, Vol 1, 15–11 system services
SYS$SYNCH system service, Vol 1, 6–29; Vol 2, asynchronous, Vol 1, 6–35
23–18, 23–19 synchronous, Vol 1, 6–35
SYS$TIMCON system service, Vol 2, 27–2 to 27–4 System routine template, understanding, Vol 2,
SYS$ULKPAG system service, Vol 1, 12–12, 17–1
13–12

Index–22
Systems Time (cont’d)
exception dispatcher, Vol 1, 9–24 numeric and ASCII, Vol 2, 27–7
Systems, mailbox, Vol 2, 23–43 setting system, Vol 2, 27–11
System service access, Vol 2, 24–1, 24–2 using system services, Vol 2, 27–2 to 27–4
System services Time, conversions, Vol 2, 27–2
calling, Vol 2, 20–1 Time, current, Vol 2, 27–9
C function prototypes, Vol 1, 11–11 Time conversions
executing formatting, Vol 2, 27–4
asynchronously, Vol 2, 20–5 Time format logical names, Vol 2, 27–30 to 27–31
synchronously, Vol 2, 20–5 Time manipulation
execution wait, Vol 2, 20–6 using LIB$ADDX routine, Vol 2, 27–7
initializing volumes, Vol 2, 23–36 using LIB$ADD_TIMES routine, Vol 2, 27–7
loading site-specific, Vol 2, 31–30 using LIB$DAY routine, Vol 2, 27–5
MACRO-32, Vol 1, 11–11 using LIB$MULTF_DELTA_TIME, Vol 2, 27–7
macros, Vol 2, 20–1, A–1 using LIB$MULT_DELTA_TIME routine, Vol
obtaining information about processes, Vol 1, 2, 27–7
4–5, 4–9 using LIB$ routines, Vol 2, 27–5 to 27–7
OpenVMS, Vol 1, 1–17 using LIB$SUBX routine, Vol 2, 27–7
privileges, Vol 2, 20–2 using LIB$SUB_TIMES routine, Vol 2, 27–7
resource wait, Vol 2, 20–6 Timer requests, Vol 2, 27–13
restrictions, Vol 2, 20–2 canceling, Vol 2, 27–16
return status, Vol 1, 9–21 Timers
testing for successful completion, Vol 2, 20–9 deallocating, Vol 2, 27–19
System space, definition, Vol 1, 10–2 initializing, Vol 2, 27–19
System timer obtaining statistics, Vol 2, 27–19
canceling, Vol 1, 4–63 statistics, Vol 2, 27–18
setting, Vol 1, 4–62 buffered input/output, Vol 2, 27–18
system_access_id data type, Vol 2, B–16 CPU time, Vol 2, 27–18
direct input/output, Vol 2, 27–18
elapsed time, Vol 2, 27–18
T page faults, Vol 2, 27–18
Tape volumes, mounting, Vol 2, 23–34 time_name data type, Vol 2, B–16
Terminal characteristics, Vol 2, 23–29 .TITLE directive, Vol 1, 9–60
Terminal echo, Vol 2, 22–40 Tools, alignment, Vol 1, 15–9
disabling, Vol 2, 22–41 Traceback handlers, Vol 1, 9–25
Terminal I/O, example, Vol 2, 23–24 Transaction processing, distributed environments,
Terminals, device widths, Vol 2, 22–6 Vol 1, 1–18
Terminal timeouts, Vol 2, 22–41 Transactions
Termination mailboxes, Vol 1, 4–74; Vol 2, 23–44 default, Vol 2, 29–3
Terminators programming, Vol 2, 29–1
See also I/O (input/output) transaction_id data type, Vol 2, B–16
echos, Vol 2, 22–25 Translating logical names, Vol 2, 32–11
file, Vol 2, 23–31 TRM$M_TM_ESCAPE routine, Vol 2, 22–26
record, Vol 2, 23–31 TRM$M_TM_NOECHO routine, Vol 2, 22–26
Text processors, Vol 1, 1–10 TRM$M_TM_NOTRMECHO routine, Vol 2, 22–25
Thread manager, Vol 1, 2–18 TRM$M_TM_PURGE routine, Vol 2, 22–26
Threads, Vol 1, 9–48 Type-ahead buffers, Vol 2, 22–39
Compaq POSIX Threads Library services, Vol Type entry, in argument descriptions, Vol 2, 17–7
1, 1–15
Time U
See also Current time
absolute, Vol 2, 27–1 UFO (user-file open), Vol 2, 28–10
64-bit system format, Vol 2, 27–1 See also User-open routine
128-bit system format, Vol 2, 27–36 uic data type, Vol 2, B–17
converting ASCII to binary, Vol 2, 27–6 UICs (user identification codes), Vol 2, B–16, B–17
delta, Vol 2, 27–1 Unalignment, Vol 1, 15–1
getting current system, Vol 2, 27–10
internal format, Vol 2, 27–2

Index–23
Uniprocessor operations, Vol 1, 6–5 VAX FORTRAN
Unwind condition handlers, Vol 1, 9–67 See Fortran
Upcalls, Vol 1, 2–18 VAX instruction set, accessing through run-time
User capabilities, Vol 1, 4–33 library, Vol 2, 24–9
User-defined condition values VAX language implementation tables
signaling, Vol 1, 9–61 See Implementation tables
User-defined logical name tables, Vol 2, 32–8,
VAX MACRO
32–16
See MACRO
User-file open
VAX Pascal
See UFO See Pascal
User identification codes VAX PL/I
See UICs See PL/I
User interfaces VAX platforms, Vol 1, 1–4
programming tools, Vol 1, 1–19 VAX processors, Vol 1, 1–3
User mode ASTs, Vol 1, 8–12
VAX RPG II
User-open routines, Vol 2, 28–15
See RPG II
User privileges, Vol 2, 20–2
VAX SCAN
User procedures, Vol 2, 19–1
See SCAN
User stacks, Vol 1, 2–22
vector_byte_signed data type, Vol 2, B–17
user_arg data type, Vol 2, B–17
vector_byte_unsigned data type, Vol 2, B–17
Using impersonation system services, Vol 2, 31–20
vector_longword_signed data type, Vol 2, B–17
UTC (Coordinated Universal Time)
vector_longword_unsigned data type, Vol 2, B–17
system services, Vol 2, 27–37
vector_quadword_signed data type, Vol 2, B–17
Utility routines, OpenVMS, Vol 1, 1–18
vector_quadword_unsigned data type, Vol 2, B–17
vector_word_signed data type, Vol 2, B–17
V vector_word_unsigned data type, Vol 2, B–17
Variable-length bit field routine, Vol 2, 24–10 VEST (VAX Environment Software Translator)
Variable-size stack frames, Vol 2, 18–6 alignment, Vol 1, 15–8
‘‘variant_struct’’, impact of SYS$STARLET_C.TLB, Video attributes, Vol 2, 22–12, 22–18, 22–22
Vol 2, 21–2 current, Vol 2, 22–18
‘‘variant_union’’, impact of SYS$STARLET_C.TLB, default, Vol 2, 22–18
Vol 2, 21–2 vi editor, Vol 1, 1–10
varying_arg data type, Vol 2, B–17 Viewports, Vol 2, 22–19
VAX, architecture, Vol 1, 1–4 Virtual address space, Vol 1, 12–2, 12–7, 13–1,
13–8
VAX Ada
increasing and decreasing, Vol 1, 12–6, 13–8
See Ada
mapping section of, Vol 1, 12–19, 13–18
VAX APL
specifying array, Vol 1, 12–8, 13–10
See APL
Virtual displays, Vol 2, 22–12
VAX BASIC
See BASIC See also Viewports
VAX BLISS checking occlusion, Vol 2, 22–14
See BLISS creating, Vol 2, 22–12
VAX C creating a subprocess from, Vol 2, 22–18
See C cursor movement, Vol 2, 22–21
VAXCDEF.TLB deleting, Vol 2, 22–16
replaced by new files, Vol 2, 21–1 deleting text, Vol 2, 22–23
drawing lines, Vol 2, 22–22
VAX COBOL
erasing, Vol 2, 22–16
See COBOL
ID, Vol 2, 22–12, 22–33
VAX data types
inserting text, Vol 2, 22–20, 22–21
See Data types list pasting order of, Vol 2, 22–16
VAX DIBOL, Vol 1, 1–11 logical cursor position, Vol 2, 22–19
VAXELN toolkit, Vol 1, 1–20 modifying, Vol 2, 22–17
VAX Environment Software Translator obtaining the pasting order, Vol 2, 22–16
See VEST overwriting text, Vol 2, 22–20, 22–21
pasting, Vol 2, 22–13
physical cursor position, Vol 2, 22–19

Index–24
Virtual displays (cont’d) Web-enabling tools, Vol 1, 1–8
popping, Vol 2, 22–16 Wildcard searches
reading data from, Vol 2, 22–24 obtaining information about processes
rearranging, Vol 2, 22–15 example, Vol 1, 4–13
scrolling, Vol 2, 22–21 using SYS$GETJPI system service, Vol 1, 4–12
sharing, Vol 2, 22–33 word_signed data type, Vol 2, B–17
specifying double-size characters, Vol 2, 22–21 word_unsigned data type, Vol 2, B–17
specifying video attributes, Vol 2, 22–12 Working sets
viewports, Vol 2, 22–19 adjusting size, Vol 1, 12–11, 13–11
writing double-width characters, Vol 2, 22–20 paging, Vol 1, 12–10, 13–11
writing text to, Vol 2, 22–19 Write-back sections, Vol 1, 12–25, 13–23
Virtual I/O, Vol 2, 23–6 Writing a condition handler
Virtual keyboards example, Vol 1, 9–65
reading data from, Vol 2, 22–24, 22–25
Virtual page size, Vol 1, 13–1
Volume protection, Vol 2, 23–4 Z
Volumes Zones, Vol 1, 14–6 to 14–14
initializing allocation algorithm, Vol 1, 14–14
within a program, Vol 2, 23–36 attributes, Vol 1, 14–8
example, Vol 2, 23–36 creating, Vol 1, 14–7
mounting, Vol 2, 23–34 default, Vol 1, 14–12
deleting, Vol 1, 14–7
W identifier, Vol 1, 14–12
resetting, Vol 1, 14–13
WAIT form services, Vol 1, 6–29 user-created, Vol 1, 14–6
Wait mode, system service, Vol 2, 20–6
Wakeup requests, scheduling, Vol 2, 27–16

Index–25

You might also like