Guide To VAX SCAN (AI FU79B TE, V1 2)
User Manual: Pdf
Open the PDF directly: View PDF
.
Page Count: 400
| Download | |
| Open PDF In Browser | View PDF |
Guide to VAX SCAN Order Number: AA–FU79C–TE November 1989 This manual describes the language elements, programming constructs, and features of the VAX SCAN language. Revision/Update Information: This revised document supersedes Guide to VAX SCAN (Order number AI-FU79B-TE). Operating System and Version: VAX/VMS Version 5.0 or higher; Software Version: digital equipment corporation maynard, massachusetts VAX SCAN Version 1.2 First Printing, September 1985 Revised, December 1986 Revised, November 1989 The information in this document is subject to change without notice and should not be construed as a commitment by Digital Equipment Corporation. Digital Equipment Corporation assumes no responsibility for any errors that may appear in this document. The software described in this document is furnished under a license and may be used or copied only in accordance with the terms of such license. No responsibility is assumed for the use or reliability of software on equipment that is not supplied by Digital Equipment Corporation or its affiliated companies. Restricted Rights: Use, duplication, or disclosure by the U.S. Government is subject to restrictions as set forth in subparagraph (c) (1) (ii) of the Rights in Technical Data and Computer Software clause at DFARS 252.227-7013. Copyright ©1985, 1986, 1989 by Digital Equipment Corporation All Rights Reserved. Printed in U.S.A. The postpaid Reader’s Comments forms at the end of this document request the user’s critical evaluation to assist in preparing future documentation. The following are trademarks of Digital Equipment Corporation: DEC DEC/CMS DEC/MMS DECnet DECsystem–10 DECSYSTEM–20 DECUS DECwriter DIBOL EduSystem IAS MASSBUS PDP PDT RSTS RSX UNIBUS VAX VAXcluster VMS VT ™ ZK3379 Contents PREFACE ix CHAPTER 1 INTRODUCTION TO VAX SCAN 1–1 1.1 UNDERSTANDING VAX SCAN 1–1 1.2 USING VAX SCAN 1.2.1 Creating a Pattern 1.2.2 Creating Replacement Text 1.2.2.1 Capturing Matched Text • 1–8 1.2.2.2 Constructing Replacement Text • 1–10 1.2.2.3 Reporting Replacement Text • 1–11 1–2 1–5 1–8 1.3 GETTING 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.4 PROCESSING TEXT WITH VAX SCAN 1.4.1 Filters 1.4.2 Translators 1.4.3 Extractors/Analyzers 1.4.4 Preprocessors STARTED WITH VAX SCAN Flow of Control in a VAX SCAN Program Token Building Picture Matching Input and Output Stream Forms VAX SCAN Variables VAX SCAN Trees 1–11 1–14 1–17 1–18 1–19 1–20 1–23 1–27 1–27 1–27 1–28 1–29 iii CHAPTER 2 VAX SCAN APPLICATION DEVELOPMENT 2.1 CREATING AND EDITING VAX SCAN PROGRAMS 2.1.1 VAX Text Processing Utility 2.1.2 VAX Language-Sensitive Editor 2–1 2–1 2–2 2.2 COMPILING, LINKING, AND RUNNING PROGRAMS 2.2.1 SCAN Command 2.2.2 LINK Command 2.2.3 RUN Command 2–3 2–4 2–4 2–5 CHAPTER 3 ELEMENTS OF THE VAX SCAN LANGUAGE iv 2–1 3–1 3.1 PROGRAM FORM 3–1 3.2 CHARACTER SET 3–2 3.3 NAMES 3–3 3.4 KEYWORDS 3–3 3.5 LITERALS 3.5.1 3.5.2 3.5.3 3.5.4 3–5 3–5 3–6 3–6 3–6 Integer Literals Boolean Literals Pointer and Treeptr Literals String Literals 3.5.4.1 Quoted String Literal • 3–7 3.5.4.2 Control Character Literals • 3–7 3.5.4.3 Special Character Literals • 3–9 3.5.4.4 Hexadecimal Character Literals • 3–10 3.6 OPERATORS AND DELIMITERS 3–10 3.7 SPACES, TABS, COMMENTS, AND FORM FEEDS 3–12 CHAPTER 4 PROGRAM STRUCTURE 4–1 4.1 STATEMENT STRUCTURE 4–2 4.2 MACRO STRUCTURE 4–4 4.3 PROCEDURE STRUCTURE 4–6 4.4 MODULE STRUCTURE 4–7 4.5 SCOPE 4–9 CHAPTER 5 PICTURE-MATCHING STATEMENTS 5–1 5.1 SET STATEMENT 5–1 5.2 TOKEN STATEMENT 5.2.1 TOKEN Operators 5.2.2 TOKEN Attributes 5.2.3 Interaction of Tokens 5–3 5–5 5–8 5–9 5.3 GROUP STATEMENT 5–10 5.4 MACROS 5.4.1 Macro Picture 5.4.1.1 Alternation Operator ( | ) • 5–13 5.4.1.2 Concatenation • 5–14 5.4.1.3 Repetition Operator ( . . . ) • 5–15 5.4.1.4 List Operator ( \ ) • 5–15 5.4.1.5 Optional Brackets ( [ ] ) • 5–16 5.4.1.6 Operator Precedence • 5–16 5.4.2 TRIGGER and SYNTAX Attributes 5.4.3 EXPOSE Attribute 5.4.4 Picture Variables 5–12 5–13 5–16 5–18 5–20 v 5.4.5 5.4.6 5.4.7 Interaction of Macros 5.4.5.1 Criteria for Activating Trigger Macros • 5–24 5.4.5.2 Failure of Picture Matching • 5–26 Error Recovery 5.4.6.1 Error Recovery Procedures • 5–29 5.4.6.2 Error Recovery Hints • 5–31 Macro Body CHAPTER 6 INPUT AND OUTPUT STREAMS 5–27 5–32 6–1 6.1 INPUT AND OUTPUT STREAM FORM 6.1.1 File as Input or Output Stream 6.1.2 String as Input or Output Stream 6.1.3 Procedure as Input or Output Stream 6–1 6–2 6–2 6–3 6.2 VAX SCAN LITERALS IN THE INPUT STREAM 6–5 6.3 VAX SCAN LITERALS IN THE OUTPUT STREAM 6–6 6.4 REDEFINING THE VAX SCAN LITERALS 6–9 6.5 THE WIDTH OF THE INPUT AND OUTPUT STREAMS 6–9 CHAPTER 7 VARIABLES vi 5–23 7–1 7.1 INTEGER VARIABLES 7–2 7.2 BOOLEAN VARIABLES 7–2 7.3 STRING VARIABLES 7–3 7.4 FILL VARIABLES 7–4 7.5 POINTER VARIABLES 7–5 7.6 TREE VARIABLES 7–5 7.7 TREEPTR VARIABLES 7–9 7.8 RECORD VARIABLES 7–14 7.9 OVERLAY VARIABLES 7–17 7.10 FILE VARIABLES 7–20 CHAPTER 8 DECLARATION OF VARIABLES 8–1 8.1 SPECIFICATION OF VARIABLE TYPE 8–1 8.2 DECLARE STATEMENT 8–3 8.3 TYPE STATEMENT 8–4 8.4 CONSTANT STATEMENT 8–7 CHAPTER 9 PROCEDURES 9–1 9.1 PROCEDURE DECLARATION 9.1.1 Parameters 9.1.2 Passing Mechanisms 9–1 9–4 9–6 9.2 EXTERNAL PROCEDURE DECLARATION 9–7 9.3 FORWARD PROCEDURE DECLARATION 9–9 vii CHAPTER 10 EXPRESSIONS 10.1 OPERATORS 10.1.1 Substring Operator 10.1.2 Arithmetic Operators 10.1.3 Concatenation 10.1.4 Relational Operators 10.1.5 Logical Operators 10.2 REFERENCES 10.2.1 Scalar Reference 10.2.2 Record Reference 10.2.3 Tree Reference 10.2.4 Function Reference 10.2.5 Built-In Function Reference 10.2.6 Pointer Reference 10–11 10–12 10–12 10–13 10–15 10–16 10–17 10.3 EXPRESSION OPERATOR PRECEDENCE 10–19 CHAPTER 11 BUILT-IN FACILITIES viii 10–1 10–2 10–4 10–5 10–6 10–7 10–9 11–1 11.1 BUILT-IN TOKENS 11.1.1 ANY Built-In Token 11.1.2 COLUMN Built-In Token 11.1.3 FIND Built-In Token 11.1.4 INSTANCE Built-In Token 11.1.5 NOTANY Built-In Token 11.1.6 SEQUENCE Built-In Token 11.1.7 SKIP Built-In Token 11–1 11–2 11–2 11–3 11–3 11–4 11–5 11–5 11.2 BUILT-IN FUNCTIONS 11–6 11.2.1 11.2.2 11.2.3 11.2.4 11.2.5 Tree Traversing Built-In Functions 11.2.1.1 TREEPTR Built-In Function • 11–9 11.2.1.2 EXISTS Built-In Function • 11–10 11.2.1.3 FIRST Built-In Function • 11–11 11.2.1.4 LAST Built-In Function • 11–12 11.2.1.5 NEXT Built-In Function • 11–13 11.2.1.6 PRIOR Built-In Function • 11–13 11.2.1.7 VALUE Built-In Function • 11–15 11.2.1.8 VALUEPTR Built-In Function • 11–15 11.2.1.9 SUBSCRIPT Built-In Function • 11–16 String Built-In Functions 11.2.2.1 INDEX Built-In Function • 11–18 11.2.2.2 LENGTH Built-In Function • 11–19 11.2.2.3 LOWER Built-In Function • 11–20 11.2.2.4 UPPER Built-In Function • 11–20 11.2.2.5 MEMBER Built-In Function • 11–21 11.2.2.6 TRIM Built-In Function • 11–22 Conversion Built-In Functions 11.2.3.1 INTEGER Built-In Function • 11–23 11.2.3.2 STRING Built-In Function • 11–24 11.2.3.3 POINTER Built-In Function • 11–25 Mathematical Built-In Functions 11.2.4.1 ABS Built-In Function • 11–26 11.2.4.2 MAX Built-In Function • 11–27 11.2.4.3 MIN Built-In Function • 11–27 11.2.4.4 MOD Built-In Function • 11–28 Other Built-In Functions 11.2.5.1 ENDFILE Built-In Function • 11–29 11.2.5.2 TIME Built-In Function • 11–30 CHAPTER 12 EXECUTABLE STATEMENTS 11–7 11–17 11–23 11–26 11–29 12–1 12.1 LABELS 12–2 12.2 ASSIGNMENT STATEMENTS 12.2.1 Assigning to a Substring 12.2.2 Assigning to a Record or Overlay (Record Compatibility) 12–3 12–5 CALL STATEMENT 12–9 12.3 12–7 ix x 12.4 GOTO STATEMENT 12–10 12.5 CASE STATEMENT 12–11 12.6 IF STATEMENT 12–13 12.7 WHILE STATEMENT 12–15 12.8 FOR STATEMENT 12–16 12.9 RETURN STATEMENT 12–17 12.10 START SCAN STATEMENT 12.10.1 INPUT FILE Clause 12.10.2 INPUT PROCEDURE Clause 12.10.3 INPUT STRING Clause 12.10.4 OUTPUT FILE Clause 12.10.5 OUTPUT PROCEDURE Clause 12.10.6 OUTPUT STRING Clause 12.10.7 INPUT WIDTH Clause 12.10.8 OUTPUT WIDTH Clause 12.10.9 DATA STACK Clause 12–18 12–20 12–21 12–23 12–23 12–24 12–25 12–26 12–26 12–27 12.11 STOP SCAN STATEMENT 12–28 12.12 ANSWER STATEMENT 12.12.1 TRIGGER Attribute 12–29 12–30 12.13 FAIL STATEMENT 12–33 12.14 OPEN STATEMENT 12–33 12.15 CLOSE STATEMENT 12–35 12.16 READ STATEMENT 12–35 12.17 WRITE STATEMENT 12–37 12.18 ALLOCATE STATEMENT 12–38 12.19 FREE STATEMENT 12–40 12.20 PRUNE STATEMENT 12–41 CHAPTER 13 DIRECTIVE STATEMENTS 13–1 13.1 LIST DIRECTIVE 13–1 13.2 INCLUDE DIRECTIVE 13–3 13.3 REDEFINE DIRECTIVE 13–3 CHAPTER 14 VAX/VMS RUN-TIME LIBRARY ROUTINES AND SYSTEM SERVICES 14–1 14.1 VAX/VMS RUN-TIME LIBRARY ROUTINES 14–2 14.2 SYSTEM SERVICES ROUTINES 14–2 14.3 CALLING 14.3.1 14.3.2 14.3.3 14.3.4 14.3.5 SYSTEM ROUTINES FROM VAX SCAN Determine the Type of Call (Procedure or Function) Declare the Arguments Declare the System Routine Include Symbol Definitions Call the Routine or Service 14.3.5.1 Calling a System Routine in a Function Call • 14–12 14.3.5.2 Calling a System Routine in a Subroutine Call • 14–15 14–3 14–4 14–5 14–10 14–11 14–12 xi 14.3.6 14.3.7 Check the Condition Value Locate the Result 14.3.7.1 Function Results • 14–17 14.3.7.2 Subroutine Results • 14–18 14.4 EXAMPLES 14–18 14.5 FOR ADDITIONAL INFORMATION 14–24 CHAPTER 15 ERROR MESSAGES AND HELP 15–1 15.1 ERROR MESSAGES 15–1 15.2 ACCESSING VAX SCAN HELP 15–1 CHAPTER 16 DEBUGGING VAX SCAN PROGRAMS 16–1 16.1 ACTIVATING THE VAX/VMS DEBUGGER 16–1 16.2 VAX SCAN SYMBOLIC DEBUGGING 16.2.1 VAX SCAN Elements Available for Debugging 16.2.1.1 Names • 16–3 16.2.1.2 Line Numbers • 16–3 16.2.2 Controlling Program Execution 16.2.2.1 Breakpoints and Tracepoints • 16–4 16.2.2.2 Break on Event and Trace on Event • 16–5 16.2.2.3 Watchpoints • 16–6 16.2.3 Examining and Depositing 16.2.3.1 STRING Variables • 16–7 16.2.3.2 FILL Variables • 16–7 16.2.3.3 POINTER Variables • 16–7 16.2.3.4 TREE and TREEPTR Variables • 16–8 16.2.3.5 RECORD and OVERLAY Variables • 16–11 16–2 16–3 16.3 xii 14–15 14–17 SAMPLE DEBUGGING SESSION 16–4 16–6 16–11 APPENDIX A VAX SCAN CONTROL CHARACTERS A–1 APPENDIX B SYNTAX DIAGRAMS B–1 B.1 EXECUTABLE STATEMENTS B.1.1 ALLOCATE-statement B.1.2 ANSWER-statement B.1.3 Assignment-statement B.1.4 CALL-statement B.1.5 CASE-statement B.1.6 CLOSE-statement B.1.7 FAIL-statement B.1.8 FOR-statement B.1.9 FREE-statement B.1.10 GOTO-statement B.1.11 IF-statement B.1.12 OPEN-statement B.1.13 PRUNE-statement B.1.14 READ-statement B.1.15 RETURN-statement B.1.16 START-SCAN-statement B.1.17 STOP-SCAN-statement B.1.18 WHILE-statement B.1.19 WRITE-statement B–1 B–2 B–2 B–2 B–3 B–4 B–4 B–4 B–5 B–5 B–5 B–5 B–6 B–6 B–6 B–6 B–7 B–7 B–7 B–7 B.2 TYPES B.2.1 B.2.2 B.2.3 B–8 B–8 B–8 B–9 B.3 OVERLAY-type RECORD-type TREE-type DECLARATIONS B.3.1 CONSTANT-declaration B.3.2 EXTERNAL-declaration B.3.3 FORWARD-declaration B.3.4 GROUP-declaration B.3.5 MACRO-declaration B.3.6 MODULE-declaration B–9 B–9 B–9 B–10 B–10 B–11 B–12 xiii B.3.7 B.3.8 B.3.9 B.3.10 B.3.11 B.4 PROCEDURE-declaration SET-declaration TOKEN-declaration TYPE-declaration Variable-declaration DIRECTIVES B.4.1 INCLUDE-directive B.4.2 LIST-directive B.4.3 REDEFINE-directive B–13 B–14 B–14 B–15 B–15 B–15 B–15 B–16 B–16 APPENDIX C VAX SCAN KEYWORDS C–1 APPENDIX D VAX SCAN FILE SUPPORT D–1 APPENDIX E DEC MULTINATIONAL CHARACTER SET E–1 APPENDIX F OPTIONAL PROGRAMMING PRODUCTIVITY TOOLS F–1 xiv F.1 GETTING STARTED WITH THE VAX LANGUAGE-SENSITIVE EDITOR F–2 F.2 COMMANDS FOR TOKENS AND PLACEHOLDERS F–2 F.3 CREATING AND EDITING CODE F.3.1 Editing a New File F.3.2 Editing an Existing File F.3.3 Defining Aliases F.3.4 Using the Compiler Interface F.3.4.1 The COMPILE Command • F–7 F.3.4.2 The REVIEW Command • F–8 F.3.4.3 REVIEW Mode • F–9 F.3.5 VAXLSE Command Line F.3.6 Editor Command Line Qualifiers F–4 F–4 F–6 F–6 F–7 F–10 F–11 F.3.7 Keypad Functions F–11 F.4 USING THE VAX LANGUAGE-SENSITIVE EDITOR WITH VAX SCAN F–20 F.5 SAMPLE EDITING SESSION F.5.1 Module and Token Declarations F.5.2 Macros F.5.3 Creating a MAIN Procedure F.5.4 Creating a Function F.5.5 Variable Declarations F.5.6 Control Structures F–20 F–21 F–25 F–29 F–34 F–39 F–41 F.6 VAX LANGUAGE-SENSITIVE EDITOR TOKENS AND PLACEHOLDERS FOR VAX SCAN F–48 INDEX Index–1 EXAMPLES 1–1 Search and Replace Macro 1–3 1–2 CHANGE_TIMES Program 1–15 1–3 Variable Declaration Placement 1–21 1–4 Declaring a TREE Structure 1–25 1–5 Assigning TREE Values 1–25 2–1 VAX Language-Sensitive Editor Program 2–3 4–1 VAX SCAN Macro 4–5 4–2 VAX SCAN Procedure 4–7 4–3 VAX SCAN Module 4–4 Scope 4–9 4–10 5–1 SET Declarations 5–2 5–2 TOKEN Declarations 5–3 5–3 Alternation 5–14 5–4 Concatenation 5–14 5–5 Repetition 5–15 5–6 List 5–16 xv xvi 5–7 MACRO Interaction 5–19 5–8 Picture Variables 5–21 5–9 Tree Subscripts and Repetition 5–21 5–10 List Operator 5–22 5–11 MACRO Scope 5–25 5–12 Error Context 5–27 5–13 Error Recovery Procedure 5–29 5–14 Error Recovery Packet 5–30 6–1 String as Input Stream 6–3 6–2 Procedure as Input Stream 6–4 6–3 Special VAX SCAN Characters in Input Stream 6–6 6–4 Linked List in Input Stream 7–1 Integer Variable 7–2 7–2 Boolean Variable 7–3 7–3 String Variables 7–4 7–4 Fill Variable 7–5 7–5 Pointer Variables 7–6 Tree Traversing 7–11 7–7 Tree Traversing Using TREEPTR 7–13 7–8 Record Variables 7–15 7–9 Record Variable Component Names 7–16 7–10 Comparison of a Record Variable with an Overlay Variable 7–18 7–11 Use of Overlay Variables 7–19 7–12 File Variables 7–20 6–11 7–6 8–1 Variable Declarations 8–5 8–2 User-Defined Type Declaration 8–5 8–3 User-Defined Variable Type 8–6 8–4 Multiple Reference of User-Defined Type 8–7 8–5 Local Constant Declarations 8–8 8–6 Global Constant Declarations 8–8 8–7 External Constant Declarations 8–8 8–8 Naming Literal Constants 8–9 9–1 Procedure Subroutine 9–3 9–2 Procedure Function 9–3 9–3 Procedure Invocation 9–4 9–4 Parameter Passing in Procedures 9–4 9–5 EXTERNAL PROCEDURE Declarations 9–6 FORWARD PROCEDURE Declaration 10–1 Creating New Values with Expressions 10–2 Logical Operators 10–10 10–3 Logical Operators Used with Integer Operands 10–10 10–4 Variable References 10–11 10–5 Scalar Variable Reference 10–12 10–6 Record Reference 10–13 10–7 Tree Reference 10–14 10–8 Passing a Tree as a Parameter 10–15 10–9 Function Reference 10–16 10–10 Built-In Function Reference 10–17 10–11 Pointer Reference 10–17 10–18 9–8 9–10 10–1 10–12 Pointer to Dynamically Allocated Storage 11–1 Use of FIND Built-In Token 11–3 11–2 Use of INSTANCE Built-In Token 11–4 11–3 Use of NOTANY Built-In Token 11–5 11–4 Use of SEQUENCE Built-In Token 11–5 11–5 Use of SKIP Built-In Token 11–6 11–6 Tree Traversing Code Example 11–7 Use of TREEPTR Built-In Function 11–8 11–10 11–8 Using Built-In Functions to Traverse a Tree 11–14 11–9 Use of Tree Built-In Functions 11–17 11–10 Use of POINTER Built-In Function 11–26 11–11 Use of ENDFILE Built-In Function 11–30 11–31 11–12 Use of TIME Built-In Function 12–1 Program Labels 12–3 12–2 Assignment Statements 12–5 12–3 Substring Assignment 12–6 12–4 Assigning to a Record 12–7 12–5 Record Compatibility 12–8 12–6 CALL Statement 12–10 12–7 GOTO Statement 12–11 12–8 CASE Statement 12–12 xvii 12–9 IF . . . THEN . . . ELSE Statement 12–15 12–10 WHILE Statement 12–16 12–11 FOR Loop 12–17 12–12 RETURN Statement 12–18 12–13 File as Input Stream 12–21 12–14 Procedure as Input Stream 12–22 12–15 String as Input Stream 12–23 12–16 File as Output Stream 12–24 12–17 Procedure as Output Stream 12–25 12–18 String Variable as Output Stream 12–26 12–19 ANSWER Statement 12–30 12–20 ANSWER Attribute Program Segment 12–31 12–21 Using EXPOSE to Enable ANSWER Rechecking 12–32 12–22 Using TRIGGER Attribute to Enable ANSWER Rechecking 12–32 12–23 FAIL Statement 12–34 12–24 OPEN Statement 12–35 12–25 READ Statement with PROMPT 12–36 12–26 Use of ENDFILE with READ Statement 12–37 12–27 WRITE Statement 12–38 12–28 ALLOCATE Statement 12–40 12–40 12–29 FREE Statement 13–1 LIST Directive 13–2 REDEFINE Directive 14–1 VAX SCAN Program Calling LIB$FIND_FILE 14–20 14–2 VAX SCAN Program Calling SYS$FILESCAN 14–22 13–2 13–4 FIGURES xviii 1–1 VAX SCAN Application Flow 1–2 1–2 VAX SCAN Module Structure 1–13 1–3 Nesting of Program Blocks 1–22 1–4 TREE Structure 1–24 1–5 Sample TREE 1–26 4–1 Program Structure 4–1 5–1 TOKEN Mapping 5–7 5–2 UNIVERSAL TOKEN Building 5–9 7–1 Tree Diagram 7–6 7–2 Modified Tree Diagram 7–9 7–3 Keyword Tree 7–11 7–4 Overlay Storage 7–18 10–1 Use of Substring Operators 10–5 10–2 Use of Arithmetic Operators 10–6 10–3 Results of Concatenation 10–7 10–4 Use of Relational Operators 10–9 11–1 Tree Structure 11–8 11–2 Tree References 11–9 11–3 Use of EXISTS Built-In Function 11–11 11–4 Use of FIRST Built-In Function 11–12 11–5 Use of LAST Built-In Function 11–13 11–6 Use of NEXT Built-In Function 11–13 11–7 Use of PRIOR Built-In Function 11–14 11–8 Use of VALUE Built-In Function 11–15 11–9 Use of VALUEPTR Built-In Function 11–16 11–10 Use of SUBSCRIPT Built-In Function 11–17 11–11 Use of INDEX Built-In Function 11–19 11–12 Use of LENGTH Built-In Function 11–19 11–13 Use of LOWER Built-In Function 11–20 11–14 Use of UPPER Built-In Function 11–21 11–15 Use of MEMBER Built-In Function 11–22 11–16 Use of TRIM Built-In Function 11–23 11–17 Use of INTEGER Built-In Function 11–24 11–18 Use of STRING Built-In Function 11–25 11–19 Use of ABS Built-In Function 11–27 11–20 Use of MAX Built-In Function 11–27 11–21 Use of MIN Built-In Function 11–28 11–22 Use of MOD Built-In Function 11–29 12–1 Estimation of Buffer Size for DATA STACK 12–28 12–2 PRUNE Statement 12–42 16–1 Structure of VOTER Tree F–1 Initial Screen Display 16–9 F–5 xix F–2 VAX Language-Sensitive Editor Keypad Layout for VT100 Series Terminals F–12 F–3 VAX Language-Sensitive Editor Keypad Layout for VT200 Series Terminals F–13 F–4 Expansion of Initial String F–22 F–5 First Placeholder F–23 F–6 TOKEN Selected F–24 F–7 Pattern Provided for Token F–25 F–8 MACRO Expanded F–26 TABLES xx 3–1 Character Set 3–2 3–2 Equivalent Symbols 3–2 3–3 Reserved Keywords 3–4 3–4 Unreserved Keywords 3–4 3–5 Control Characters 3–7 3–6 Special VAX SCAN Characters 3–10 3–7 Delimiters 3–11 5–1 SET Operator Precedence 5–2 5–2 TOKEN Operator Precedence 5–7 5–3 GROUP Operator Precedence 5–11 5–4 Picture Operators 5–16 5–5 Error Recovery Packet Meaning 5–30 7–1 Record Variable Initial Value 7–17 7–2 File Variable Operations 7–20 9–1 Procedure Parameter Types 9–2 Parameter-Passing Mechanisms 10–1 Expression Operators 10–2 10–2 Substring Operator Restrictions 10–4 10–3 Relational Operator Rules 10–8 10–4 Logical Operators 10–5 Pointer Reference Meanings 10–18 10–6 Expression Operator Precedence 10–20 11–1 Built-In Tokens 11–1 11–2 Built-In Functions 11–6 9–5 9–7 10–9 11–3 Integer Conversion Results 11–23 11–4 String Conversion Results 11–25 12–1 VAX SCAN Executable Statements 12–1 12–2 Assignment Statement Requirements 12–4 12–3 Assignment Operand Restrictions 12–6 12–4 Case Values 12–13 12–5 START SCAN Options 12–19 12–6 READ Statement Target Variables 12–37 12–7 Initialization Value for Variable Types 12–39 13–1 VAX SCAN Directive Statements 13–1 13–2 Listing Options 13–2 13–3 VAX SCAN Special Characters 13–3 14–1 VAX/VMS Run-Time Library Facilities 14–2 14–2 Groups of VAX/VMS System Services 14–3 14–3 VAX/VMS Data Structures 14–4 Default Passing Mechanisms in VAX SCAN 14–13 14–5 Overriding the Default Passing Mechanism 14–14 16–1 DEBUG Command Qualifiers 14–7 16–2 A–1 VAX SCAN Control Characters A–1 C–1 Reserved Keywords C–1 C–2 Unreserved Keywords C–1 D–1 FDL Description for VAX SCAN Input File D–1 D–2 FDL Description for VAX SCAN Output File F–1 Editor Command Line Qualifiers F–11 F–2 Default Editor Keypad Functions F–13 F–3 Editor Line Mode Commands F–14 D–2 xxi Preface This manual describes the features, uses, constructs, and syntax of the VAX SCAN language on VAX/VMS and MicroVMS systems. Intended Audience The Guide to VAX SCAN is intended for use by the seasoned programmer. It assumes a thorough knowledge and working facility with computer concepts, the VAX/VMS operating system, the VAX/VMS Symbolic Debugger, and one or more high-level programming languages in the VAX/VMS Common Language Environment. Document Structure This manual has 16 chapters, 6 appendixes, and an index. Chapter 1 introduces you to VAX SCAN on the VAX/VMS operating system and describes the major concepts and parts of the language, its elements, and its structure. Typical uses for the language are discussed. Chapter 2 introduces the development and structure of VAX SCAN programs. Creating and editing VAX SCAN programs are discussed in relation to the VAX Language-Sensitive Editor (VAXLSE). DIGITAL Command Language (DCL) commands for compiling, linking, and running VAX SCAN programs are introduced. Chapter 3 describes the primitives of the language. ix Chapter 4 describes the structure and interrelationships of the constructs in a VAX SCAN program, such as MODULE, PROCEDURE, MACRO, STATEMENT, and ELEMENT. Chapter 5 introduces and explains the picture-matching concepts and statements of VAX SCAN. Chapter 6 introduces and explains the concept particulars of the input and output streams in VAX SCAN. Chapter 7 describes the types of variables that support the algorithmic part of the VAX SCAN language. Chapter 8 describes the statements involved in declaring variables in VAX SCAN. Chapter 9 explains the statements used to declare the VAX SCAN procedures. Chapter 10 describes the use of expressions. Chapter 11 explains the built-in facilities supplied by the VAX SCAN language. Chapter 12 describes the executable statements used in VAX SCAN. Chapter 13 explains the statements that control how the VAX SCAN program is compiled. Chapter 14 explains how to call the VAX/VMS Run-Time Library routines and system services from VAX SCAN programs. Chapter 15 describes the error reporting and error recovery facilities of VAX SCAN and explains how to access the VAX SCAN HELP library. Chapter 16 describes how to use the VAX/VMS Debugger with VAX SCAN programs. Appendix A lists the symbols, hexadecimal values, and descriptions of the various VAX SCAN control characters. Appendix B contains syntax diagrams for VAX SCAN executable statements, declarations and types, and directives. Appendix C contains tables of the reserved and the unreserved keywords in VAX SCAN. Appendix D lists the file attributes that VAX SCAN supports. x Appendix E contains the DEC Multinational Character Set. Appendix F describes the use of the VAX Language-Sensitive Editor in the development and maintenance of VAX SCAN programs. The Guide to VAX SCAN is indexed to let you find information quickly and easily. (Information is also available on line from the VAX SCAN HELP facility.) Associated Documents For additional information on the VAX/VMS operating system and other areas, refer to the following manuals: • • • • • The(VMS_DCLDICT_REF) for detailed information about how to use the DIGITAL Command Language (DCL) The (VMS_ARCHITECTURE_A) for detailed information about the family of VAX computers and VAX data types The (VMS_SYSROUT_R) for a description of the VAX/VMS routines used to control resources, allow process communication, control I/O, and various other operating system functions The VAX Language-Sensitive Editor User’s Guide for a description of the VAX Language-Sensitive Editor, a multi-language advanced text editor designed for software development The (VAX_TPU_LRM) for a description of the VAX Text Processing Utility, a programmable editing tool that is part of the VAX Language-Sensitive Editor (VAXLSE) Conventions The following conventions are used in this document: xi Convention Meaning UPPERCASE letters and special symbols Uppercase letters and special symbols in syntax descriptions and sample procedures indicate VAX SCAN keywords and other user input that must be typed exactly as shown. lowercase letters Lowercase letters in syntax descriptions and sample procedures represent elements that you must replace according to the description in the text. RETURN A symbol with a one- to six-character abbreviation indicates that you press a key on the terminal, for example RETURN . In Appendix F, some keys that are listed within tables are boxed for ease in viewing, even though they are not shown in interactive examples. CTRL/x CTRL/x indicates that you press the key labeled CTRL while you simultaneously press another key, for example, CTRL/Y, CTRL/E, CTRL/Z. $ SCAN test.scn RETURN DBG> EXIT RETURN Command examples show all output lines or prompting characters that the system prints or displays in black letters. All userentered commands or responses are shown in red letters. quotation mark Quotation mark refers to the double quotation mark ( " ). apostrophe Apostrophe refers to the single quotation mark ( ’ ). n phrase1 o phrase2 xii Oversized braces in syntax diagrams indicate a mandatory portion of the syntax. The vertical stacking indicates that phrase2 is an alternative for phrase1. Therefore, when oversized braces enclose a stacked list of items, you must choose one of the items. Convention h phrase1 i phrase2 Meaning Oversized brackets in syntax diagrams indicate an optional portion of the syntax. Vertical stacking within oversized brackets indicates that you can choose one of the items. phrase . . . Horizontal ellipses mean that a phrase or item may be repeated. A horizontal ellipsis preceded by a comma ( , ) means that you can repeat the item, separating two or more items with the comma. Enter the comma only when the item is repeated two or more times. MODULE . . . END MODULE Vertical ellipses mean that not all the statements are shown. VAX SCAN keywords appear in uppercase in this manual and must be spelled exactly as shown, except where abbreviations are allowed. Metasymbols are in lowercase letters in examples, as well as in the syntax diagrams and statements of general rules. Metasymbols are names used to describe syntax diagrams that are described elsewhere. Syntax diagrams present the format specifications used in writing VAX SCAN source code. You must order syntax elements as shown in the syntax diagram. The diagrams are included in the detailed discussions of each language element. In addition, Appendix B contains all of the syntax diagrams for the VAX SCAN language. Syntax diagrams consist of VAX SCAN keywords, metasymbols, phrases, and punctuation symbols. A phrase can be any of the following: a keyword, a metasymbol, or, a sequence of keywords, metasymbols, and operators enclosed by braces ( { } ) or brackets ( [ ] ) that are oversized. When the syntax diagram contains braces ( { } ) or brackets ( [ ] ) that are not oversized, the braces or brackets are part of the actual syntax and you enter them as shown in the diagram. The syntax diagrams thus show the placement and sequence of VAX SCAN statement items, and whether an item is optional or mandatory, as in the following example: xiii " CASELESS TOKEN token-name IGNORE ALIAS character-literal # ... {token-expression}; token-name has the following syntax: 2 letter 3 6 digit 7 letter 4 5 ... _ $ This is the syntax diagram for the TOKEN statement, one of the VAX SCAN declarative statements. TOKEN is a reserved keyword identifying the statement type. TOKEN is followed by the metasymbol token-name (which you choose and declare when you write your program). Metasymbols are spelled out in italic print and are defined immediately after the diagram in which they are used. The metasymbol definition may be text only or another syntax diagram. The metasymbol defined here is token-name. It is defined as letter optionally followed by a letter, digit, underscore ( _ ), or dollar sign ( $ ). The horizontal ellipsis ( . . . ) indicates that the optional second phrase (the range of which is shown by stacking) can be repeated. The TOKEN statement has three optional attributes: CASELESS, IGNORE, and ALIAS. The optional ALIAS attribute is followed by the character-literal. The final elements of the statement are the token-expression, which is enclosed in braces ( { } ), and the terminating semicolon ( ; ). Note that the braces ( { } ) enclosing the token-expression are not oversized and are therefore part of the syntax that you must enter. xiv Chapter 1 Introduction to VAX SCAN Welcome to the community of VAX SCAN users. 1.1 Understanding VAX SCAN VAX SCAN is a block-structured programming language in the VAX/VMS environment that is designed to build tools to manipulate text strings and text files. The primary applications for VAX SCAN are filters, translators, extractors/analyzers, and preprocessors. VAX SCAN is a compiled programming language that includes string operators for searching, comparing, extracting, and assigning character strings. A significant strength of VAX SCAN is in the pattern-matching constructs that permit matching of one or more complex patterns of text in the input data. VAX SCAN can then create replacement text for the original patterns that were found in the input. Because VAX SCAN is a high-level language, short programs are easily written to produce tools for special-purpose applications. VAX SCAN programs are readable and easy to comprehend, thus easing software maintenance. VAX SCAN is a layered product in the VAX/VMS family that adheres to the VAX/VMS Common Language Environment. You can call procedures written in other VAX/VMS languages from within a VAX SCAN program. Similarly, you can call VAX SCAN procedures from programs written in other VAX/VMS languages. Thus, VAX/VMS Run-Time Library routines are available to your VAX SCAN program, as well as the VAX/VMS system services. Introduction to VAX SCAN 1–1 Compiling a VAX SCAN program produces an OBJ file that, when linked, produces an EXE file. You can debug your VAX SCAN programs with the VAX/VMS Debugger. 1.2 Using VAX SCAN The VAX SCAN programming language is named for the way the input text is scanned, or processed, as it is searched for the patterns specified by the application. The input is treated in a flowing manner, so it is referred to as the input stream. The output, referred to as the output stream, consists of text from the input stream plus program-generated replacement text. In Figure 1–1, the VAX SCAN application represents the point in the VAX SCAN program where text in the input stream undergoes transformations on its way to the output stream. Figure 1–1: VAX SCAN Application Flow ARTFILE ZKO-4285-85 VAX SCAN processes text similar to the way the following editor SUBSTITUTE command replaces text: S/oldstring/newstring/ The task of the SUBSTITUTE command is to replace all occurrences of oldstring with newstring. The transformations that occur in a VAX SCAN program are similar, although in a VAX SCAN program oldstring and newstring are not limited to strings. Oldstring is replaced by a pattern that can recognize constructs as complicated as a programming language. Newstring is replaced by an algorithm that can generate arbitrary replacement text. 1–2 Introduction to VAX SCAN The VAX SCAN construct that performs a transformation is called a macro. A macro has a block-structured form that looks like the following: MACRO macro-name TRIGGER { pattern }; . Sequence of statements that construct . the text that will replace the text matched . by the pattern. END MACRO; The pattern that the macro is to search for in the input stream is enclosed in braces. This pattern is referred to as the macro’s picture. It corresponds to oldstring in the editor command. Between the MACRO and END MACRO statements is the algorithm that creates the text to replace the text matched by the picture. This algorithm is referred to as the body of the macro. It corresponds to newstring in the editor command. Example 1–1 shows a macro that is designed to search for a time stamp and to replace the time with ’1st time’, ’2nd time’, or ’3rd time’, depending on which occurrence it is. Example 1–1: Search and Replace Macro MACRO find_time TRIGGER { integer ’:’ integer [ ’:’ integer ] }; DECLARE count: STATIC INTEGER; count = count + 1; ! increment count CASE count 1 TO 3; ! case on value of count [ 1 ]: ANSWER ’1st ’; ! if count = 1 [ 2 ]: ANSWER ’2nd ’; ! if count = 2 [ 3 ]: ANSWER ’3rd ’; ! if count = 3 [ outrange ]: ANSWER STRING( count ), ’th ’; ! otherwise END CASE; ANSWER ’time’; END MACRO; Introduction to VAX SCAN 1–3 The picture states that the macro is searching for an integer followed by a colon, followed by an integer, optionally followed by another colon and an integer. A picture is constructed much like the syntax diagrams in this manual. The following table lists picture segments and their meanings. Picture Segment Meaning integer ’:’ An integer followed by ’:’ [ integer ] The integer is optional integer... One or more integers integer | ’:’ An integer or a ’:’ The body of the macro (the text replacement algorithm) starts by declaring the variable count. The statements that follow increment the value of count, and then case on its value to generate the replacement text. The actual reporting of replacement text is done using the ANSWER statement. As the example shows, multiple ANSWER statements are permitted, each adding a segment to the replacement text. In this example, the different parts of the CASE statement report whether this is the first, second, or third time. The ANSWER statement following the CASE statement appends the sequence ’time’ to the replacement text. Assume that an application containing this macro reads the following input stream text. Courageous rounded the first buoy at 1:23:55, 20 seconds ahead of Australia II. On the windward leg, Australia II made up the difference and surged ahead, rounding the second buoy at 1:59:00 compared to Courageous’ time of 2:00:03. From that point on it was Australia II’s race. She had a commanding lead when the race ended at 3:14. The application then makes textual changes in the output stream as follows. Courageous rounded the first buoy at 1st time, 20 seconds ahead of Australia II. On the windward leg, Australia II made up the difference and surged ahead, rounding the second buoy at 2nd time compared to Courageous’ time of 3rd time. From that point on it was Australia II’s race. She had a commanding lead when the race ended at 4th time. 1–4 Introduction to VAX SCAN The analogy to the editor SUBSTITUTE command is apparent now. The VAX SCAN application scanned the input stream to find the pattern specified by the macro and replaced the text matched by the pattern with the text generated by the macro body. Input stream text that is not matched by the pattern is transferred to the output stream unaltered. Your VAX SCAN applications can use multiple macros to perform a series of transformations, or they can use a set of macros to describe new statements for a programming language. Bodies of macros can include calls to VAX/VMS Run-Time Library routines and to VAX/VMS system services. They can also include calls to other procedures written in any of the VAX/VMS languages, including VAX SCAN. 1.2.1 Creating a Pattern VAX SCAN uses a two-level approach to define the patterns to be searched for in the input stream. The first level of patterns describes how to map the characters of the input stream into units called tokens. If your application was developed to process Pascal programs, it would describe the elements of the Pascal language, such as identifiers, integers, strings, comments, and punctuation marks, as tokens. The second level of patterns are the macro pictures. Pictures are patterns of tokens. Thus, integer and ’:’ used in the example in the previous section are tokens. The following example shows their declaration: TOKEN integer { { ’0’ | ’1’ | ’2’ | ’3’ | ’4’ | ’5’ | ’6’ | ’7’ | ’8’ | ’9’ | }... }; TOKEN colon ALIAS ’:’ { ’:’ }; The first declaration defines integer to be a digit between 0 and 9, repeated one or more times. The vertical bar ( | ) means or and the horizontal ellipsis ( . . . ) indicates repetition just as in macro pictures. The second declaration defines a colon ( : ) to be the colon token. This token declaration has the ALIAS attribute. This attribute states that you can reference the colon token by an alternate name, ’:’, which is more readable in macro pictures than the name colon. Introduction to VAX SCAN 1–5 VAX SCAN provides several aids in declaring tokens, one of which is a set. A set describes a subset of the DEC Multinational Character Set. For example, the set digit describes the set of digits. You can then use this subset to simplify the token integer in the following example: SET digit ( ’0’..’9’ ); TOKEN integer { digit... }; This set uses the range operator ( .. ) to define digit as the characters between 0 and 9 in the collating sequence. You can also use the operators AND, OR, and NOT to form sets from one or more ranges. The following example shows the declaration of several commonly used tokens: SET alpha ( ’a’..’z’ OR ’A’..’Z’ ); SET digit ( ’0’..’9’ ); SET quote ( ’’’’ ); SET non_quote ( NOT quote ); TOKEN key_input CASELESS { ’INPUT’ }; TOKEN identifier { alpha [ alpha | digit | ’_’ | ’$’ ]... }; TOKEN string { quote [ non_quote | quote quote ]... quote }; TOKEN space IGNORE { { ’ ’ | s’ht’ }... }; TOKEN comma ALIAS ’,’ { ’,’ }; TOKEN semi ALIAS ’;’ { ’;’ }; The first token describes the keyword INPUT that is the sequence of five characters, I N P U T. The attribute CASELESS specifies that any alphabetic character in the pattern can appear in either uppercase or lowercase. For example, INPUT, input, or InPuT will match this token. The second token describes an identifier in the VAX SCAN language, and the third token defines a string literal. The token space describes one or more blanks or tabs. This token has the IGNORE attribute that specifies that the token should be ignored during picture-matching. This is useful because it eliminates the need for describing where spaces can occur in a macro pattern—they can appear zero or more times between any two tokens. After you have defined the tokens needed by the application, you are ready to arrange them in macro pictures to define the patterns you are searching for. The following example uses the tokens you have just seen to describe the pattern of an input statement that starts with the keyword input, followed by a series of identifiers separated by commas and terminated with a semicolon: MACRO input_statement TRIGGER { key_input identifier [ ’,’ identifier ]... ’;’ }; 1–6 Introduction to VAX SCAN A final consideration in building patterns is factoring common patterns. Token declarations provide such factoring because all the macro pictures in a module share a set of tokens. It is also frequently useful to share common macro pictures. A typical example is the description of a data type in a programming language. Such a pattern is needed in the description of a variable, type, and record component. You create such a macro in VAX SCAN as follows. MACRO data_type SYNTAX { INTEGER | BOOLEAN | [ FIXED ] STRING ’(’ integer_value ’)’ | VARYING STRING ’(’ integer_value ’)’ | [ DYNAMIC ] STRING | RECORD { component ’,’ }... END RECORD | POINTER TO data_type } ; END MACRO; MACRO component SYNTAX { identifier ’:’ data_type }; END MACRO; MACRO declare_stmt TRIGGER { DECLARE identifier [ ’,’ identifier ]... ’:’ data_type ’;’ }; END MACRO; MACRO type_stmt TRIGGER { TYPE identifier ’:’ data_type ’;’ }; END MACRO; This example shows that each VAX SCAN macro has one of two attributes, SYNTAX or TRIGGER. A macro with the TRIGGER attribute is one that works like the editor substitute command. It searches the input stream for its pattern. A macro with the SYNTAX attribute is an extension of the picture of another macro. Data_type is such a syntax macro, describing the syntax of a data type. The macros declare_stmt and type_stmt reference the name of the macro data_ type at the point in their pattern where they require the pattern that has been factored into data_type. Thus, the pattern for type_stmt consists of the keyword TYPE, followed by an identifier, followed by a colon, followed by a data type, where the form of a data type is given by the picture of macro data_type. VAX SCAN’s pattern-matching capabilities center around trigger macros. The pictures of these macros describe the patterns to be searched for in the input stream. In the case of complex or common patterns, you use syntax macros to factor the complex or common picture parts into separate pictures. Introduction to VAX SCAN 1–7 Macro pictures are constructed of tokens. These tokens themselves are patterns that describe character level constructs that the application needs to find. 1.2.2 Creating Replacement Text The picture of a macro matches a sequence of text in the input stream, and the body of the macro generates the text to replace the text matched by the picture. This is the basic principle of a VAX SCAN macro. When generating replacement text, there are three important points to consider: • • • 1.2.2.1 How to capture the text matched by the picture How to construct the replacement text How to report the text constructed Capturing Matched Text Text matched by a macro picture is placed in picture variables. Picture variables are dynamic string or integer variables that are placed in the actual macro picture, as shown in the following example: MACRO find_time TRIGGER { hour: integer ’:’ minute: integer [ ’:’ second: integer ] }; In this example, hour, minute, and second are dynamic string picture variables. Hour collects the text matched by the first integer token; minute collects the text matched by the second integer token; second collects the text matched by the last integer token. For example, if the macro find_time matched the text 1:33, the picture variables would have the following values in the body of the macro: hour minute second 1 33 null string Note that second contains the null string. It appears in an optional part of the pattern, a part that was not matched. Thus, it was never assigned a value. 1–8 Introduction to VAX SCAN Picture variables are not limited to appearing before tokens. They can appear before a syntax macro, in which case they collect the replacement text of that syntax macro. They can also appear before a phrase, as in the following example: MACRO find_time TRIGGER { time:{ integer ’:’ integer second:[ ’:’ integer ] } }; In this example, time captures the text matched by the entire picture and second captures the text of the final optional phrase. Thus, if the macro picture matched 12:59:59, the picture variables would contain the following values: time second 12:59:59 :59 There are also integer picture variables that capture the line and column of the matched text. They are shown in the following example: MACRO find_time TRIGGER { hour_text,hour_line,hour_column: integer ’:’ *,minute_line: integer [ ’:’ integer ] }; As can be seen from this example, one to three picture variables can be specified. The first is for capturing the text, the second is for the line where the text started, and the third is for the column where the text started. An asterisk ( * ) can be used if you do not wish to capture one of the values. In the example find_time, an asterisk ( * ) is used to indicate that you are not interested in the text of the minute, just the line where the minute’s text started. The final aspect of using picture variables has to do with repetition. Consider the following example: MACRO integer_list TRIGGER { { value: integer }... }; This picture can match one or more integer tokens. The picture variable value, in this example, is a tree variable. A tree can hold multiple values like an array in Pascal. The concept of trees is discussed in Section 1.3.6. Assume that the macro picture matched the following text: 12 345 67890 444 3333333 1 Introduction to VAX SCAN 1–9 The picture variable would then hold the following values: value( value( value( value( value( value( 1.2.2.2 1 2 3 4 5 6 ) ) ) ) ) ) 12 345 67890 444 3333333 1 Constructing Replacement Text The VAX SCAN language contains a complete programming language to construct replacement text using an algorithm. The language has similarities to Pascal and has the following features: • • • • Variable, constant, and external procedure declarations Executable statements such as assignment, IF-THEN-ELSE, FOR, WHILE, and CASE Subroutine and function procedures Expressions including powerful operators and built-in functions The following macro shows an example of the VAX SCAN language being used to construct replacement text: CONSTANT h = ’hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh’; CONSTANT m = ’mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm’; CONSTANT s = ’ssssssssssssssssssssssssssssssssssssssss’; MACRO find_time TRIGGER { hour: integer ’:’ minute: integer [ ’:’ second: integer ] }; /* replace hour with a sequence of h’s */ ANSWER h[ 1..length( hour ) ], ’:’; /* replace minute with a sequence of m’s */ ANSWER m[ 1..length( minute ) ]; /* replace second with a sequence of s’s if it was present */ IF second <> ’’ THEN ANSWER ’:’, s[ 1..length(second) ]; END IF; /* add AM or PM based on the hour */ IF INTEGER (hour) <= 11 THEN ANSWER ’am’; ELSE ANSWER ’pm’; END IF; END MACRO; 1–10 Introduction to VAX SCAN One of the most significant features of the VAX SCAN language is that you can call procedures written in other VAX/VMS languages. Thus, you can construct replacement text in procedures written in languages such as VAX BASIC, VAX PASCAL, or VAX SCAN. In addition, you can use the VAX/VMS Run-Time Library routines and VAX/VMS system services. 1.2.2.3 Reporting Replacement Text VAX SCAN provides a special statement, the ANSWER statement, for reporting replacement text. Consider the replacement text as a buffer of text. This buffer is empty before you execute the body of a macro. When you execute the body of a macro, each of the ANSWER statements appends text to any text already in the buffer. If the body of your macro executes no ANSWER statements, then the text matched by the picture is replaced by the null string. This is a convenient way to remove text from the input stream. The previous example in this section shows the use of multiple ANSWER statements to report replacement text in segments. 1.3 Getting Started with VAX SCAN You have now encountered many of the components of a VAX SCAN program. In this section, the goal is to use them in a complete program. Understanding the structure of a VAX SCAN program involves understanding the following major structural components of the language: • • • • Programs Modules Macros Procedures A program is a VAX/VMS executable image (an EXE file) that you run with the DCL RUN command. A program is composed of one or more modules. Another term used in this manual for a program is an application. Introduction to VAX SCAN 1–11 A module may be written in any of the VAX/VMS languages, including VAX SCAN. Each module is compiled using the appropriate language compiler to create an object module (an OBJ file). The object modules are combined using the VAX/VMS Linker to produce the program. A module is central to the VAX SCAN language in several ways. First, the VAX SCAN compiler compiles a single module at a time. Second, although your application can span multiple modules, the picturematching constructs in VAX SCAN (such as tokens and macros) are local to a module. When the picture-matching process is started in a module, VAX SCAN applies the macros defined in that module against the input stream. A macro is the vehicle for transforming the input stream to produce the output stream. Each module can define zero or more macros. A procedure performs the same function in VAX SCAN as in other languages. A VAX SCAN module can define zero or more procedures. Most modules contain at least one procedure because one is needed to start the picture-matching process. In addition, procedures are used for communicating between VAX SCAN modules when a program consists of more than one module. Procedures are one of the cornerstones of the VAX/VMS Common Language Environment. In this environment, a procedure (some languages call them routines, functions, or subroutines) written in one language can be called by modules written in other languages. Figure 1–2 shows the structure of a module. 1–12 Introduction to VAX SCAN Figure 1–2: VAX SCAN Module Structure Artfile ZK-4286-85 Figure 1–2 shows that modules, macros, and procedures also consist of the following components: • • • Declarations Directives Executable statements Declarations allow you to define variables and to control their data type, name, and storage requirements. Introduction to VAX SCAN 1–13 Directives are placed in the program source code to control compiler functions such as listing control. Executable statements perform actions such as assigning values to variables, calling procedures, and starting picture-matching. These statements are described in detail in Section 4.1. Example 1–2 shows a complete VAX SCAN module. This program consists of a single module, change_times. The module begins with the comment that describes the function of the program, followed by a series of declarations which define constants, a set, and tokens. The module also contains two macros, one for transforming dates and another for transforming times. The module also contains a single procedure called main_routine. The bodies of the macros in this example contain only executable statements. These create the replacement text for the text matched by their respective macro pictures. The procedure also has a body, like the macros. Its body consists of a single executable statement, START SCAN. 1.3.1 Flow of Control in a VAX SCAN Program A key concept in understanding the CHANGE_TIMES program is understanding the order in which the statements are executed. To run the CHANGE_TIMES program, compile and link it to create an executable image. The program is executed with the RUN command. The RUN command starts the execution of the program at the main procedure. If the main procedure is written in VAX SCAN, as in Example 1–2, it is the procedure with the MAIN attribute. The main procedure can be written in any of the VAX/VMS languages. In CHANGE_TIMES, execution starts with the procedure main_ routine. The statements in the body of this procedure are executed sequentially. The first statement in this procedure is a START SCAN 1–14 Introduction to VAX SCAN Example 1–2: CHANGE_TIMES Program MODULE change_times; !+ This is a program that locates all occurrences ! of times of the form: ! a date dd-mmm-yyyy -or- a time hh:mm:ss ! and replaces them with: !"dd-mmm-yyyy" -or- "hh:mm:ss" CONSTANT h = ’hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh’; CONSTANT m = ’mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm’; CONSTANT s = ’ssssssssssssssssssssssssssssssssssssssss’; CONSTANT x = ’xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’; CONSTANT y = ’yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy’; CONSTANT d = ’dddddddddddddddddddddddddddddddddddddddd’; SET digit ( ’0’ .. ’9’ ); TOKEN integer { digit... }; TOKEN colon ALIAS ’:’ {’:’}; TOKEN month CASELESS { ’jan’ | ’feb’ | ’mar’ | ’apr’ | ’may’ | ’jun’ | ’jul’ | ’aug’ | ’sep’ | ’oct’ | ’nov’ | ’dec’ }; TOKEN dash ALIAS ’-’ { ’-’ }; MACRO replace_date TRIGGER { day: integer ’-’ month ’-’ year: integer }; ANSWER d[ 1..length(day) ], ’-mmm-’, y[ 1..length(year) ]; END MACRO /* replace_date */; MACRO replace_time TRIGGER { hour: integer ’:’ minute: integer [ ’:’ second: integer ] }; ANSWER h[ 1..length( hour ) ], ’:’, m[ 1..length( minute ) ]; IF second <> ’’ THEN ANSWER ’:’, s[ 1..length(second) ]; END IF; END MACRO /* replace_time */; PROCEDURE main_routine MAIN; !+ Start the picture matching process. The input stream ! is the file TIME.DAT. The output stream is defined !- via the logical name SYS$OUTPUT. START SCAN INPUT FILE ’TIME.DAT’ OUTPUT FILE ’SYS$OUTPUT’; END PROCEDURE /* main_routine */; END MODULE /* change_times */; statement. The purpose of this statement is to initiate the picturematching process. Three items are central to starting the picturematching process: • • The input stream The output stream Introduction to VAX SCAN 1–15 • The set of tokens and macros to use The START SCAN statement specifies all three of these items. You see that the input and output streams are specified using clauses. In the example, the input stream is the file TIME.DAT, and the output stream is a file specified by the logical name SYS$OUTPUT. The macros and tokens that specify the transformations are those defined in the module where the START SCAN statement is executed. As the START SCAN statement is executed in the module change_times, it is the macros and tokens in this module that define the transformations to be performed. With the execution of the START SCAN statement, the flow of control in your program changes. The macros start searching the input stream for transformations to be made. Statements are no longer executed one after another like in most languages. The macros that are invoked, and the order in which they are executed, are driven by the sequence of data in the input stream. Assume that the following sequence is a segment of the input stream: The TITANIC struck the iceberg 14-Apr-1912 at 11:55 pm The date 14-Apr-1912 would activate the macro replace_date. Thus, the next sequence of statements to be executed are those in the body of the macro replace_date. After reaching the end of the macro body and completing the text replacement specified by the macro body, searching of the input stream continues. Next, the time 11:55 activates the macro replace_time. Once again, the body of the macro is sequentially executed, text replacement takes place, and searching continues for more patterns. This cycle continues until the end of the input stream is reached. With no further transformations to make, the START SCAN statement is finished doing its job. Sequential execution of the statements following the START SCAN statement continues. This example has no further statements to execute, so the procedure main_routine returns control to its caller. Main_routine was called by the RUN command in this case, so the execution of the program halts. You are then returned to DCL command level, and you receive the DCL prompt. 1–16 Introduction to VAX SCAN From this example, it is easy to extrapolate the points where a VAX SCAN program can interact with procedures in other modules. First, a procedure in a separate module can call the procedure main_routine (main_routine should not have the MAIN attribute in this case). Thus, a separate module, perhaps written in VAX FORTRAN, can call a VAX SCAN procedure passing a file or string for a set of VAX SCAN macros to analyze. This is generally the way other languages take advantage of VAX SCAN capabilities. The second point where interaction can occur is in a macro body. A macro body can call a procedure to do some work. This procedure could be a VAX/VMS Run-Time Library routine, a VAX/VMS system service, or a procedure written in another language. 1.3.2 Token Building The starting point for picture matching is token building. VAX SCAN begins processing the input stream by grouping characters in the input stream into tokens. This process is referred to in VAX SCAN as tokenizing, or token building. VAX SCAN tokenizes the input stream characters into tokens according to the token declarations in the module. Each token declaration describes a pattern of characters. If the text in the input stream matches one of these patterns, then VAX SCAN builds that token. Your token declarations typically do not describe all possible sequences of characters in the input stream. If a sequence is encountered that does not have a matching token, VAX SCAN builds a universal token for this sequence of characters. Thus, given your token declarations and the universal token, VAX SCAN can process the entire input stream of characters into an input stream of tokens. The token building process analyzes the input stream in sequential order. VAX SCAN attempts to build the longest token possible. This process can be explained by an example. Consider the following two tokens: TOKEN one { ’ab’ }; TOKEN two { ’abcd’ }; If the series of characters abcd is found in the input stream, the larger token, ’abcd’, is built, rather than ’ab’. Introduction to VAX SCAN 1–17 If the characters in the input stream at a particular point do not match a token, the characters are built into a single universal token until one of the following characters is found: an end of line, an end of stream, or a start of stream. Whenever any of these are encountered, they terminate the universal token that is currently being built. Once initiated, the scanning process continues, with tokens being built and identified either as universal tokens or as a match for application tokens. The following two tokens can be used to further illustrate this concept: TOKEN samp2 { ’x’ | ’y’ | ’Z’ }; TOKEN samp3 { ’x’...’y’...’Z’... }; With these tokens in mind, construct a hypothetical situation with a stream of text consisting of xmmmxyyyZnnnnnn oooxyZZZ. The following stream of tokens is built (uni represents the universal token): ARTFILE ZK-4289-85 Note that the two sequences, xyyyZ and xyZZZ, both caused the token samp3 to be built. Although the two sequences are different, they both match the pattern of token samp3. Note also that the token generator does not stop at xyZ when it builds the second occurrence of samp3, but builds the longest possible token, in this case, xyZZZ. 1.3.3 Picture Matching The trigger macros in the module initiate transformations. Picture matching keeps a table of the tokens that start each of the trigger macro pictures. The tokens that start a trigger macro are known as triggers for that macro. 1–18 Introduction to VAX SCAN When the first token is built from the text read in the input stream, it compares this token with its table of trigger tokens. If this token is a trigger for one or more trigger macros, VAX SCAN declares each of these macros to be candidates for activation. If there is only one trigger macro to activate, it is activated. If there is more than one candidate, VAX SCAN applies a set of rules discussed in Section 5.4.5 to choose the first trigger macro. Analysis of the whole picture of the chosen trigger macro now begins. Additional tokens are built and compared with the pattern defined in the macro picture. There may or may not be a match. If not, then VAX SCAN backs the input stream up to the trigger token and tries another macro candidate. The process continues until there is a match, or until there are no more trigger macros that have the original input token as a trigger. If a token is not a trigger, or if it is a trigger that did not successfully match a macro picture, the text of the token is transferred to the output stream. The process continues by building the next token and checking whether it is a trigger. The body of the macro is activated if there is a picture match. Replacement text that is generated by the macro body replaces the text in the input stream that is matched by the macro picture. The input stream can then be considered a local copy kept by picture matching. Token building then tokenizes the input stream, starting with the replacement text. The replacement text usually does not cause further triggering, unless the replacement text was answered with the TRIGGER attribute. A second scan checks for this special case of answered text with the TRIGGER attribute. If the replacement text contains no further triggers, it is transferred to the output stream. 1.3.4 Input and Output Stream Forms Input and output streams in VAX SCAN can take several forms. An input or an output stream can be a file, a string, or a procedure. When the input stream is a procedure, the VAX SCAN application reads the input stream by making repeated calls to the input stream procedure, which returns a single line of input for each call. Similarly, to write to the output stream, the VAX SCAN application makes repeated calls to Introduction to VAX SCAN 1–19 the output stream procedure, passing it a single line of output on each call. 1.3.5 VAX SCAN Variables VAX SCAN has the following variable types to accommodate the textoriented tasks that the language is used for: • • • • • • Integer String (fixed, varying, and dynamic) Boolean Pointer File Fill VAX SCAN also provides the following data structures: • • • • Scalars Records Overlays (similar to Variants or Unions) Trees VAX SCAN also provides several different storage method, allowing efficient control over resource allocation and intermodule accessibility and sharing. The relative placement of your variable declarations in the module affects the scope of the variable definition. In general, variables defined in a module, macro, or procedure can be referenced from within that block as well as from the ones that are structurally nested within it. A variable declared at module level is accessible in any block in the module, unless the name becomes redefined at a lower nested level. The scope of the redefined variable is then determined by the level where it is declared. Example 1–3 shows the use and placement of variable declarations in a VAX SCAN program. 1–20 Introduction to VAX SCAN Example 1–3: Variable Declaration Placement MODULE outer; DECLARE vmodule : DYNAMIC STRING ; PROCEDURE proc1a; DECLARE v1a : DYNAMIC STRING ; PROCEDURE proc2a; DECLARE v2a : DYNAMIC STRING PROCEDURE proc3a; DECLARE v3a : DYNAMIC END PROCEDURE /* proc3a */; END PROCEDURE /* proc2a */; END PROCEDURE /* proc1a */; PROCEDURE proc1b; DECLARE v1b : DYNAMIC STRING ; PROCEDURE proc2b; DECLARE v2b : DYNAMIC STRING PROCEDURE proc3b; DECLARE v3b : DYNAMIC END PROCEDURE /* proc3b */; END PROCEDURE /* proc2b */; END PROCEDURE /* proc1b */; END MODULE /* outer */; ; STRING ; ; STRING ; The nesting of program blocks in this example is shown in Figure 1–3. Introduction to VAX SCAN 1–21 Figure 1–3: Nesting of Program Blocks Artfile ZK-4287-85 In Example 1–3, the variable vmodule is accessible to all procedures, but the variable v2b is limited to the procedures proc2B and proc3B. 1–22 Introduction to VAX SCAN For a detailed discussion of the declaration of variables and variable storage class, see Chapter 8. 1.3.6 VAX SCAN Trees VAX SCAN has a convenient and efficient data structure for the storage of data. This structure is a tree or tree variable. A tree is similar to an array in other programming languages. You can reference a node in a tree much like an array element. Some significant differences between VAX SCAN trees and arrays are as follows: • • • Trees can have a varying number of elements (called nodes). Tree subscripts are not necessarily contiguous. Tree subscripts are not necessarily integers. A VAX SCAN tree is shown in Figure 1–4. Introduction to VAX SCAN 1–23 Figure 1–4: TREE Structure Artfile ZK-4290-85 The root of the tree exists from the time of its declaration. There is no specified limit to the number of interior nodes and leaf nodes. The number of levels, or the depth of the tree, is specified in the TREE declaration statement. The maximum number of levels that a tree can have is 100. Nodes do not exist in a tree until you assign them a value. In VAX SCAN, the subscript value assigned to identify the nodes can be either the string or integer type. Once identified by declaration, all nodes at a given level have subscripts of the same type. The nodes at each level are sorted intrinsically—if a level has integer subscripts, all nodes at that level are in numerical order. Nodes with string subscripts are in collating sequence. Thus, one way to perform a sort in VAX SCAN is to make the data you are sorting the subscript of a tree. For more information on VAX SCAN trees, see Chapter 7. Example 1–4 shows a tree containing geopolitical divisions and populations. 1–24 Introduction to VAX SCAN Example 1–4: Declaring a TREE Structure DECLARE geography : TREE( STRING,STRING ) OF INTEGER; This declaration names the tree geography. The declaration also indicates that the tree has two levels of string subscripts and that the tree’s values at the leaf nodes are integers. The subscripts are used to describe state (level 1) and city (level 2), and the leaf value is the population of the city. Example 1–5 shows how to use several assignment statements to place values in this tree. Example 1–5: Assigning TREE Values geography( geography( geography( geography( ’California’, ’Sacramento’ ) ’New York’, ’Buffalo’ ) ’New York’, ’Albany’ ) ’New York’, ’New York City’ ) = = = = 275741; 357870; 101727; 7071030; This tree now has the form and contents shown in Figure 1–5. Introduction to VAX SCAN 1–25 Figure 1–5: Sample TREE Artfile ZK-4291-85 Note that strings appear inside single quotes ( ’ ) and integers do not. The state names (’New York’, ’California’) and city names (’Albany’, ’Buffalo’, ’New York City’, ’Sacramento’) are subscripts. By appearing in the assignment, they serve to construct the tree. The relative position of the subscripts (from left to right) inside the parentheses defines their level in the tree (from top to bottom). The integer values below the city names (101727, 357870, 7071030, and 275741) represent the values stored at the specified leaf nodes. VAX SCAN has built-in functions to help you use trees easily and efficiently. These functions give you the ability to do the following: • • • • • • Determine if a node exists Find a specific node Return the value and subscript of a node Find the first, last, prior, and next nodes Remove a node Traverse a tree 1–26 Introduction to VAX SCAN 1.4 Processing Text with VAX SCAN The primary application for VAX SCAN is processing text and text symbols. These applications may be categorized broadly as follows: • • • • Filters Translators Extractors/analyzers Preprocessors 1.4.1 Filters Filter programs remove unwanted parts of a text stream. VAX SCAN applications can read an input data stream, while looking for specified text patterns. When found, the unwanted parts can then be removed, without changing the remaining text. For example, RNO files intended for processing by the DIGITAL Standard Runoff (DSR) text processor consist of text plus DSR commands. A VAX SCAN program can identify and delete certain commands from the file, leaving other commands unchanged. A VAX SCAN application of this type would define components of the DSR commands as tokens and then use macros to search for the appropriate commands. The macros would remove the unwanted commands, while the remaining text would pass unchanged from the input stream to the output stream. In another situation, certain strings in a file could be replaced by application-generated text. As an example, absolute time references such as 12:34:56 can be replaced by general references such as HH:MM:SS. 1.4.2 Translators Translator programs are often needed to make syntax changes to a text file in accordance with a set of rules. For example, there are many different dialects of Pascal and BASIC and quite a few variations of FORTRAN. This can create a problem of portability for a computer user who must write programs that run on multiple dialects. A VAX Introduction to VAX SCAN 1–27 SCAN translation application can be developed to recognize the syntax differences in the source code and to build the desired syntax. In this way, VAX SCAN can be used to translate source files written in dialect A to dialect B. If dialect B does not have all the capabilities of A, but system calls can perform the desired function, the translation can replace the feature in dialect A with a call to a procedure in dialect B that performs the feature. Another application is to nationalize a computer language by taking, for example, all the English keywords and replacing them with their French equivalents. Thus, BASIC applications written using French keywords could be translated by VAX SCAN to run on an Englishbased BASIC interpreter or compiler. This is accomplished in a VAX SCAN application by mapping the French keywords to their English equivalents using a tree, while leaving the identifiers, comments, strings, and punctuation marks as written. 1.4.3 Extractors/Analyzers Extractors and analyzers are used to mark or count text patterns having special significance. The pattern-matching ability of VAX SCAN can be used to find and record specified text or string patterns. Thus, a VAX SCAN application can be written to record the occurrence of certain words and phrases, or patterns, for later statistical analysis, without any effect on the subject file. VAX SCAN can search a file for specified patterns, record them, and never produce an output file. For example, in an application where the only need is to count the comments in a PL/I file, no transformation would take place and the only output would be the comment count. These comment lines are readily identifiable in PL/I, as in other languages, and can be described using a single VAX SCAN token. This token can be the picture of a macro whose body increments a count whenever this token is built. 1–28 Introduction to VAX SCAN 1.4.4 Preprocessors A preprocessor program can be used to extend a language to increase its power, without modifying the language itself. To do this, you can develop a VAX SCAN application that recognizes the syntax of the extensions and produces code in the host language and, thus, perform the task defined by the extended instructions. Thus, specialized software at your site can be preprocessed by a VAX SCAN application to allow it to run on a DIGITAL system (for example, for benchmarking). A preprocessor can also be developed to allow language extensions to be evaluated before they are formally built into the compiler for that language. When a programming language or a tool does not have a macro capability that permits users to extend its syntax, VAX SCAN can be used to provide the macro functions. For example, one DSR flag can be provided to both underline and bold with a minimum of keystrokes: With the appropriate VAX SCAN preprocessor, these flags ( <> ) highlight a section of text for underlining and bolding. Your text file contains your special flags, < and>. Your VAX SCAN application maps these symbols to the DSR equivalents, ^*^& and \*\&, respectively. Another example is merging a mailing list with a standard format letter. The same letter is sent to each person on the list, with the appropriate name, address, and salutation filled in according to the list. You can do this in VAX SCAN by creating a master copy of the letter that indicates where the substitutions need to be made. Place the data to be substituted into the letter in a second file. A VAX SCAN module can read the second file of data to substitute and store it in a tree. A second VAX SCAN module can then repeatedly scan the master copy of the letter and perform the substitutions. Introduction to VAX SCAN 1–29 Chapter 2 VAX SCAN Application Development VAX SCAN applications are developed much like programs in other high-level languages. The programmer first establishes a clear picture of what the application is to do, then puts together the collection of program statements that does the job. Using VAX SCAN on the VAX/VMS operating system is the same as using other VAX/VMS compiled languages. You create a VAX SCAN program with one of the available editors. Then compile, link, and run the program. The default file type for VAX SCAN source programs is SCN. 2.1 Creating and Editing VAX SCAN Programs You can use VAX Text Processing Utility (VAXTPU) and the VAX Language-Sensitive Editor (VAXLSE) to create and edit VAX SCAN programs. Both are described in this section. 2.1.1 VAX Text Processing Utility The VAX Text Processing Utility (VAXTPU) is a programmable text processing utility designed to aid the development of editing interfaces. VAXTPU includes a high-level procedural language, a compiler, an interpreter, and two editing interfaces written in VAXTPU. The editing interfaces are the EDT Keypad Emulator and the Extensible VAX Editor (EVE). You can layer other editors on top of VAXTPU. You can create extensions to the interfaces, thus tailoring your VAXTPU editing VAX SCAN Application Development 2–1 interface to suit your own needs. You can also create a completely separate editing interface with VAXTPU. The VAXTPU language has many built-in procedures that perform functions such as the following: • • • • Screen management Key definition Limited text manipulation Program execution You can use these built-in procedures to manipulate VAXTPU. To invoke VAXTPU from the DCL level, type EDIT/TPU, followed by the file specification to be edited. For example: $ EDIT/TPU yourfile.SCN RETURN This command opens the file yourfile.SCN for editing. For more information on using VAXTPU, see the (VAX_ TPU_LRM). 2.1.2 VAX Language-Sensitive Editor The VAX Language-Sensitive Editor (VAXLSE) is a source code editor that allows you to quickly and accurately develop and maintain programs. You can control the editing environment by using VAXLSE commands. You can also access VAXLSE’s knowledge of programming languages to create, compile, and review your VAX SCAN programs. VAXLSE can serve both experienced and inexperienced programmers as a time-saving tool for program development. Some of the features supported by VAXLSE are as follows: • • • Tokens—Syntactic models of language constructs (including VAX SCAN). Placeholders—Strings that indicate a place requiring the substitution of program text. User-defined templates, keys, and commands—Constructs that let you customize your editing environment and which you can save for use in subsequent sessions. 2–2 VAX SCAN Application Development • • A compiler interface—An interface which allows you to compile programs and review errors from inside VAXLSE. VAXLSE uses diagnostic messages from the compiler to locate places in the source file where errors have been diagnosed. Online Language Help—Help that is associated with language keywords and placeholders. To invoke the VAX Language-Sensitive Editor (VAXLSE) from DCL level, type LSEDIT, followed by the name of your file. For example: $ LSEDIT yourfile.SCN RETURN This command opens the file yourfile.SCN for editing. Example 2–1 shows a VAX SCAN program editing session, with selected placeholders expanded for purposes of illustration. Example 2–1: VAX Language-Sensitive Editor Program MODULE {-module_name-} [-IDENT ’{-module_ident-}’-]; SET {-set_name-} ( {-set_expression-} ); TOKEN {-token_name-} [-token_attr-]... { {-token_expression-} }; MACRO {-macro_name-} {-req_attribute-} [-opt_attribute-] { [-picture-] }; [-macro_body_statement-]... END MACRO /* {-macro_name-} */; PROCEDURE {-procedure_name-} [-MAIN-] [-parameters-] [-OF {-type-}-]; [-procedure_body_statement-]... END PROCEDURE /* {-procedure_name-} */; [-module_statement-]... END MODULE /* {-module_name-} */; For more information on VAXLSE, see Appendix F and the VAX Language-Sensitive Editor User’s Guide. 2.2 Compiling, Linking, and Running Programs The DCL command qualifiers for VAX SCAN program development follow the conventions of the VAX/VMS Common Language Environment. VAX SCAN Application Development 2–3 2.2.1 SCAN Command The SCAN command invokes the VAX SCAN compiler to compile a VAX SCAN source program. For a complete description of VAX/VMS compiler commands, including more information about qualifiers, see the VAX/VMS Program Development volume. The format for the SCAN command is as follows: " SCAN # " file-spec /qualifier # , ... The /qualifiers for the SCAN command can be found in the system HELP files by entering HELP SCAN. The following is an example of the SCAN command: $ SCAN/LIST testprog.scn RETURN This command creates an object module with the file name testprog.OBJ and the listing file testprog.LIS. (Note that the SCN file type is the default and can be omitted.) 2.2.2 LINK Command The VAX/VMS Linker uses the object module produced by the SCAN command as input and generates an executable image file as output. The format of the LINK command is as follows: " LINK # /qualifier " file-spec # , ... File-spec Is the object module with the OBJ file type that was produced by the VAX SCAN compiler. For a complete description of the VAX/VMS Linker, including more information about the LINK command and its qualifiers, see the (VMS_LINKER_REF). The following is an example of the LINK command: $ LINK testprog RETURN The linker will produce an executable image with the file name testprog.EXE. 2–4 VAX SCAN Application Development 2.2.3 RUN Command Run the VAX SCAN application by typing the following command: $ RUN file-spec RETURN File-spec Is the executable image with the EXE file type that was previously produced by the linker. VAX SCAN Application Development 2–5 Chapter 3 Elements of the VAX SCAN Language You construct a VAX SCAN program by arranging primitives of the language into statements, macros, procedures, and modules. These primitives are the elements of the language and include the following: • • • • • Names Keywords Literals Operators and delimiters Spaces, tabs, and comments These elements are described in detail in this chapter. 3.1 Program Form VAX SCAN is a free-form language—constructs such as statements and macros can span more than one source line. Constructs need not begin or end in any particular column. Elements of the language, however, cannot span source lines. Thus, a comment or a literal cannot start on one line and terminate on a subsequent line. The width of a source line can be up to 256 characters. Elements of the VAX SCAN Language 3–1 3.2 Character Set Elements of the VAX SCAN language are constructed using the characters in Table 3–1. ASCII uppercase and lowercase characters are interchangeable except within string literals. Table 3–1: Character Set Subset Characters Letter ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz Digit 0123456789 Other _ ’ & ( ) * , + – . / : = [ ] | <> ; ! $ \ { } space tab form-feed Rest %" ? @^’ DEC Multinational Characters X’A0’ through X’FF’ The DEC Multinational Character Set is an 8-bit character set with 256 characters. Appendix E contains the complete character set. Because the characters [, ], | , \, {, and } are not universally available on all hardware, equivalent symbols are defined for these characters, as shown in Table 3–2. Table 3–2: Equivalent Symbols Character Equivalent Symbol [ << ] >> | / \ // { } /> Members of the letter, digit and other subsets are used to build the elements. However, characters from the rest subset are valid only in comments and string literals. Missing from the character set are control characters, which are not permitted in a VAX SCAN source 3–2 Elements of the VAX SCAN Language program. Special literals must be used to construct a string literal containing a control character. String literals are discussed in detail in Section 3.5.4. 3.3 Names VAX SCAN language objects such as sets, tokens, variables, procedures, and macros have names of the following form: 2 letter 3 6 digit 75 . . . letter 4 _ $ A name cannot exceed 31 characters in length. The following are examples of valid VAX SCAN names: X A_RATHER_LONG_NAME_12345 SS$_NORMAL 3.4 Keywords Keywords are names that have special meaning and can be used in the following contexts in VAX SCAN: • • • • • As a statement verb—Each statement in VAX SCAN (except assignment) begins with a keyword, for example, DECLARE and IF. As a clause verb—Several statements have subparts that begin with a keyword such as TO integer-expression and STEP integerexpression in the FOR statement. As an attribute—Several statements use keywords as attributes to further qualify the statement, such as CASELESS and ALIAS in the TOKEN statement. As a built-in facility—All of the VAX SCAN built-in functions and built-in tokens start with a keyword. Examples are UPPER and LOWER. As a literal—Boolean and pointer literals are expressed using keywords, including TRUE, FALSE, and NIL. Elements of the VAX SCAN Language 3–3 • As an operator—Several VAX SCAN operators are keywords, such as AND, OR, and NOT. VAX SCAN has both reserved and unreserved keywords. A reserved keyword, often called a reserved word, cannot be used as the name of an object such as a token or variable. An unreserved keyword, on the other hand, can be used to name an object. In general, statement verbs, clause verbs, literals, and operators are reserved. Most built-in functions and attributes are not reserved. The reserved and unreserved keywords in VAX SCAN are shown in Tables 3–3 and 3–4, respectively. Table 3–3: Reserved Keywords ALLOCATE AND ANSWER CALL CASE CLOSE COLLATE CONSTANT DECLARE ELSE END ERROR EXTERNAL FAIL FALSE FILE FOR FORWARD FREE FROM GOTO GROUP IF INCLUDE INRANGE LIST MACRO MODULE NIL NOT OPEN OR OUTRANGE PROCEDURE PROMPT PRUNE READ REDEFINE RETURN SCAN SET START STEP STOP THEN TO TOKEN TRIGGER TRUE TYPE WHILE WRITE XOR Table 3–4: Unreserved Keywords ABS ALIAS ANY ASCII AUTOMATIC BOOLEAN CASELESS COLUMN COMMON DATA DEC_MULTI 3–4 Elements of the VAX SCAN Language AS Table 3–4 (Cont.): Unreserved Keywords DESCRIPTOR DYNAMIC EBCDIC ENDFILE EXISTS EXPOSE FILL FIND FIRST FIXED GLOBAL IDENT IGNORE INDEX INPUT INSTANCE INTEGER LAST LENGTH LOWER MAIN MAX MEMBER MIN MOD NATIVE NEXT NOTANY OF OFF ON OUTPUT OVERLAY PAGE POINTER PRIOR RECORD REFERENCE SEQUENCE SIZE SKIP STACK STATIC STRING SUBSCRIPT SYNTAX TIME TITLE TREE TREEPTR TRIM UPPER USER VALUE VALUEPTR VARYING WIDTH 3.5 Literals A literal is an element that represents a value. VAX SCAN has five types of literals: integer, Boolean, pointer, treeptr, and string. 3.5.1 Integer Literals An integer literal represents the value of a whole number. Integer literals have the form of an optional sign followed by one or more digits. h+ i integer-literal : digit . . . – Elements of the VAX SCAN Language 3–5 VAX SCAN implements integers as signed longwords. Thus, an integer literal must be in the range of –2,147,483,647 to 2,147,483,647. The following are examples of integer literals: 0 +123456 -1 0067000 3.5.2 Boolean Literals A Boolean literal represents either the value TRUE or the value FALSE. Thus, there are exactly two Boolean literals that are expressed using the reserved keywords TRUE and FALSE. n TRUE o boolean-literal : FALSE 3.5.3 Pointer and Treeptr Literals The only pointer or treeptr value that can be expressed as a literal is the null pointer or treeptr. This literal is represented with the reserved keyword NIL. pointer-literal : NIL; treeptr-literal : NIL; 3.5.4 String Literals A string literal represents a sequence of 0 to 65535 characters. String literals have several forms: string-literal: 8 quoted-string > < control-character > special-VAX-SCAN-character : hexadecimal-character 3–6 Elements of the VAX SCAN Language 9 > = > ; 3.5.4.1 Quoted String Literal The most common string literal is a quoted string literal, an apostrophe ( ’ ) followed by zero or more characters and closed by another apostrophe ( ’ ). An apostrophe can be represented in a string literal using two consecutive apostrophes, ( ’’ ). The following are examples of quoted string literals: ’aB&*c’ ’’ ’’’’ 3.5.4.2 the null string a single apostrophe Control Character Literals A string literal for a control character has the form S’name’, where name is one of the 2- or 3-character mnemonics listed in Table 3–5. Each of these string literals is one character in length. String literals for control characters can be either uppercase or lowercase. Table 3–5: Control Characters Symbol Hexadecimal Value Meaning s’nul’ 00 Null s’soh’ 01 Start of heading s’stx’ 02 Start of text s’etx’ 03 End of text s’eot’ 04 End of transmission s’enq’ 05 Enquiry s’ack’ 06 Acknowledge s’bel’ 07 Bell s’bs’ 08 Backspace s’ht’ 09 Horizontal tab s’lf’ 0A Line feed s’vt’ 0B Vertical tab s’ff’ 0C Form feed Elements of the VAX SCAN Language 3–7 Table 3–5 (Cont.): Control Characters Symbol Hexadecimal Value Meaning s’cr’ 0D Carriage Return s’so’ 0E Shift out s’si’ 0F Shift in s’dle’ 10 Data link escape s’dc1’ 11 Device control 1 s’dc2’ 12 Device control 2 s’dc3’ 13 Device control 3 s’dc4’ 14 Device control 4 s’nak’ 15 Negative Acknowledge s’syn’ 16 Synchronous idle s’etb’ 17 End of transmission block s’can’ 18 Cancel previous data s’em’ 19 End of medium s’sub’ 1A Substitute character s’esc’ 1B Escape s’fs’ 1C File separator s’gs’ 1D Group separator s’rs’ 1E Record separator s’us’ 1F Unit separator s’del’ 7F Delete s’ind’ 84 Index s’nel’ 85 Next line s’ssa’ 86 Start of selected area s’esa’ 87 End of selected area s’hts’ 88 Horizontal tab set s’htj’ 89 Horizontal tab with justification s’vts’ 8A Vertical tab set s’pld’ 8B Partial line down 3–8 Elements of the VAX SCAN Language Table 3–5 (Cont.): Control Characters 3.5.4.3 Symbol Hexadecimal Value Meaning s’plu’ 8C Partial line up s’ri’ 8D Reverse index s’ss2’ 8E Single shift 2 s’ss3’ 8F Single shift 3 s’dcs’ 90 Device control string s’pu1’ 91 Private use 1 s’pu2’ 92 Private use 2 s’sts’ 93 Set transmit state s’cch’ 94 Cancel character s’mw’ 95 Message waiting s’spa’ 96 Start of protected area s’epa’ 97 End of protected area s’csi’ 9B Control sequence introducer s’st’ 9C String terminator s’osc’ 9D Operating system command s’pm’ 9E Privacy message s’apc’ 9F Application program command Special Character Literals The special character literals consist of three characters that have a special meaning to VAX SCAN during picture matching. They are the characters that mark the start of the input stream, the end of the input stream, and the record boundaries in the input stream. The string literals for representing these characters are listed in Table 3–6. Elements of the VAX SCAN Language 3–9 Table 3–6: Special VAX SCAN Characters Symbol Hexadecimal Value Meaning s’eol’ 85 End of line s’sos’ 02 Start of stream s’eos’ 03 End of stream The hexadecimal value in the second column of Table 3–6 is the default value given to these special literals. You can change this default value with the REDEFINE directive. 3.5.4.4 Hexadecimal Character Literals Hexadecimal character literals consist of a single character. The form of this literal is X’xx’, where xx is two hexadecimal digits. The value of the string literal is the single character whose internal value is xx. The following are examples of hexadecimal literals: X’0D’ X’41’ X’85’ Carriage return control character Uppercase A Next line control character 3.6 Operators and Delimiters Operators are symbols such as +, –, *, and / that instruct VAX SCAN to perform a certain action. Delimiters are symbols that mark the beginning or end of a construct. For instance, the semicolon ( ; ) is the delimiter that marks the end of a statement. Most operators and delimiters are single characters. However, some involve a pair of characters, or a character sequence. Any operator or delimiter that consists of more than one character cannot span multiple source lines and cannot contain embedded blanks. Table 3–7 lists the VAX SCAN operators and delimiters. 3–10 Elements of the VAX SCAN Language Table 3–7: Delimiters Delimiter Use () Grouping operands in an expression, or delimiting arguments of a procedure [ ] or <<>> Optional phrase in pattern matching, or substring operator { } or /> Mandatory phrase | or / Alternative operator \ or // List operator – Subtraction operator, or unary minus operator + Addition operator, or unary plus operator * Multiplication operator / Division operator & Concatenation operator = Equal to operator, or assignment operator == Exactly equal to operator <> or >< Not equal to operator < Less than operator > Greater than operator >= or => Greater than or equal to operator <= or =< Less than or equal to operator ; End of statement delimiter : Label delimiter, look-ahead operator, or picture variable delimiter –> Pointer operator . Record component delimiter . . Range operator . . . Repetition operator , Delimiter in a list Elements of the VAX SCAN Language 3–11 3.7 Spaces, Tabs, Comments, and Form Feeds Spaces, tabs, and comments are special elements in the language. They are a means of delimiting other elements, such as two names. One or more of these elements may appear before or after any other element in the language. However, spaces, tabs, and comments that appear in string literals are treated as character sequences rather than as delimiters. A comment can take one of two forms. The first is a slash and an asterisk ( /* ), followed by arbitrary text and terminated by an asterisk and a slash ( */ ) or the end of the source line. The second format for a comment is an exclamation point ( ! ) followed by arbitrary text and terminated by the end of the source line. Comments cannot be nested; thus a slash and an asterisk ( /* ) within a comment are part of the arbitrary text. Because the end of the source line terminates a comment, no comment can span multiple lines. The following are examples of comments in a VAX SCAN program: /* This comment is terminated with the sequence: */ !+ ! This block comment is actually 4 comments, each of which ! is terminated by the end of the source line. !- Form feeds are control characters and, thus, cannot appear directly in a VAX SCAN program. The control character s’ff’ must be used instead. There is one exception to this rule: a form feed may appear in column 1 of a source line because VAX/VMS editors typically separate parts of a program with a form feed. The form feed causes a page break in the listing. 3–12 Elements of the VAX SCAN Language Chapter 4 Program Structure Chapter 1 used an example to describe the structure of a VAX SCAN program. This chapter analyzes the structure of a program in greater detail. Figure 4–1 shows the many levels of constructs in a VAX SCAN program. Figure 4–1: Program Structure ARTFILE ZK–4292–85 A VAX SCAN program consists of one or more modules. Each module is compiled separately using the VAX SCAN compiler to produce an object module. The object modules are then combined using the Program Structure 4–1 VAX/VMS Linker to produce an executable image. This executable image is the VAX SCAN program. The building blocks of a module are procedures and macros. A module consists of one or more procedures and zero or more macros. (Macros are optional.) A module can also contain supporting declarations for the procedures and macros. These include set, token, and variable declarations. Both procedures and macros have bodies consisting of zero or more statements. Procedure statements specify the algorithm to perform when that procedure is called. Macro statements specify the algorithm that will create text to replace the text matched by the macro’s picture. Statements specify the objects in the program and the actions to perform on those objects. Statements are constructed from the elements of the language that were described in Chapter 3. 4.1 Statement Structure VAX SCAN statements are divided into the following three categories: • • • Declarative statements Executable statements Directive statements Declarative statements, often called declarations, define the objects of your program. The objects include sets, tokens, and groups used in pattern matching. They also include variables and named constants used in algorithms. The declarative statements in your program must appear before the executable statements in the respective structures where they appear. The syntax diagram for VAX SCAN declarative statements is as follows: declarations: 2 constant-declaration 66 group-declaration 66 set-declaration 66 token-declaration 66 type-declaration 64 variable-declaration external-declaration forward-declaration 4–2 Program Structure 3 77 77 77 77 75 GROUP, SET, and TOKEN declarations are restricted to the module body. These objects are used by all the macro pictures; thus, they are restricted to a scope where they are visible to all macros. The remaining declarations can occur in the module body or within a procedure or macro. Those objects declared in the module body can be referenced throughout that module. Those within a macro or procedure are local to that macro or procedure. Executable statements specify the actions to be performed on the declared objects of the program. They include statements that assign values to objects, such as assignment and READ. They also include statements such as CALL and WHILE that control the order of execution of other statements. The syntax diagram for VAX SCAN executable statements is as follows: 2 allocate-statement 66 answer-statement 66 assignment-statement 66 call-statement 66 case-statement 66 close-statement 66 fail-statement 66 for-statement 66 free-statement label-name : . . . 6 goto-statement 66 if-statement 66 open-statement 66 prune-statement 66 read-statement 66 return-statement 66 start-scan-statement 66 stop-scan-statement 4 3 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 75 while-statement write-statement Note that executable statements are not permitted outside macro and procedure bodies (at module level). Directive statements, or directives, control the operation of the VAX SCAN compiler. They control the listing file, the source program input, the collating sequence, and so forth. Program Structure 4–3 The syntax diagram for directives is as follows: 2 3 include-directive 4 list-directive 5 redefine-directive The placement of directives in a program depends on the directive. REDEFINE statements affect the semantics of the entire module and, thus, must appear at the start of the module. INCLUDE and LIST directives can appear anywhere. 4.2 Macro Structure Macros are block-structured constructs. There are two kinds of macros in VAX SCAN—TRIGGER macros and SYNTAX macros. The syntax for the TRIGGER macro is as follows: " MACRO macro-name TRIGGER 2 variable-declaration 66 type-declaration 66 constant-declaration 66 procedure-declaration 64 macro-declaration 3 77 77 77 75 " # external-declaration forward-declaration executable-statement # {picture} ; EXPOSE ... ... END MACRO ; The syntax for the SYNTAX macro is as follows: " MACRO macro-name SYNTAX 4–4 Program Structure # EXPOSE " { # picture }; 2 variable-declaration 66 type-declaration 66 constant-declaration 66 procedure-declaration 64 macro-declaration 3 77 77 77 75 " # external-declaration forward-declaration executable-statement ... ... END MACRO ; Macros are local to a module; thus, one module cannot reference the macros of another module. The collection of macros defined within a module is called a macro set. Several such macro sets can exist in a program. The macro set used to process an input stream is the macro set defined in the module that executes the START SCAN statement. Declarations in a macro body must occur before any of the executable statements. However, there is no restriction on the placement of directives, macros, and procedures in the macro body. Example 4–1 shows a VAX SCAN macro. Example 4–1: VAX SCAN Macro MACRO count_keywords TRIGGER { id: symbol }; /* the declarations are first */ DECLARE copy: STRING; DECLARE symbol_table: COMMON TREE( STRING ) OF INTEGER; /* the executable statements follow the declarations */ copy = upper( id ); IF exists( symbol_table( copy ) ) THEN symbol_table( copy ) = symbol_table( copy ) + 1; END IF; END MACRO; Program Structure 4–5 4.3 Procedure Structure Procedures are block-structured constructs described by the following syntax diagram: " PROCEDURE procedure-name " # " MAIN # (parameter , . . . ) # OF type ; 2 variable-declaration 66 type-declaration 66 constant-declaration 66 64 procedure-declaration 3 77 77 77 75 " # external-declaration forward-declaration executable-statement ... ... END PROCEDURE ; Procedures defined in the module body are global to the module; they can be called from other modules. VAX SCAN adheres to the VAX Procedure Calling Condition Handling standard. As a result, the modules that call these procedures need not be written in VAX SCAN. The structure of the statements within a procedure body conform to the same rules as those in a macro body. Declarations must occur before any executable statements. There is no restriction on the placement of directives and procedures in the procedure body. Note that a macro cannot be defined within a procedure. Example 4–2 shows a VAX SCAN procedure. 4–6 Program Structure Example 4–2: VAX SCAN Procedure PROCEDURE trim_blanx ( string_to_trim: STRING ) OF STRING; /* the declarations are first */ DECLARE i, j, k: INTEGER; /* the executable statements come after the declarations */ k = LENGTH (string_to_trim); i = 1; WHILE ( i <= k ) AND ( string_to_trim [i] = ’ ’ ); i = i + 1; END WHILE; j = k; WHILE ( j >= i ) AND ( string_to_trim [j] = ’ ’ ); j = j - 1; END WHILE; IF j < i THEN RETURN ’’; ELSE RETURN string_to_trim [ i .. j ]; END IF; END PROCEDURE; 4.4 Module Structure Modules have the following form: " MODULE module-name # IDENT character-literal ; Program Structure 4–7 2 variable-declaration 66 type-declaration 66 constant-declaration 66 set-declaration 66 token-declaration 66 group-declaration 66 66 procedure-declaration 66 macro-declaration 66 external-declaration 66 forward-declaration 66 64 redefine-directive list-directive 3 77 77 77 77 77 77 77 77 77 77 77 75 ... include-directive END MODULE ; The body of the module can contain directives, declarations, macros, and procedures. No executable statements appear in the module body. The module must have a name. The name identifies the module to various VAX/VMS utilities. For example, VAX DEBUG allows you to qualify symbols on a module basis. The name in the module statement is the means of specifying the correct VAX SCAN module. IDENT is another VAX/VMS concept for further identification of a module. It is usually used to indicate the version of the module. The IDENT is a string constant in VAX SCAN. The VAX SCAN compiler includes the IDENT in the object module. If no IDENT is given on the module statement, an IDENT consisting of a single space is placed in the object module. Example 4–3 shows a VAX SCAN module. 4–8 Program Structure Example 4–3: VAX SCAN Module MODULE count_comments IDENT ’v1.0’; SET comment_char ( NOT ( s’eol’ OR s’eos’ ) ): TOKEN start_comment { ’!’ }; TOKEN comment_body { comment_char ... }; TOKEN end_comment { s’eol’ }; DECLARE count: INTEGER; MACRO find_comment TRIGGER { start_comment comment_body end_comment }; count = count + 1; END MACRO; PROCEDURE main_routine MAIN; START SCAN INPUT FILE ’scn$input’ OUTPUT FILE ’sys$output’; WRITE ’encountered ’, count ,’ comments’; END PROCEDURE; END MODULE; 4.5 Scope Each object in a VAX SCAN program has a name by which it is referenced. The scope is the set of rules that dictate which names (and, thus, which objects) can be referenced in which blocks. There are four rules of scope: 1. You can declare any number of objects within a block. However, each object in a block must be assigned a unique name. 2. You can reference an object within the block where you declare it and in any nested block, provided the nested block does not use the previously declared object’s name in another declaration. 3. You can assign the name of a previously declared object to an object declared in a nested block. In this case, however, the nested block (and any additional nested blocks) cannot reference the original object. 4. You must declare all objects before you reference them. The exceptions to this rule are labels, syntax macros, and user-defined types. Program Structure 4–9 Example 4–4: Scope MODULE illustrate_scope; CONSTANT a = 1; . ! here A is . . MACRO mac1 TRIGGER { ... }; CONSTANT b = 2; . ! here A is . . MACRO mac2 SYNTAX { ... }; CONSTANT a = 3; . ! here A is . . END MACRO; END MACRO; PROCEDURE global_proc ( ... ); CONSTANT b = 3; . ! here A is . . PROCEDURE nested_proc ( ... ); CONSTANT a = 3; . ! here A is . . PROCEDURE inner_most_proc ( ... ); CONSTANT c = a+b; . ! here A is . . END PROCEDURE; END PROCEDURE; END PROCEDURE; END MODULE; 1 1; B is 2 3, B is 2 1, B is 3 3, B is 3 3, B is 3, C is 6 Example 4–4 shows the four rules of scope. Rule 1 states that the names within a particular block need to be unique. Thus, it would be an error if the first macro was named a, because a is already the name of a constant. Rule 2 states that a nested block can reference an object in an enclosing block unless it declares another object with the same name. Thus, the module body, mac1, and globalproc can all reference the constant a declared in the module body. B can be referenced from both mac1 and mac2, but not from the module body. The most important aspect of 4–10 Program Structure this rule is that objects declared in the module body are accessible to all the macros and procedures in the module. The example in Section 4.4 uses this rule of scope to share data between a macro and a procedure (specifically, the variable count) . Rule 3 states that the declaration of the constant a in nested_proc prohibits the procedures nested_proc and innermost_proc from referencing the constant a declared in the module body. This rule should be exercised with care. A module with multiple objects having the same name can be very confusing and, thus, hard to debug. Rule 4 states that an object must be declared before it is referenced. Thus, the following sequence is not valid, because the constant giving the length of the string appears after a reference in the DECLARE statement. DECLARE name: FIXED STRING( max_name_length ); CONSTANT max_name_length = 200; There are a few exceptions to Rule 4: • • • Labels—A label is defined when it appears before an executable statement. A forward reference to a label is permitted. Syntax macros—A forward reference to a syntax macro within a picture is also permitted. VAX SCAN assumes that an undefined name as a picture operand is a forward reference to a syntax macro. User-defined types—A pointer in a TYPE declaration may point to an undefined type. Program Structure 4–11 Chapter 5 Picture-Matching Statements This chapter discusses the SET, TOKEN, GROUP, and MACRO statements that define a VAX SCAN picture. Pictures are not defined using an algorithm. Instead, they are defined using a sequence of rules or definitions. This is similar to defining the syntax of a language using Backus Normal Form (BNF). A SET declaration defines a set of characters. A TOKEN declaration defines a pattern of characters. A GROUP declaration defines a set of tokens. The picture in a MACRO defines a pattern of tokens to be searched for in the input stream. There is a hierarchy to these declarations. Sets are used in the definition of tokens. Tokens are used in the definition of groups. Tokens and groups are used in the definition of a MACRO picture. 5.1 SET Statement The SET declaration associates a name with a set of characters. Sets in VAX SCAN are constant; the characters that are members of a set are declared once and cannot later be changed. The syntax diagram for a SET declaration is as follows: SET set-name ( set-expression ) ; The SET statement describes the set of characters that you want to be members of the set. Picture-Matching Statements 5–1 Single character literals and sets are used to construct a set. These are the operands of a set definition, and they can be combined using operators to produce more complex sets. You can perform union (OR), intersection (AND), complement (NOT), and range ( .. ) operations on these operands. The intersection of two sets is a set containing all the characters that are members of both original sets. The union of two sets is a set that contains all characters that are members of either original set. The complement of a set is a set containing all characters except those in the original set. Range ( .. ) is a special operator for selecting a set of characters in the collating sequence between the first and second operand inclusively. The operands of range must be single characters and the left operand must come before or at the same point in the collating sequence as the right operand. Example 5–1 shows some SET declarations. Example 5–1: SET Declarations SET SET SET SET SET alpha alphanum non_ascii non_ascii terminator ( ( ( ( ( ’a’ .. ’z’ OR ’A’ .. ’Z’ ); alpha OR ’0’ .. ’9’ ); X’80’ .. X’FF’ ); NOT(X’00’ .. X’7F’) ); S’EOL’ OR S’EOS’ ); ! ! ! ! ! all alphabetics alphanumerics all with high bit set all with high bit set end of line or stream The precedence of the set operators is given in Table 5–1. Parentheses can be used to emphasize or override standard operator precedence. Table 5–1: SET Operator Precedence Operator Meaning Precedence .. Range Highest (done first) 5–2 Picture-Matching Statements Table 5–1 (Cont.): SET Operator Precedence Operator Meaning NOT Complement AND Intersection OR Union Precedence Lowest (done last) 5.2 TOKEN Statement A TOKEN declaration defines a token. The VAX SCAN language is designed to transform an input stream of text to an output stream of text. The tokens and macros in a VAX SCAN program control the particular translation performed on the input stream to produce the output stream. Tokens play a role at the character level. They describe patterns of characters that form a token. The TOKEN definitions in Example 5–2 define the patterns of characters for a space, a word, and a number. Example 5–2: TOKEN Declarations SET SET TOKEN TOKEN TOKEN alpha digit space word number ( ( { { { ’a’ .. ’z’ ); ’0’ .. ’9’ ); ’ ’ }; alpha... }; digit... }; ! ! ! ! ! the set of lowercase letters the set of digits just a space one or more letters one or more digits Macros view the input stream as a sequence of tokens. However, the actual input stream is a sequence of characters. The TOKEN declarations in your program state how to collect sequences of characters in the input stream to transform the input stream into a sequence of tokens. Picture-Matching Statements 5–3 The following example shows this transformation from a sequence of characters to a sequence of tokens. The example is based on three TOKEN declarations: space, word, and number: Input stream segment: 12345 is bigger than 123 Token Text Matching Token number space word space word space word space number 12345 is bigger than 123 The syntax diagram for a TOKEN declaration is as follows: " CASELESS TOKEN token-name IGNORE ALIAS character-literal # { token-expression } ; The pattern, {token-expression}, is similar to an expression you find in an assignment statement. The expression on the right-hand side of an assignment produces a value. This value results from combining the values of variables and literals with operators. A pattern in a token expression is similarly produced by combining patterns with operators to produce more complex patterns. The simplest patterns in a TOKEN declaration are sets and string literals. These are combined using the concatenation, alternation ( | ), repetition ( . . . ), and look-ahead ( : ) operators. Two grouping delimiters, much like parentheses in an expression, also exist for describing patterns. Braces ( {} ) are used to emphasize or override the standard precedence of the operators. Brackets ( [ ] ) indicate that the pattern contained within them is optional. These operators are explained in detail later. A set as a simple pattern matches any character that is a member of that set. The following TOKEN declaration has a pattern that contains just a set: SET alpha ( ’a’ .. ’z’ ); TOKEN character { alpha }; The token matches a single character that is a lowercase letter. 5–4 Picture-Matching Statements A string-literal as a simple pattern matches a series of characters that are exactly the same as the string-literal. The following TOKEN declaration has a pattern that contains just a string literal: TOKEN print_keyword { ’PRINT’ }; The token matches a sequence of five characters consisting of P, followed by R, followed by I, followed by N, followed by T. NOTE The maximum number of tokens you can have in a SCAN module is 500. 5.2.1 TOKEN Operators The TOKEN operators construct more complex patterns out of simpler patterns. Repetition is a unary operator and, thus, takes only one pattern as an operand. The resulting pattern of repetition is one that matches one or more occurrences of the original pattern. The TOKEN number below uses repetition to create a pattern that matches one or more characters from the set digit: SET digit TOKEN number ( ’0’ .. ’9’ ); { digit... }; Concatenation is a TOKEN operator that has no symbol. It occurs implicitly between two patterns that are not separated by an operator. The concatenation of two patterns is a pattern that matches an occurrence of the first pattern followed by the second pattern. The following TOKEN declaration is an example of concatenation: SET digit TOKEN positive_integer ( ’0’ .. ’9’ ); { ’+’ digit }; Concatenation appears implicitly between the string literal ’+’ and the set digit. The resulting pattern is the plus sign ( + ) followed by a digit. Alternation is an operator for specifying a choice between two patterns. Alternation constructs a pattern that matches either of two other patterns. The TOKEN sign below is an example of alternation: TOKEN sign { ’+’ | ’-’ }; Picture-Matching Statements 5–5 Sign’s pattern is either a ’+’ or a ’-’. You can make a pattern optional by enclosing it in brackets. The following example uses concatenation, alternation, repetition, and optional brackets to form the pattern for a name in VAX SCAN: SET alpha (’a’ .. ’z’ OR ’A’ .. ’Z’); SET digit (’0’ .. ’9’); TOKEN scan_name { alpha [ alpha | digit | ’_’ | ’$’ ]... }; The pattern starts with a character from the set alpha. This pattern is optionally followed by a complex pattern in the brackets. The complex pattern has four alternatives. The first alternative is a member of the set alpha; the second alternative is a member of the set digit; the third alternative is the underscore ( _ ); the fourth alternative is the dollar sign ( $ ). The optional complex pattern is followed by the repetition operator; thus, the complex pattern can occur zero or more times. The final TOKEN operator is the look-ahead operator. A look-ahead pattern is written with a pattern on the left and right side of a colon. left pattern : right pattern In this example, it is the left pattern that you are trying to match. However, using the look-ahead operator, not only must you match the left pattern, but the characters following the left pattern must match the right pattern. This might seem like concatenation, that is, the left pattern followed by the right pattern, but it is not. The difference is in the characters that are considered to be matched. For concatenation, the characters matching both the left and right patterns are the characters matched. For the look-ahead operation, only the characters matching the left pattern are the characters matched. You just ‘‘looked ahead’’ to make sure that they were followed by the right pattern. Consider the following example. If ’/’ is the last nonblank character on a line, it is the continuation symbol; otherwise, it is the division symbol. You can use the look-ahead operator to distinguish these two cases. SET TOKEN TOKEN TOKEN TOKEN digit continue division integer space 5–6 Picture-Matching Statements ( { { { { ’0’ .. ’9’ ); ’/’ : [ ’ ’... ] s’eol’ }; ’/’ }; digit... }; ’ ’... }; The first TOKEN declaration constructs a continue token if a ’/’ is followed by zero or more spaces and an end of line. Figure 5–1 shows the mapping of the input stream from characters to tokens, using the four TOKEN declarations above. Figure 5–1: TOKEN Mapping Input stream segment: 12345 / 34/5 / Token Text Matching Token integer space division space integer division integer space continue 12345 / 34 / 5 / The TOKEN operators have a specific precedence that is specified in Table 5–2. Table 5–2: TOKEN Operator Precedence Operator ... Meaning Precedence Repetition Highest (done first) (no symbol) Concatenation | or / Alternation : Look-ahead Lowest (done last) Both braces and square brackets can be used to override the default operator precedence. Picture-Matching Statements 5–7 5.2.2 TOKEN Attributes Several attributes can be ascribed to a token. They are as follows: • • • IGNORE CASELESS ALIAS IGNORE states that if this token is built, it is to be ignored during picture matching. This is a useful attribute for tokens such as blanks or spaces that do not contain any useful information, but are needed to delimit other tokens. A token with the IGNORE attribute cannot appear in a macro picture. The CASELESS attribute states that the character pattern should not be case sensitive. Thus, any alphabetic character in the token represents both the uppercase and lowercase definition of the character. Therefore, the following three TOKEN declarations are equivalent: TOKEN ex1 { ’AA3’ | ’aA3’ | ’Aa3’ | ’aa3’ }; TOKEN ex2 CASELESS { ’AA3’ }; TOKEN ex3 CASELESS { ’aA3’ }; Appendix E describes case-sensitive characters as either uppercase or lowercase. See Appendix E to determine which characters are case sensitive. The ALIAS attribute is designed to improve the readability of tokens in macro pictures. Token names cannot include special symbols such as the comma ( , ) and colon ( : ). The ALIAS attribute allows a token to be referenced using a character literal that can include these symbols. The literal appears after the ALIAS attribute. For example: TOKEN TOKEN TOKEN MACRO left_parenthesis ALIAS ’(’ { ’(’ }; right_parenthesis ALIAS ’)’ { ’)’ }; comma ALIAS ’,’ { ’,’ }; call_stmt1 SYNTAX { CALL name left_parenthesis expression [ comma expression ]... right_parenthesis }; MACRO call_stmt2 SYNTAX { CALL name ’(’ expression [ ’,’ expression ]... ’)’ }; The picture of call_stmt2 is considerably more readable than call_ stmt1. An alias can appear anywhere in a VAX SCAN program that a token can appear as an operand. 5–8 Picture-Matching Statements 5.2.3 Interaction of Tokens The set of TOKEN declarations in a module describe a mapping of the input stream from a stream of characters to a stream of tokens. Your programs can encounter a sequence in the input stream that does not match any of the tokens. To handle such sequences, VAX SCAN has a built-in feature called the universal token. If a token cannot be built, VAX SCAN advances the input stream to the next character that can start a token and tries again to build a token. The characters that are skipped become a universal token. Figure 5–2 shows the building of universal tokens. Figure 5–2: UNIVERSAL TOKEN Building TOKEN x TOKEN y { ’x’... }; { ’y’... }; Input stream segment: xxxzyyyzzx Token Text Matching Token x universal y universal x xxx z yyy zz x The universal token cannot be specified in a macro picture; its appearance in the input stream causes a macro picture to fail. TOKEN declarations sometimes overlap. For example: TOKEN times TOKEN power TOKEN print SET alpha TOKEN keyword { { { { { ’*’ }; ’**’ }; ’print’ }; ’A’ .. ’Z’ OR ’a’ .. ’z’ }; alpha... }; Picture-Matching Statements 5–9 If the input stream includes the sequence ’***’, then it would appear that this sequence could be three times tokens, or one power followed by one times, and so forth. VAX SCAN always tries to build the longest token possible; thus, in this case, the input stream is one power token followed by one times token. Sometimes the text matches more than one token. For instance, ’print’ in the above example matches both print and keyword. The choice here is the token that lexically appears first; thus, print is the token built. Tokens that cannot be built are diagnosed. For example, an unbuildable token would occur if the definitions of the tokens print and keyword in the example above were reversed. In this case, the sequence ’print’ would build the token keyword; thus, the TOKEN print could never be built. The VAX SCAN compiler would issue a diagnostic message indicating that print cannot be built. 5.3 GROUP Statement A GROUP declaration gives a name to a set of tokens. A reference to a group can appear anywhere that a reference to a token can appear. For example: GROUP group-name ( group-expression ) ; Constructing a group is much like constructing a set. The operands are tokens and other groups rather than characters and sets. The operators for combining the operands are intersection (AND), union (OR), and complement (NOT), as in set construction. Parentheses are also provided to emphasize or override operator precedence. The union of two groups is a group containing tokens that are members of either original group. For example, set_opr is a group containing the tokens and_opr, or_opr, not_opr, and range_opr: TOKEN TOKEN TOKEN TOKEN GROUP and_opr or_opr not_opr range_opr set_opr 5–10 Picture-Matching Statements { { { { ( ’AND’ }; ’OR’ }; ’NOT’ }; ’..’ }; and_opr OR or_opr OR not_opr OR range_opr ); The intersection of two groups is a group containing the tokens that are members of both of the original groups. Thus, you can add to the previous example: GROUP group_opr ( and_opr OR or_opr OR not_opr ); GROUP common_opr( group_opr AND set_opr ); The tokens representing the common operators of the group set_opr and group_opr can be defined using the AND operator in a group definition. All VAX SCAN modules contain at least one group, because VAX SCAN implicitly defines a group called the universal group for each VAX SCAN module. The universal group for each module consists of all the tokens defined in the module. The complement operation requires this universal group. The complement of a group is a group that contains all tokens in the universal group that are not members of the complemented group. Another way of defining group_opr would be as follows: GROUP group_opr ( set_opr AND ( NOT range_opr ) ); The universal group in this example is and_opr, or_opr, not_opr, and range_opr. Thus, (NOT range_opr) is and_opr, or_opr, and not_opr, which, when intersected with set_opr, produces the desired group of tokens. The group operators have the precedence given in Table 5–3. Parentheses can be used to emphasize or override operator precedence. Table 5–3: GROUP Operator Precedence Operator Meaning Precedence NOT Complement Highest (done first) AND Intersection OR Union Lowest (done last) Group declarations must follow the last TOKEN declaration so that the definition of the universal group is known when the group is declared. Picture-Matching Statements 5–11 5.4 Macros Macros are the final component in VAX SCAN’s picture matching. A macro is a block-structured statement. It has properties of both a declaration and an executable statement. The MACRO statement that begins a macro block contains a declaration, called the macro picture, that describes the pattern of tokens to be searched for in the input stream. An END MACRO statement ends a macro block. Between these two statements are zero or more declarations and executable statements that compose the text to replace the text matched by the picture. This group of statements is referred to as the macro body. The syntax for the TRIGGER macro is as follows: " MACRO macro-name TRIGGER 2 variable-declaration 66 type-declaration 66 constant-declaration 66 procedure-declaration 64 macro-declaration 3 77 77 77 75 " # external-declaration forward-declaration # {picture} ; EXPOSE ... ... executable-statement END MACRO ; The syntax for the SYNTAX MACRO is as follows: " MACRO macro-name SYNTAX 2 variable-declaration 66 type-declaration 66 constant-declaration 66 procedure-declaration 64 macro-declaration external-declaration forward-declaration 5–12 Picture-Matching Statements 3 77 77 77 75 ... # EXPOSE { " # picture }; " # executable-statement ... END MACRO ; NOTE The maximum number of macros you can have in a SCAN module is 127. 5.4.1 Macro Picture A macro picture is much like a token pattern. Both describe patterns. Tokens describe patterns of characters, and pictures describe patterns of tokens. Pictures, like tokens, are constructed using simple pictures that are combined using operators to construct more complex pictures. The simplest pictures are tokens, groups, and syntax macros. A token as part of a picture states that the next token in the input stream needs to be the named token. A group as part of a picture states that the next token in the input stream needs to be a member of the named group. Syntax macros are a means of directing VAX SCAN to look at another macro picture for the pattern of tokens. The operators in pictures are alternation ( | ), concatenation, repetition ( . . . ), and list ( \ ). Braces ( { } ) and brackets ( [ ] ) can be used to emphasize or override standard operator precedence. Braces ( { } ) indicate that a pattern is required. Brackets ( [ ] ) indicate that the enclosed pattern is optional. 5.4.1.1 Alternation Operator ( | ) The alternation operator ( | ) indicates that one of a series of pictures must match. The alternation of two pictures is a picture that matches either the left picture or the right picture. The macro operand in Example 5–3 shows the use of the alternation operator. Picture-Matching Statements 5–13 Example 5–3: Alternation SET digit ( ’0’ .. ’9’ ); SET alpha ( ’A’ .. ’Z’ OR ’a’ .. ’z’ ); TOKEN integer { digit... }; TOKEN real { digit... [ ’.’ [ digit... ] ] }; TOKEN name { alpha ... }; TOKEN operator { ’+’ | ’-’ | ’*’ | ’/’ }; TOKEN spaces IGNORE { ’ ’... }; MACRO operand SYNTAX { integer | real | name }; . . . END MACRO; Example 5–4: Concatenation MACRO exp SYNTAX { operand operator operand }; . . . END MACRO; The macro operand’s picture is either the token integer, the token real, or the token name. 5.4.1.2 Concatenation The concatenation picture operator has no symbol. It occurs implicitly between two pictures not separated by an operator. The concatenation of two pictures is a picture that matches the left picture followed by the right picture. Example 5–4 shows concatenation. The picture contains two concatenations. The picture of the syntax macro operand must be followed by an operator token, that in turn must be followed by the picture of the syntax macro operand. 5–14 Picture-Matching Statements 5.4.1.3 Repetition Operator ( . . . ) Repetition is a unary operator and, thus, takes only one picture as an operand. The resulting picture of repetition is one that matches one or more occurrences of the original picture, as shown in Example 5–5. Example 5–5: Repetition MACRO exp SYNTAX { operand { operator operand }... }; . . . END MACRO; Example 5–5 defines exp to be an operand followed by one or more operator operand pairs. Thus, the following stream matches this macro’s picture: input stream segment: abc + def/123 - 1.456 5.4.1.4 Token Text Matching Token Comment name spaces operator spaces name operator integer spaces operator spaces real abc First operand Ignored in match Start of 1st repetition Ignored End of 1st repetition Start of 2nd repetition End of 2nd repetition Ignored Start of 3rd repetition Ignored End of 3rd repetition + def / 123 1.456 List Operator ( \ ) The list operator is a convenient way of describing a list of pictures. The picture consists of one or more occurrences of the left pattern, each of which is separated by an occurrence of the right pattern. The pictures in the macros in Example 5–6 are equivalent. Picture-Matching Statements 5–15 Example 5–6: List MACRO exp SYNTAX { operand \ operator }; MACRO exp SYNTAX { operand [ operator operand ]... }; Both pictures describe one or more operands separated by an operator. The list operator appears in VAX SCAN not only because it is a short-hand notation, but because it makes the collection of text in picture variables cleaner (see Section 5.4.4 for an example). 5.4.1.5 Optional Brackets ( [ ] ) Brackets are used to make a picture optional. The previous example shows a use of optional brackets. These optional brackets indicate that the operator operand pair may or may not appear. When coupled with the repetition operator, the result is a pattern that can occur zero or more times. 5.4.1.6 Operator Precedence The picture operators have the precedence given in Table 5–4. Braces can be used to emphasize or override operator precedence. Table 5–4: Picture Operators Operator ... Meaning Precedence Repetition Highest (done first) (no symbol) Concatenation \ or // List | or / Alternation Lowest (done last) 5.4.2 TRIGGER and SYNTAX Attributes Declarations of VAX SCAN macros must specify either the TRIGGER or the SYNTAX attribute. A macro with the TRIGGER attribute is a trigger macro. A trigger macro is activated when one of the tokens that can start its picture is recognized in the input stream. The set of tokens that can start a picture is called the trigger for that picture. 5–16 Picture-Matching Statements A macro with the SYNTAX attribute is a syntax macro. Syntax macros are activated when their name appears in a macro picture. The TRIGGER and SYNTAX attributes are mutually exclusive. To illustrate the difference in the two types of macros, the following problem is given: VAX SCAN’s WRITE statement has no formatting associated with it. It writes a sequence of expressions to a file (see WRITE statement for further details). The goal of this example is to translate write statements containing format information into the WRITE statements supported by the VAX SCAN language. VAX SCAN macros recognize a FORMAT clause in the WRITE statement. The FORMAT clause allows the specification of a sequence of values to be placed in one record and also the width of each field. Its format is as follows: # " WRITE format-clause; FILE ’(’ file-variable’)’ Format-clause has the following syntax: FORMAT( ( exp, field_width )... ) For example: WRITE FORMAT( (a,4) (b+c,6) (a & b & c,128) ); The aim is to find WRITE statements in the input stream (that in this case is a VAX SCAN program) and ignore the rest of the input stream. A trigger macro is a good solution because it can trigger picture matching based on the presence of a token such as the keyword WRITE. Once a WRITE statement is found, you need to parse the remainder of the statement. This can best be done with syntax macros that reduce the complexity of the WRITE statement’s syntax. To start, you must define as tokens the keyword WRITE and the operands and operators of expressions: Picture-Matching Statements 5–17 SET alpha SET digit SET name_char TOKEN white_space IGNORE TOKEN write_key CASELESS TOKEN file_key CASELESS TOKEN format_key CASELESS TOKEN ops1 CASELESS TOKEN ops2 TOKEN ops3 TOKEN comma ALIAS ’,’ TOKEN semi ALIAS ’;’ TOKEN left_paren ALIAS ’(’ TOKEN right_paren ALIAS ’)’ TOKEN name TOKEN integer GROUP operand GROUP operator ( ( ( { { { { { { { { { { { { { ( ( ’A’ .. ’Z’ OR ’a’ .. ’z’ ); ’0’ .. ’9’ ) alpha OR digit OR ’$’ OR ’_’ ); { ’ ’ | s’eol’ | s’ht’ }... }; ’WRITE’ }; ’FILE’ }; ’FORMAT’ }; ’XOR’ | ’OR’ | ’NOT’ | ’AND’ }; ’+’ | ’-’ }; ’*’ | ’/’ }; ’,’ }; ’;’ }; ’(’ }; ’)’ }; alpha [ name_char ... ] }; digit... }; name OR integer ); ops1 OR ops2 OR ops3 ); Now you must construct the macros that match the syntax of the new WRITE statement: MACRO write_stmt TRIGGER { write_key [ file_key ’(’ name ’)’ ] out_field ’;’ }; MACRO out_field SYNTAX { format_key ’(’ { ’(’ exp ’,’ integer ’)’ }... ’)’ }; MACRO exp SYNTAX { simple_operand [ operator simple_operand ]... }; MACRO simple_operand SYNTAX { [ ops2 ] { ’(’ exp ’)’ | operand } }; The trigger macro is used to find the WRITE statements. The syntax macros are used to specify the format of the separate parts of the WRITE statement. 5.4.3 EXPOSE Attribute The EXPOSE attribute controls whether other trigger macros can be triggered during the matching of this macro’s picture. EXPOSE also allows the macro whose picture is being matched to be triggered recursively. EXPOSE states that any other trigger macro in the program can be triggered. The default is that triggering is prohibited. The EXPOSE attribute is important when you have two patterns that may overlap one another. Consider recognizing both italics and bolding in a typesetting language. The italics sequence starts with . The bold sequence starts with . Bolding can occur within italics and italics can occur within bolding. Without 5–18 Picture-Matching Statements EXPOSE, recognition of one construct would be prohibited while recognition of the other construct was taking place. With EXPOSE, it is possible for one trigger macro to be activated while another is activated. The following example shows EXPOSE: SET blank ( ’ ’ OR s’ht’ OR s’eol’ ); SET non_angle ( NOT( ’<’ OR ’>’ OR blank ) ); TOKEN start_bold { ’’ }; TOKEN contents { non_angle... }; TOKEN spaces IGNORE { blank... }; MACRO bold TRIGGER EXPOSE { start_bold contents... end_construct}; END MACRO; MACRO italics TRIGGER EXPOSE { start_italics contents... end_construct}; END MACRO; Example 5–7 shows the interaction to the two macros above. Example 5–7: MACRO Interaction input stream segment: fox > Token Text Matching Token Comment start_italics spaces contents spaces start_bold spaces contents spaces end_construct spaces contents spaces end_construct Ignored Bold exits - italics restored Ignored fox > Ignored Italics exits Picture-Matching Statements 5–19 5.4.4 Picture Variables The body of a macro often requires the text matched by the picture in order to generate the replacement text. Picture variables are the means of capturing the text matched by a segment of the picture. Thus, they provide the replacement algorithm with its input. There are two types of information that can be captured—the text matched and the position of the text in the input stream. Position means the line number and character position of the start of the text that is captured in the input stream. If you wish to collect information on a segment of the input stream, you must precede it with a picture variable list and a colon. The syntax format is as follows: text_variable [ , line_variable [ , column_variable ] ] : You cannot explicitly declare picture variables; their presence in the picture is an implicit declaration. The text variable is of dynamic string type. The line and column variables are of the type integer. Picture variables are local automatic variables in the macro containing their picture. A picture variable may be either a scalar or a tree, depending on its use within the picture. If a picture variable is embedded in a repetition or list construct, it is a tree. The depth of the tree is the number of repetitions or list constructs in which the variable is nested. Each nested context increases the depth by one. The data type of the subscripts for each level of the tree is integer. Although the depth of a VAX SCAN tree must ordinarily be between 1 and 100, trees that are picture variables must have a depth between 1 and 10. Example 5–8 shows these concepts. The picture variable c is not nested. Consequently, it is a scalar. The picture variable b is a 1-level tree due to repetition, whereas a is a 2-level tree due to repetition and list operators. Thus, consider the following input stream: 5–20 Picture-Matching Statements Example 5–8: Picture Variables SET alpha TOKEN left ALIAS ’[’ TOKEN right ALIAS ’]’ TOKEN comma ALIAS ’,’ TOKEN word MACRO x TRIGGER { c:{ { . . . END MACRO; ( ’a’ .. ’z’ ); { ’[’ }; { ’]’ }; { ’,’ }; { alpha... }; ’[’ b:{ a:word \ ’,’ } ’]’ }... } }; Example 5–9: Tree Subscripts and Repetition SET alpha SET digit TOKEN name TOKEN number TOKEN blank IGNORE MACRO x TRIGGER . . . END MACRO; ( ( { { { { ’a’ .. ’z’ ); ’0’ .. ’9’ ); alpha... }; digit... }; ’ ’... }; { vname:name | vnumb:number }... }; [x,xx,xxx][y][z,zzzz] The variables a, b, and c would have the following values: c b(1) b(2) b(3) a(1,1) a(1,2) a(1,3) a(2,1) a(3,1) a(3,2) [x,xx,xxx][y][z,zzzz] x,xx,xxx y z,zzzz x xx xxx y z zzzz The subscripts used to identify tree nodes correspond to the repetition during which the value was assigned. Thus, the first repetition has the subscript 1. The Nth repetition has the subscript N. Example 5–9 shows this concept. Picture-Matching Statements 5–21 The following input results in vname and vnumb having the following values: aaa 123 456 bbb vname(1) vnumb(2) vnumb(3) vname(4) aaa 123 456 bbb Vnumb( 1 ) is not a node in the vnumb tree, because the first iteration of the repetition matched name, not number. Similarly, vname( 2 ) is not a node in the vname tree because the second iteration of the repetition matched number, not name. The list operator ( \ ) is particularly useful for capturing text. Consider Example 5–10. Example 5–10: List Operator SET alpha TOKEN word TOKEN comma ALIAS ’,’ MACRO word_list1 SYNTAX . . . MACRO word_list2 SYNTAX { word_text1: word ( { { { ’a’ .. ’z’ ); alpha ... }; ’,’ }; { word_text: word } \ ’,’ }; [ ’,’ word_text2: word ]... }; By using a list operator, the text of all the word tokens can be placed in the same tree. Without the list operator, you would be forced to put the first word in a separate variable, as in the case of macro word_ list2 in the example above. The contents of a picture variable vary according to how the variable is used in the application. This is shown in the following table. Object Contents of Picture Variable TOKEN Text matched by the token 5–22 Picture-Matching Statements Object Contents of Picture Variable GROUP Text matched by any token from that group SYNTAX MACRO Text answered by the syntax macro Built-in-token Text matched by that built-in token Phrase Combination or concatenation of text matched by phrase, including any preceding or intervening ignored tokens You must answer the text that is captured in the picture variable of a syntax macro if that text is to appear in the output stream. In the following example, the ANSWER statement in the syntax macro pro answers the text that was matched by TOK1, TOK2, or TOK3. MACRO pro SYNTAX { Y: ANSWER Y; END MACRO /* pro */; { TOK1 | TOK2 | TOK3 } }; Without the ANSWER Y statement, the matched text does not appear in the output stream. This effect can result in a run time error report, if your program has resulted in the removal of the end-of-stream character (S’EOS’) character. VAX SCAN searches for the end-of-stream character in the output stream. If you have not answered with the picture variable containing the s’eos’ character, VAX SCAN searches for more text. After 10 tries, the PASENDSTM error occurs. A description of this error and all VAX SCAN error messages is in the online VAX SCAN HELP library. 5.4.5 Interaction of Macros There are three important points in the execution of a macro. The first is its activation, which begins the matching of its picture. For a trigger macro, activation results from finding its trigger in the input stream. For a syntax macro, activation results from a reference to its name during the matching of a picture. The second point is invocation, the point at which the body starts execution. For both types of macros, this occurs once the picture is successfully matched. The final point is completion, when the body has completed execution. Picture-Matching Statements 5–23 5.4.5.1 Criteria for Activating Trigger Macros Multiple trigger macros can have the same trigger. Therefore, a method is needed to select the trigger macro to activate. In fact, the method does not really choose one, but determines the order in which the macros should be tried. The trigger macros are activated sequentially until one is found that matches the input stream. Before a trigger macro can be activated, the following criteria must be met: 1. Triggering must be enabled—If no macro is active, triggering is enabled. Once a macro has been activated, it controls triggering by the EXPOSE attribute. If the macro has the EXPOSE attribute, triggering is enabled; if it does not, triggering is disabled. 2. The current token must be a trigger for the macro—If the current token is a print token, then only trigger macros with print as a trigger can be activated. 3. The current token must consist solely of text that can cause triggering—Each character in the input stream is in one of two states. The first state is capable of causing triggering and the second is not. At the start of picture matching, all the characters in the input stream are capable of causing triggering. Replacement text answered by macros is, by default, not capable of causing triggering. The current token must consist solely of text that can cause triggering for a macro to be activated. Note that the state of replacement text can be controlled. See the discussion of the ANSWER statement in Chapter 12 for details. 4. The trigger macro must be in the current scope—If no macros are active, the trigger macros in the module body are the only ones in the current scope. Once a macro is active, the following macros are in the current scope: • The children of the active macro • The active macro and its sibling macros • The ancestors of active macro and their sibling macros Example 5–11 shows children, siblings, and ancestors. 5–24 Picture-Matching Statements Example 5–11: MACRO Scope MODULE scope_example; TOKEN a { ’a’ }; TOKEN b { ’b’ }; MACRO x1 TRIGGER EXPOSE { b a... }; ! Sibling of ancestor ! of y2 END MACRO; MACRO y1 TRIGGER EXPOSE { a b... }; ! Ancestor of y2 (3rd) MACRO y2 TRIGGER EXPOSE { a a b b }; MACRO y3 TRIGGER { a b b a }; END MACRO; END MACRO; END MACRO; MACRO z1 TRIGGER EXPOSE { a \ b }; ! y2 (2nd) ! Child of y2 (1st) ! Sibling of ancestor ! of y2 (4th) MACRO z2 TRIGGER { a a b b }; END MACRO; END MACRO; END MODULE; If y2 is currently matching its picture, then it is the active macro. Its children are the macros defined within its body, in this case y3. Its siblings are other macros defined within the same macro body as y2. In this case, y2 has no siblings. Its ancestors are any macros in which it is enclosed. Y2 has one ancestor, y1. And finally, x1 and z1 are siblings of y1. The order of activation is children first, followed by progressively more global macros. If there are several macros at a particular nesting level, they are tried in lexical order. For example, if y2 is matching its picture and the next token in the input stream is an a token, criterion 1 is satisfied because y2 has the EXPOSE attribute. If y3 is active instead of y2, no triggering takes place because it does not have the EXPOSE attribute. The current token is a and the following trigger macros have a as a trigger: y1 y2 y3 z1 z2 Assume in this case that criterion 3 is met and token a is built solely of text that can cause triggering. The trigger macros that are in the current scope are as follows: • x1—a sibling of y1, y2’s ancestor Picture-Matching Statements 5–25 • • • • y1—y2’s ancestor y2—y2 itself y3—y2’s child z1—a sibling of y1, y2’s ancestor Combining the second and fourth criteria, x1 is eliminated because it does not have a as its trigger. This leaves four macros that can be tried in the following order: 1. 2. 3. 4. 5.4.5.2 y3—the child y2—the active macro or sibling of the active macro y1—the first ancestor or sibling of an ancestor z1—the second ancestor or sibling of an ancestor Failure of Picture Matching Macro pictures are compared against the input stream. If a segment of the input stream does not match the picture, the next alternative is tried. In the following example, if a is not found, look for its alternative b. If c is not found, look for d. If b or d is not found, then the macro picture fails, because there are no more alternatives to check within the picture. MACRO x SYNTAX { { a | b } [ c ] d }; When a macro picture fails, the input stream is reset to its state at the activation of the macro. If the macro was a syntax macro, look at the point where the syntax macro was referenced to see whether the reference point has an alternative. For example, the macro x is referenced from macro y as follows: MACRO y TRIGGER { trg x... ’;’ }; If the syntax macro x is successfully matched at least once, picture matching continues by trying to match the ’;’. If this is the first attempt to match syntax macro x, the trigger macro y fails. When a trigger macro fails, VAX SCAN tries to match the next trigger macro with the same trigger as the macro that failed, according to the rules discussed in the previous section. If none exist, the input stream 5–26 Picture-Matching Statements advances one token at a time until a token is found that triggers a macro and the cycle begins again. 5.4.6 Error Recovery The previous section emphasized that no transformation occurs if the input stream does not match a macro’s picture. Reconsider the example in Section 5.4.2 that extends the VAX SCAN WRITE statement to permit formatting: MACRO write_stmt TRIGGER { write_key [ file_key ’(’name’)’ ] out_field ’;’ }; MACRO out_field SYNTAX { format_key ’(’ { ’(’ exp ’,’ integer ’)’ }... ’)’ }; The following text fails to match write_stmt: WRITE FILE (a) FORMAT( (a, 4+5) (b, 4) (c 8)); The sequence 4+5 does not match the token integer. This can be unacceptable. One way to work around this is to allow the pattern 4+5. However, this does not fix the missing ’,’ required after c. A better solution is to use error recovery. Error recovery allows you to specify that your picture should not fail if it does not match. Instead, you want to advance the input stream forward to a point where picture matching can continue. You specify error recovery in macro pictures using an error context. An error context is a part of a picture where you desire error recovery. This is shown in Example 5–12. Example 5–12: Error Context MACRO { MACRO { write_stmt TRIGGER write_key ERROR:{ [ file_clause ] out_field } ’;’ }; out_field SYNTAX format_key ’(’ { ’(’ ERROR:{ exp ’,’ integer } ’)’ }... ’)’ }; Picture-Matching Statements 5–27 In the first part of Example 5–12, the error context covers the pattern between the tokens write_key and ’;’, exclusively. This includes the pattern of the syntax macro out_field that is referenced within the error context. The second example covers the pattern: exp ’,’ integer Enclosing part of a picture in braces and preceding it with the keyword ERROR, followed by a ’:’, specifies an error context. A picture may contain zero or more error contexts and they may be nested. Error contexts may occur in zero or more pictures. If pattern matching fails within an error context, an alternative outside of the context is not searched for. The context instead succeeds. Two actions occur as part of the recovery. First, the input stream is advanced so that matching can continue beyond the error context. Second, an optional user-specified procedure is called. Advancing the input stream is accomplished as follows. At the point the error occurs, one or more error contexts can be active. Consider the following input stream: WRITE FORMAT ( ( a, 4 ) ( b, 5); The error occurs when VAX SCAN encounters the ’;’ when it expects either another ’(’ or the concluding ’)’ of output_field. Only one context is active at this point, the one established by the macro write_ stmt. Consider this input stream: WRITE FORMAT ( ( c 4 )); Now the error is the missing comma following c. At the point of the error, two error contexts would be active. Each of these error contexts has one or more tokens that can legally follow the error context. These tokens are called the follow group for that context. Follow groups are required for error recovery. The follow group for write_stmt’s error context the follow group is the token ’;’ and for out_field’s error context is the token ’)’. The recovery starts by advancing the input stream. The input stream is advanced until a token in one of the active error context follow groups is found. This token is the recovery token. It is the first token built when VAX SCAN continues picture matching following error recovery. The context whose follow group contains the recovery token is the 5–28 Picture-Matching Statements context that does the recovery. If the recovery token is in more than one follow group, the most deeply nested context does the recovery. The next step in the recovery is to call the user-specified procedure, if the user has provided one. Error recovery procedures are the topic of the next section. The recovery is now complete. Picture matching continues from the recovery point. 5.4.6.1 Error Recovery Procedures To gain control during the error recovery process, specify an error recovery procedure with an error context. The procedure is called just prior to continuing picture matching so that you can issue diagnostics. You specify an error recovery procedure as shown in Example 5–13. Example 5–13: Error Recovery Procedure Form: ERROR( error-procedure( error-code ) ):{ picture } Example: MACRO xyz TRIGGER { x ERROR( announce_error( fac$_mycode ) ):{ y zz y } }; The procedure to call appears in parentheses following the keyword ERROR. You may also optionally specify a single constant in parentheses following the procedure name. This constant is intended to be used as an error code, and it must be a declared constant. It is passed to your error procedure during recovery. If it is not present, the constant is assumed to have a value of zero. VAX SCAN provides a standard error procedure, SCN$REPORT_ ERROR, that you can specify if you wish. Your error recovery procedure is called with one argument, a record containing information about the error and recovery. The program segment in Example 5–14 shows the form of the record. Picture-Matching Statements 5–29 Example 5–14: Error Recovery Packet TYPE recovery_packet: RECORD error_code: INTEGER, error_token: INTEGER, error_token_text: POINTER TO STRING, error_token_line: INTEGER, error_token_column: INTEGER, recovery_token: INTEGER, recovery_token_text: POINTER TO STRING, recovery_token_line: INTEGER, recovery_token_column: INTEGER, failing_instruction: INTEGER, global_state_block: INTEGER, END RECORD; PROCEDURE error_routine( recovery_packet ); . . . END PROCEDURE; The fields of this record have the meanings shown in Table 5–5. Table 5–5: Error Recovery Packet Meaning Record Information Contained Error_code The constant specified as an argument to the error procedure Error_token Internal name of the token in error Error_token_text Text of the error token Error_token_line Line of the start of the error token Error_token_column Column of the start of the error token Recovery_token Internal name of the recovery token Recovery_token_text Text of the recovery token Recovery_token_line Line of the start of the recovery token Recovery_token_column Column of the start of the recovery token Failing_instruction Offset of the picture-matching instruction that initiated error recovery Global_state_block Address of the global state block 5–30 Picture-Matching Statements VAX SCAN provides a function, SCN$GET_TOKEN_NAME, that returns the name of a token. This function may be used to obtain the name of a token from its internal name given in error recovery packet. The following example shows the use of this function: EXTERNAL PROCEDURE scn$get_token_name ( value integer, value integer ) OF string; PROCEDURE error_proc( err_rec: recovery_packet ); DECLARE token_name: STRING; token_name = scn$get_token_name( err_rec.error_token, err_rec.global_state_block ); WRITE token_name; END PROCEDURE; 5.4.6.2 Error Recovery Hints Error recovery should be used prudently. Once an error context is entered, it matches successfully without regard for consequences or results. For example: ERROR:{ a } | b | c This error context is not very meaningful. B or c is not tried because a must always succeed. MACRO a SYNTAX MACRO b SYNTAX { b | c }; { ERROR:{ d | e | f } }; The same is true of the previous example. A’s picture first references the syntax macro b. B cannot fail because its entire picture is an error context. Thus, the c alternative is never tried. In general, you should take care using error contexts in the case of an optional pattern, or in a pattern that has an alternative. Another point to consider is that error recovery is only entered if you are in an error context when the error is encountered. Consider the following example: MACRO print_stmt TRIGGER { ’print’ ERROR:{ exp } ’;’ }; MACRO exp SYNTAX { id | integer | ’(’ exp ’)’ }; Consider the following input stream: print a+ ; Picture-Matching Statements 5–31 The macro print_stmt does not match this input even with the error recovery present, because the character ’a’ is a valid expression. VAX SCAN is outside of error context when it tries to match ’+’ against the token ’;’. One solution to the problem is as follows: MACRO print_stmt TRIGGER { ’print’ { exp ’;’ | ERROR:{ error_token } ’;’} }; You can provide an alternative to exp that can never be matched. If exp fails to match or is not followed by the token ’;’, the second alternative is tried. This second alternative forces you into error recovery and the recovery token is ’;’. A null group is one way to define a picture that can never be matched. 5.4.7 Macro Body The macro body is a sequence of statements to generate the replacement text for the text matched by the macro picture. These statements execute once the macro picture has been matched successfully. Two of the VAX SCAN statements that can appear in a macro body, ANSWER and FAIL, are of particular interest. The ANSWER statement is the means of specifying replacement text. Text from ANSWER statements is concatenated together in the order that the ANSWER statements are executed. The aggregate text is reported as the replacement text when the execution of the body of the macro completes. The FAIL statement indicates that the active macro is to fail just as if its picture had not been matched successfully. These statements are discussed more fully in Chapter 12. 5–32 Picture-Matching Statements Chapter 6 Input and Output Streams The model for picture matching in the VAX SCAN language consists of an input stream of text being transformed into an output stream of text by one or more macros that are defined by the application. The input and output streams are each a sequence of characters that can take one of three forms: • • • File String Procedure 6.1 Input and Output Stream Form The form of the input and output stream is specified by the START SCAN statement. For example: START SCAN INPUT FILE ’stream.dat’ OUTPUT STRING my_buffer; In this particular example, the input stream is a file and the output stream is a string. In another application, both streams may be procedures. The input stream and the output stream need not be of the same form. Input and Output Streams 6–1 6.1.1 File as Input or Output Stream The most common form of input and output streams is a file. The input stream can be any VAX Record Management Service (VAX RMS) file that can be read sequentially. This includes sequential, relative, and indexed files. Sequential files can have implied or explicit carriage control. If the output stream is to be a file, VAX SCAN creates a new version of the file. The file is a sequential file with varying length records and implied carriage control (similar to what EDT or VAXTPU creates). For more information on the file attributes that VAX SCAN supports, see Appendix D. 6.1.2 String as Input or Output Stream If your VAX SCAN module is a subroutine of a larger program, using strings for the input and output streams is often convenient. A typical example may be a VAX SCAN subroutine that parses a command. The input stream is then a string variable passed to the VAX SCAN subroutine as a parameter. This parameter may be either a dynamic, fixed, or varying string, as shown in Example 6–1. 6–2 Input and Output Streams Example 6–1: String as Input Stream MODULE parse_command; /* tokens and macros to parse input stream */ . . . PROCEDURE parse( command: VARYING STRING( 256 ), unparsed: STRING, output: RECORD ... END RECORD ); START SCAN INPUT STRING command OUTPUT STRING unparsed; END PROCEDURE; END MODULE; In this example, the input stream is a varying string passed as a parameter to the procedure parse. The macros of the module analyze the command and place the results in the record output. Any part of the command that cannot be analyzed flows to the output stream, which is the dynamic string unparsed. A dynamic string is a good solution for the output stream. Using a dynamic string relieves you of the need to predict the size of the output. 6.1.3 Procedure as Input or Output Stream The final form the input and output stream can take is a procedure. This is the most flexible form of a stream, although it is also the most laborious to create. In the case of the input procedure, VAX SCAN calls the procedure for the next segment of the input stream when it needs more input. There are a variety of ways you can create that input segment, such as retrieving data from a data base, or getting it from linked lists in memory. Example 6–2 shows a VAX SCAN external definition of the calling sequence used by VAX SCAN to call your input stream procedure, and the corresponding START SCAN statement. Input and Output Streams 6–3 Example 6–2: Procedure as Input Stream EXTERNAL PROCEDURE input_stream ( REFERENCE INTEGER, REFERENCE POINTER TO FIXED STRING( 256 ) ) OF INTEGER; START SCAN INPUT PROCEDURE input_stream INPUT WIDTH 256; The calling sequence is set up in this form to give a reasonable amount of flexibility. As input to the procedure input_stream, the two arguments give the length and address of a buffer (fixed string) that can be used to hold the next input line. The buffer is allocated by VAX SCAN as part of the START SCAN statement. The size of this buffer is dictated by the INPUT WIDTH clause of the START SCAN statement. Your input procedure is not, however, required to use the buffer that is supplied. The only requirement is that the two parameters contain the correct length and address of the buffer containing the input line when the procedure returns. Thus, the buffer returned may be a buffer allocated by the input stream procedure. An output stream procedure is necessary if OUTPUT STRING or OUTPUT FILE do not produce the output format you need. For example, if your output needs to be a VAX RMS stream file, you need to either write an output procedure in a language that supports the creation of stream files, or call a procedure that interfaces directly with VAX RMS. The following example shows a VAX SCAN external definition of the calling sequence used by VAX SCAN to call your output stream procedure, and the corresponding START SCAN statement: EXTERNAL PROCEDURE output_stream ( REFERENCE INTEGER, REFERENCE FIXED STRING( 256 ) ); START SCAN OUTPUT PROCEDURE output_stream; The external procedure output_stream has two parameters shown in parentheses. The first parameter gives the number of characters in the buffer. The second of the two parameters is the buffer containing the text that is to be written to the output stream. 6–4 Input and Output Streams 6.2 VAX SCAN Literals in the Input Stream The three special VAX SCAN literals, S’SOS’ (start of stream), S’EOL’ (end of line), and S’EOS’ (end of stream), play an important role in the input stream. Regardless of the form of the input stream, VAX SCAN places an S’SOS’ character as the first character in the input stream. Similarly, it appends an S’EOS’ character to the end of the input stream. S’EOL’ characters are inserted in the input stream by VAX SCAN to mark record boundaries. Thus, your input stream may be a file containing the following four records: record record record record 1: 2: 3: 4: Four score and seven years ago This example would appear to your VAX SCAN application as the following stream: Four score and seven years ago Represents an S’SOS’ character. Represents an S’EOL’ character. Represents an S’EOS’ character. The input stream consists of the records of the file, with S’EOL’ characters marking the end of each record. If your input stream is a procedure, the input stream is derived by VAX SCAN making repetitive calls to the procedure you specify. Each call to the procedure provides the next segment of the input stream. (The exact calling sequence used by VAX SCAN to call this procedure is specified with the START SCAN statement.) Your input procedure could return the following two segments before indicating that the end of stream had been reached: segment 1: Our fathers segment 2: brought forth on this continent For this example, the input stream would appear to your VAX SCAN application as follows: Our fathers brought forth on this continent Input and Output Streams 6–5 Represents an S’SOS’ character. Represents an S’EOL’ character. Represents an S’EOS’ character. VAX SCAN inserts no S’EOL’ characters in the input stream if it takes the form of a string. The presence of these special VAX SCAN characters in the input stream can be very useful. If you need to do some processing at the start or end of the input stream, or at the start of each line, you can create tokens using these characters and have the tokens activate macros. This is shown in Example 6–3. Example 6–3: Special VAX SCAN Characters in Input Stream TOKEN prompt { { s’eol’ | s’sos’ } ’$’ }; TOKEN eof { s’eos’ }; MACRO find_prompt { prompt }; END MACRO; MACRO find_end_file { eof }; CALL print_summary; ANSWER s’eos’; END MACRO; ! $ in column 1 6.3 VAX SCAN Literals in the Output Stream Two of the special VAX SCAN literals also play an important role in the output stream. First, the picture matching process is terminated when VAX SCAN attempts to place an S’EOS’ character in the output stream. The S’EOS’ is not actually placed in the output stream. Thus, your output file, string, or buffer that is sent to the output procedure never contains an S’EOS’ character. 6–6 Input and Output Streams Because an S’EOS’ character terminates picture matching in VAX SCAN programs, you should use care when designing macros that match S’EOS’ characters. Consider the following example: TOKEN eof { s’eos’ }; MACRO end_of_file_processing TRIGGER { eof }; CALL process_collected_data; END MACRO; The picture of the macro end_of_file_processing removes the S’EOS’ character from the input stream, and the body of the macro never puts it back. Thus, an S’EOS’ character is never placed in the output stream. Your program then begins to loop. Once end_of_file_processing terminates, VAX SCAN tries to build another token. Accordingly, it requests the next line of the input stream. Because there is none, an end of input stream is reported again and is mapped to an S’EOS’ character. This S’EOS’ character causes an eof token to be built that triggers end_of_file_processing and, thus, the loop goes around. The loop is not infinitely executed, though. There are VAX SCAN library routines that manage the input stream and that limit the number of times an end of stream can be signaled. (The actual setting is 10.) Once that limit is reached, they signal the error SCN$_PASENDSTM. This situation can also arise if you have a token of the following form: TOKEN white_space { { s’eol’ | ’ ’ | s’ht’ | s’eos’ }... }; Any token that contains S’EOS’ . . . results in the error SCN$_ PASENDSTM being signaled. Thus, this construct should be avoided. The second consequence of S’EOS’ terminating picture processing is that you can terminate picture matching by answering an S’EOS’ character. For example, you may have an application designed to extract modulelevel comments from a set of VAX SCAN programs. By convention, these comments always occur before the first form feed. Thus, there is no point in scanning the text that follows the first form feed. Your application would include the following code: Input and Output Streams 6–7 TOKEN form_feed { s’ff’ }; MACRO find_form_feed TRIGGER { form_feed }; /* answer an end of stream character to stop picture /* matching - could also do a STOP SCAN ANSWER s’eos’; END MACRO; The second special VAX SCAN character that plays an important role in the output stream is S’EOL’. This character marks the points in the output stream where record breaks should occur. The sequence of events that occurs when an S’EOL’ is encountered in the output stream is dependent on the form of the output stream: • • • If the output stream is a file, VAX SCAN writes the text prior to the S’EOL’ to the file as a record, throws away the S’EOL’ (thus, it never appears in the file), and starts a new record with the text following the S’EOL’ character. If the output stream is a procedure, upon encountering an S’EOL’ character, VAX SCAN calls the output procedure, passes the text prior to the S’EOL’, throws away the S’EOL’, and starts a new record with the text following the S’EOL’ character. If the output stream is a string, the S’EOL’ characters are not removed. They appear as just another character in the output string. Like S’EOS’, S’EOL’ characters are useful in controlling the picture matching process: • You can use the S’EOL’ character to cause a pattern to be found only if it occurs at the start or the end of a line. For example: SET start_line ( s’sos’ OR s’eol’ ); SET non_start_line ( NOT( start_line OR s’eos’ ) ); TOKEN fortran_comment { start_line ’C’ non_start_line... }; • • You can merge input stream records to a single output stream record by removing the S’EOL’ between them. You can split an input stream record into multiple output stream records by adding S’EOL’ characters. For example: 6–8 Input and Output Streams MACRO find_example_command TRIGGER { example_command [ title_key ’=’ s:str ] [ size ’=’ i:int ] }; ANSWER ’.b’, s’eol’; ! .b ANSWER ’.c; ’, s, s’eol’; ! .c; The Example Title ANSWER ’.skip ’, i; ! .skip 20 END MACRO; The final special VAX SCAN character, S’SOS’, has little significance in the output stream. When encountered in writing the output stream, it is discarded after being recognized. 6.4 Redefining the VAX SCAN Literals The VAX SCAN special character literals, S’SOS’, S’EOL’, and S’EOS’, are each mapped to one of three DEC Multinational Character codes. The default mapping is shown in Table 3–4. These default mappings may not be appropriate for your application. For example, the VAX SCAN S’EOL’ character is a DEC Multinational S’NEL’ character. Your application may have attached special meaning to S’NEL’, such as a delimiter for commands, that you do not wish to confuse with record boundaries. Using the REDEFINE directive discussed in Section 12.3, you can redefine each of the special VAX SCAN literals to have an alternate value. The following example defines S’EOL’ to be a nul: REDEFINE s’eol’ = s’nul’; 6.5 The Width of the Input and Output Streams VAX SCAN maintains internal buffers for reading the input stream and writing the output stream. These buffers have a default size or width of 132 characters, but can be controlled by your application. If the input stream is a file, the input stream buffer is the buffer used by VAX RMS to read the records of the file. If that buffer is not large enough to hold the input stream record, VAX RMS signals an error. For example, if the maximum length of the records in your file is 512 characters, you can set the size of the input buffer as follows: START SCAN INPUT FILE ’my$file’ INPUT WIDTH 512; Input and Output Streams 6–9 If the output stream is a file, the output stream buffer is used to collect records to be written to your output file. There are three possible events that can trigger the writing of this buffer to the output file: 1. S’EOL’ placed in the output buffer 2. S’EOS’ placed in the output buffer 3. A full output buffer The first two events occur automatically in most applications. The third event occurs when your output lines exceed the width of the output buffer. In this case, VAX SCAN writes the full buffer and places the balance of the line in the next record. Thus, no output is lost; long lines are wrapped into the next record. This can be avoided by increasing the width of the output buffer. For example, if the maximum length of a line that your application finds is 256 characters, place the following in your program: START SCAN OUTPUT FILE ’my$file’ OUTPUT WIDTH 256; If the input stream is a procedure, an input stream buffer is passed to your procedure to be filled in with the next line. The width of this buffer is as specified by the INPUT WIDTH clause of the START SCAN statement. The default width is 132 characters. Your input procedure can deal with the width of this buffer in several ways. The easiest method is to use the INPUT WIDTH clause to ensure that the input buffer is big enough to hold the maximum line. Or, you may choose not to use the standard input buffer at all. Consider an input stream that consists of a linked list of records of the following form: TYPE input_record: RECORD next: POINTER TO input_record, length: INTEGER, data: POINTER TO FIXED STRING( 0 ), END RECORD; The input stream is already in memory; thus, you need not copy it to the input stream buffer. Instead, you can use the buffers where the input stream currently resides. The program segment in Example 6–4 shows this. 6–10 Input and Output Streams Example 6–4: Linked List in Input Stream EXTERNAL current_input_record: POINTER TO input_record; CONSTANT scn$_endinpstm EXTERNAL INTEGER; CONSTANT ss$_normal EXTERNAL INTEGER; START SCAN INPUT PROCEDURE input_stream INPUT WIDTH 0; PROCEDURE input_stream( length: REFERENCE INTEGER, buffer: REFERENCE POINTER TO FIXED STRING( 0 ) ) OF INTEGER; IF current_input_record = NIL THEN length = 0; RETURN scn$_endinpstm; END IF; length = current_input_record->.length; buffer = current_input_record->.data; current_input_record = current_input_record->.next; RETURN ss$_normal; END PROCEDURE; The output stream buffer that is passed to your output stream procedure behaves similarly to the output file case. If the line does not fit in the buffer, your output procedure is called several times for that record. On the first call to your procedure, a full output stream buffer is passed to your procedure. On subsequent calls, the balance of the input line is passed to your procedure. An input stream buffer is not allocated if the input stream is a string. In this case, the INPUT WIDTH clause is ignored. If the output stream is a string, an output buffer is allocated to collect the output stream. The contents of the buffer are appended to the output string as each output line is generated. The size of the output buffer is not critical in this case. If an output line is too long to fit in the buffer, the line is appended to the output string in segments. The more critical concern is that your output string is appropriate for collecting the output stream. A dynamic string is perhaps the best solution—you do not have to predict the size of the output string and then allocate that much storage. A varying string is a good solution if you can accurately predict the size of the output string. A fixed string is not a good solution because information on output stream length is corrupted by blank padding. Input and Output Streams 6–11 Chapter 7 Variables Chapter 5 discussed objects such as sets and tokens that support the picture matching part of the VAX SCAN language. This chapter discusses the data objects that support the algorithmic part of the VAX SCAN language. These data objects are variables. VAX SCAN has 10 variable types which can be divided into the following 3 categories: • • • Scalar variable types Structured variable types File variable type The scalar variable types hold a single value. A comprehensive set of operators can be performed on these values. (See Chapter 11.) The scalar variable types include the following: • • • • • • Integer variables Boolean variables String variables Fill variables Pointer variables Treeptr variables The structured variable types can hold one or more values, but the operations that can be performed on these values are limited. Structured variable types include the following: • Tree variables Variables 7–1 • • Record variables Overlay variables The third category of variable types consists of the file variable type. See Section 7.10 for more information on file variables. 7.1 Integer Variables An integer variable stores a whole number. Integer variables are represented in VAX SCAN as signed longwords. Thus, their value must be in the range of –2,147,483,648 to 2,147,468,647. The initial value of an integer variable is zero. The code in Example 7–1 declares an integer variable and assigns it a value. Example 7–1: Integer Variable DECLARE count: INTEGER; count = 2000; ! declare an integer ! assign integer the value 2000 7.2 Boolean Variables A Boolean variable stores either the value TRUE or FALSE. They are implemented as a byte of storage in VAX SCAN; however, only the low order bit is used. A Boolean variable has an initial value of FALSE. The code in Example 7–2 declares a Boolean variable and assigns it a value. 7–2 Variables Example 7–2: Boolean Variable DECLARE okay: BOOLEAN; okay = TRUE; ! declare a Boolean ! assign Boolean the value TRUE 7.3 String Variables A string variable stores a sequence of zero or more characters. All string variables have a current and maximum length. The current length is the number of characters currently stored in the string. The maximum length is the maximum number of characters that can be stored in the string. String variables consist of the following three types, and each type has different rules defining its current and maximum length: • • • Fixed string—Has a constant current length that isequal to the maximum length, which you specify. The greatest maximum length you can specify is 65535 characters. The maximum length, and therefore current length, is part of the string’s declaration. Because the string always contains this number of characters, if a sequence of characters shorter than this length is assigned to the string, the sequence is left justified within the string and the remainder of the string is blank filled. Fixed strings are initialized to a sequence of blanks. Varying string—Has a maximum number of 65535 characters that is specified by the declaration of that string. However, the current length of the string is the length of the last sequence of characters assigned to the string. Varying strings have an initial value of the null string ( " ). When declaring a varying string, make sure you specify the largest number of characters it can contain. The maximum number you can specify is 65535. Dynamic string—Has a maximum number of 65535 characters that is not declared and is limited only by a maximum of 65535 characters. The current length of the string is the length of the last sequence of characters assigned to the string. Dynamic strings have an initial value of the null string ( " ). Variables 7–3 Example 7–3: String Variables DECLARE f: FIXED STRING( 40 ); DECLARE v: VARYING STRING( 4 ); DECLARE d: DYNAMIC STRING; f = ’less than 40 characters’; v = ’12’; d = ’1234567890’; ! ! ! ! ! ! ! fixed length of 40 characters maximum length of 4 characters maximum length of 65535 characters length is still 40 characters last 17 characters are blanks current length is 2 characters current length is 10 characters The code in Example 7–3 declares several string variables and assigns them values. 7.4 Fill Variables A fill variable is a sequence of bytes. The contents of the sequence of bytes is never interpreted by VAX SCAN. VAX SCAN has no operators that take a fill variable as an operand. Fill variables make it easier for VAX SCAN to interface with other languages. VAX SCAN has a limited set of data types compared to other languages. For instance, there are no floating-point or packed decimal variables. In a multi-language environment, VAX SCAN may need to look at a record created by FORTRAN. The record may contain fixed strings and also floating-point numbers; the VAX SCAN program is only interested in the fixed strings. VAX SCAN uses fills to occupy the space in the record of values that have no equivalent type in VAX SCAN. The number of bytes in a fill variable is defined by its declaration. This number cannot exceed 65535 bytes. Fill variables have an initial value of a sequence of S’NUL’ characters. The declaration in Example 7–4 declares a record containing fills. 7–4 Variables Example 7–4: Fill Variable DECLARE accounting_packet: RECORD process_name: FIXED STRING( 12 ), process_id: INTEGER, user_name: FIXED STRING( 20 ), time_stamp: FILL(8), billed: BOOLEAN, END RECORD; ! reserve 8 bytes 7.5 Pointer Variables A pointer is a variable that holds the address of another variable. Pointers in VAX SCAN are bound to a particular type of variable. The type of the variable is specified in the declaration of the pointer. This binding limits the variables that the pointer can point to. If a pointer is bound to the dynamic string type, it can only hold the address of a dynamic string. It cannot hold the address of a fixed string. The initial value of a pointer is NIL. Example 7–5 uses pointers to show a linked list in VAX SCAN. The procedure traverses the linked list performing an undesignated action on each element. 7.6 Tree Variables A VAX SCAN tree is a structured variable that can hold zero or more values of the same type. A tree diagram is shown in Figure 7–1. Variables 7–5 Example 7–5: Pointer Variables MODULE linked_list; TYPE node: RECORD next_node: POINTER TO node, ! pointer to next element data: FIXED STRING( 100 ), ! data in the element END RECORD; PROCEDURE walk_list( list_head: POINTER TO node ); DECLARE current_node: POINTER TO node; current_node = list_head; WHILE current_node <> NIL; . . current_node = current_node -> .next_node; END WHILE; END PROCEDURE; END MODULE; Figure 7–1: Tree Diagram ARTFILE ZK–4293–85 The values stored in the tree are represented at the bottom in parentheses. In this example, the values are integers. Each of these values has a unique path from the root of the tree, that is, from the top of the diagram. For example, the path from the root to the rightmost value is as follows: 7–6 Variables my_tree –> ’111’ –> 1000 –> ’y’ Specifying the path to the values at the base of the tree is how you access the values in the tree. The notation for specifying the path in this example is as follows: my_tree( ’111’, 1000, ’y’ ) The name of the tree comes first, in this case my_tree. The path to the value is then specified in parentheses. Thus, replacing the rightmost value in the tree my_tree with the leftmost value is done as follows: my_tree( ’111’, 1000, ’y’ ) = my_tree( ’1010’, -1, ’a’ ); There are several terms used in describing trees: • • • • Subscript—A subscript is one of the values used in constructing the path. Thus, ’111’, 1000, and ’y’ are each subscripts. Depth—The depth of a tree is the number of subscripts used in the path to specify a value. Because three subscripts are needed to specify a value in my_tree, its depth is three. Level—If a tree has a depth of n, it is an n level tree. The term level is also used to describe a particular set of subscripts in the tree. The levels are numbered from top to bottom. For instance, the first level of the tree is right below the root and has the subscripts ’1010’ and ’111’ in Figure 7–1. The first level of the tree has string subscripts; thus, the first subscript in the path for this tree is always a string. Node—The tree is built from nodes. Each subscript identifies a node. The node at the top of the tree is called the root node and is labeled in the diagram with the name of the tree. Leaf nodes are the nodes at the base of the tree, and each has an associated value. The remaining nodes in the tree are called interior nodes. Each interior node contains the links to the nodes at the next level of the tree. Given these terms, you can now further examine the properties of a VAX SCAN tree. The declaration of a tree specifies: • • • The name of the tree The depth of the tree The type of the subscripts at each level Variables 7–7 • The type of the leaf node values The declaration of the example tree is as follows: DECLARE my_tree : TREE( STRING, INTEGER, STRING ) OF INTEGER; The list in parentheses following the name of the tree specifies both the depth and the type of the subscripts. Because there are three types specified, the depth of the tree is three. The leftmost type in the list gives the type of the subscripts for the first level. The type of the second level subscripts is given next, and so on. The type of the values stored in the tree follows the keyword OF. The subscripts of a level in a tree must be either of type INTEGER or type STRING. The values stored in the tree can be of any type. The depth of a VAX SCAN tree must be between 1 and 100. Trees that are picture variables must have a depth of between 1 and 10. Trees have several other interesting properties. First, nodes in the tree do not exist until they are assigned a value. Thus, a VAX SCAN tree does not have a fixed number of nodes. A tree starts with no nodes; each time a new unique path is specified as the target of an assignment, a new leaf node is added to the tree. Nodes can be removed from the tree with the PRUNE statement. Adding leaf nodes to a tree is shown in the following example: DECLARE population: TREE( STRING, STRING ) OF INTEGER; /* At this point the tree holds no values */ population( ’New Hampshire’, ’Nashua’ ) = 90000; /* Now the tree holds 1 value */ population( ’Massachusetts’, ’Maynard’ ) = 35000; /* Now the tree holds 2 values */ population( ’New Hampshire’, ’Nashua’ ) = 91000; /* Tree still holds 2 values, an existing value was replaced */ Second, the nodes at their specific level of the tree have an order. They are sorted according to subscript. If the type of the subscripts is integer, the nodes at that level are maintained in numeric order. If the type of the subscripts is string, the nodes at that level are maintained in collating sequence order. This order is shown in Figure 7–1. The first level of the tree has two string subscripts. ’1010’ comes before ’111’ in the collating sequence, so it appears to the left of ’111’. The second level of the tree has integer subscripts. The subscripts beneath ’1010’ are in numeric order. Similarly, the subscripts beneath ’111’ 7–8 Variables are in numeric order. Assigning two new values to the tree changes the structure as shown in Figure 7–2. Figure 7–2: Modified Tree Diagram ARTFILE ZK–4294–85 The first assignment adds a node just before my_tree(’111’,1000,’x’), and the second assignment creates three nodes in the center of the tree. VAX SCAN provides a set of built-in functions for traversing a tree. These functions make it easy to use VAX SCAN trees for sorting. The built-in functions are described in Chapter 11 and in the next section on treeptr variables. 7.7 Treeptr Variables The value of a treeptr is the address of a node in a tree. Treeptr variables are much like pointers—they both have addresses as values. A pointer holds the address of a variable. A treeptr is restricted to holding the address of a node in a tree. The initial value of a treeptr is NIL. Like a pointer, a treeptr is bound to a type of object. There is a difference, however; whereas a pointer is bound to a type of variable, a treeptr is bound to a level in a tree. The following declarations show this binding further: Variables 7–9 DECLARE population: TREE( STRING, STRING ) OF INTEGER; DECLARE state_ptr: TREEPTR( STRING )TO TREE( STRING ) OF INTEGER; DECLARE city_ptr: TREEPTR( STRING )TO INTEGER; The first treeptr, state_ptr, is bound to the first (top-most) level of a tree of the same form as population. The second treeptr, city_ptr, is bound to the second level of a tree of the same form as population. The treeptr declaration specifies the form of the tree to which it is bound. The treeptr is bound to the first level of the tree specified. The tree defined in the declaration of state_ptr has the same form as population; thus, state_ptr can point to any node at the first level of population. The tree defined in the declaration of city_ptr has the same form as the second level of population. This is clearer if an equivalent declaration of population is shown: DECLARE population: TREE( STRING ) OF TREE( STRING ) OF INTEGER; From this you can see that a 2-level tree is really a tree of trees. The declaration of city_ptr defined a tree of the same form as the second level tree in population. Thus, city_ptr can point to any node at the second level of population. Neither of these treeptr variables is limited to pointing at a node in population. They can point to any node of the form specified by their declaration. Thus, state_ptr could point to a node in the third level of the following tree: DECLARE x: TREE( INTEGER, INTEGER, STRING, STRING ) OF INTEGER; Because the third level of x is TREE( STRING, STRING ) OF INTEGER, that is the form of the tree for state_ptr. Treeptr variables are useful for traversing trees. As an example, consider a tree that holds the keywords of a language, and the number of times each one is used. This tree would have the form shown in Figure 7–3. 7–10 Variables Figure 7–3: Keyword Tree DECLARE keyword: TREE( STRING ) OF INTEGER; keyword | ----------------------------------------------| | | | | ’ABS’ ’ALLOCATE’ ’FREE’ ... ’WHILE’ ’WRITE’ (0) (4) (4) (9) (8) The information in the tree can be printed without knowing all the subscripts. Treeptr variables and built-in functions provided by VAX SCAN allow you to print out the information in a tree. You can do this with the code in Example 7–6. Example 7–6: Tree Traversing DECLARE keyword: TREE( STRING ) OF INTEGER; DECLARE t: TREEPTR( STRING ) TO INTEGER; /* initialize the treeptr T to point to the first node */ t = FIRST( keyword ); WHILE t <> NIL; /* print out info for this node */ WRITE ’keyword: ’, SUBSCRIPT( t ), ’occurred ’, VALUE( t ), ’ times’; /* advance to the next node in the tree */ t = NEXT( t ); END WHILE; The treeptr variable is declared on the second line of the code segment. Its value is the address of a node in a tree. The built-in function FIRST is used in the example to start T pointing at keyword ( ’ABS’ ). Two other built-in functions are used to display information about a node. SUBSCRIPT returns the subscript of the node pointed to by a treeptr variable and VALUE returns the value of a leaf node pointed to by a treeptr. Another built-in function, NEXT, is used to get the next node in the tree. Variables 7–11 Treeptr variables are similar to pointers because they both hold the address of other objects. Pointers can be used to point at strings, records, or entire trees. Treeptr variables, on the other hand, are restricted to holding the address of a node in a tree. Like a pointer, a treeptr variable is bound to a type of object. In the case of a treeptr, this object is a level in a tree. DECLARE t: TREEPTR( STRING ) TO INTEGER; | | subscript type -------| | lower levels of tree --------------- The subscript type of the nodes that this treeptr can point to is written in parentheses following the keyword TREEPTR. A description of the tree below this node follows the keyword TO. Because keyword has STRING subscripts, T is declared as TREEPTR( STRING ). The description of the data in a leaf in keyword follows TO. The following example shows the declaration of two treeptr variables for the tree population discussed in Section 7.6: DECLARE population: TREE( STRING, STRING ) OF INTEGER; DECLARE state_ptr: TREEPTR( STRING ) TO TREE( STRING ) OF INTEGER; DECLARE city_ptr: TREEPTR( STRING ) TO INTEGER; Population is a 2-level tree; thus, a different treeptr variable is needed to describe each level of the tree. State_ptr points to nodes with STRING subscripts. Below these nodes in the tree is yet another level of the tree described as TREE( STRING ) OF INTEGER. City_ptr points to nodes in the second level of the tree. These nodes also have STRING subscripts. These are leaf nodes; thus, following TO is the type of value in the leaves. Neither of these treeptr variables is limited to pointing to a node in population. They can point to any nodes of the form specified by their declaration. Thus, state_ptr could point to a node in the third level of the following tree: DECLARE x: TREE( INTEGER, INTEGER, STRING, STRING ) OF INTEGER; This is because the third and fourth levels of x have the same form as population. 7–12 Variables As shown earlier, treeptr variables are used to traverse trees. Most of the tree built-in functions return a treeptr variable. NEXT, for example, returns the treeptr of the next node in a tree. Example 7–7 traverses the tree population using treeptr variables. Example 7–7: Tree Traversing Using TREEPTR DECLARE population: TREE( STRING, STRING ) OF INTEGER; DECLARE state_ptr: TREEPTR( STRING ) TO TREE( STRING ) OF INTEGER; DECLARE city_ptr: TREEPTR( STRING ) TO INTEGER; /* get the first state */ state_ptr = FIRST( population( ) ); WHILE state_ptr <> NIL; /* get the first city in the current state */ city_ptr = FIRST( state_ptr ); WHILE city_ptr <> NIL; WRITE ’the population of ’, SUBSCRIPT( city_ptr ), ’, ’, SUBSCRIPT( state_ptr ), ’ is ’, VALUE( city_ptr ); /* get the next city in the current state */ city_ptr = NEXT( city_ptr ); END WHILE; /* get the next state */ state_ptr = NEXT( state_ptr ); END WHILE; The treeptr variables in Example 7–7 keep track of our position in the tree. Built-in functions change the nodes pointed to by the treeptr variables. The FIRST built-in function takes a tree node as an argument and returns the treeptr of the first node at the next level of the tree. The program uses FIRST twice. The first assignment statement uses FIRST to initialize state_ptr to point to the first node of the first level (the first state). FIRST is also used to find the node for the first city within each state. The NEXT built-in function returns a treeptr to the next node at the same level. This built-in is used at the end of each of the WHILE loops to advance to the next city or state. If a next node does not exist, NEXT returns NIL. Variables 7–13 The WRITE statement uses the built-in functions SUBSCRIPT and VALUE to retrieve the subscript and value of a node. 7.8 Record Variables A record is a structured variable that can hold values of different types. Each of the values that make up a record is called a component. A record declaration specifies the following: • • • • The The The The name of the record name of each record component type of each record component order of the components in the record The syntax for a record is as follows: RECORD {component-name : type ,} . . . END RECORD Example 7–8 declares a record and assigns values to several of its components. 7–14 Variables Example 7–8: Record Variables DECLARE my_record: RECORD name: RECORD first: STRING(10), last: STRING(20), END RECORD, age: INTEGER, employed: BOOLEAN, address: FILL(20), END RECORD; my_record.name.last = ’Olsen’; my_record.employed = TRUE; This record has four components: NAME, a record; AGE, an integer; EMPLOYED, a Boolean; and ADDRESS, a fill. NAME is further divided into two components, FIRST and LAST, that are both fixed strings. Not every type of value can be a component of a record. Record components are limited to the following types: • • • • • • • • • Integer Boolean Fill Pointer Treeptr Fixed string Varying string Record Overlay Dynamic strings, trees, and files cannot be components of a record. A record specifies the name of each of its components. The names of components must be unique within a record, but they can be repeated in different records. Example 7–9 shows this concept. Variables 7–15 Example 7–9: Record Variable Component Names TYPE family: RECORD name: STRING( 20 ), father: RECORD name: STRING( 15 age: INTEGER, parent: POINTER TO END RECORD, mother: RECORD name: STRING( 15 age: INTEGER, parent: POINTER TO END RECORD, child: RECORD name: STRING( 15 age: INTEGER, family: POINTER TO END RECORD, child: ! error RECORD name: STRING( 15 age: INTEGER, family: POINTER TO END RECORD, END RECORD; ), family, ), family, ), family, ), family, The name name is repeated five times in this declaration. Each is within a different record and, thus, correct. The name child appears twice as the name of two components within the family record. This is an error. The initial value of a record is all zeros. This has the effect of initializing the components as shown in Table 7–1. 7–16 Variables Table 7–1: Record Variable Initial Value Type Initial Value Storage Size Integer 0 4 bytes Boolean FALSE 1 byte Fill( n ) n S’NUL’ n bytes Pointer NIL 4 bytes Treeptr NIL 4 bytes Fixed string( n ) n S’NUL’ n bytes Varying string( n ) Null string n+2 bytes Record Size of its components Overlay Size of largest component Table 7–1 also gives the amount of storage allocated by VAX SCAN for particular components of a record. Records start on byte boundaries. No alignment to the next word, longword, or quadword boundary is done. Components are allocated one after another with no alignment gaps. Thus, the size of a record can be computed by adding the size of each component. 7.9 Overlay Variables Overlays are structured variables with many similarities to records. An overlay is a means of overlaying storage for one or more variables, thus making more efficient use of that storage. Where a record uses an amount of storage equal to the sum of all its components, an overlay variable uses only the storage required by its largest component. The other smaller components share this storage. The syntax diagram for the overlay data type is as follows: OVERLAY {component-name : type ,} . . . END OVERLAY Variables 7–17 Example 7–10 compares a record and an overlay variable that are used for the same purpose. Example 7–10: Comparison of a Record Variable with an Overlay Variable RECORD street:STRING(30), city: STRING(20), zip: FILL(5), END RECORD; OVERLAY street:STRING(30), city: STRING(20), zip: FILL(5), END OVERLAY; The resulting storage use is as shown in Figure 7–4. Figure 7–4: Overlay Storage ARTFILE ZK–4295–85 Overlay variables can have the following types of components: • • • • • • 7–18 Variables Integer Boolean Fill Pointer Treeptr Fixed string • • • Varying string Record Overlay Note that an overlay variable cannot have a dynamic string, file, or tree for a component. An overlay variable can be a component of a record. Example 7–11 shows a use of overlay variables. Example 7–11: Use of Overlay Variables TYPE boat: RECORD make: VARYING STRING(25), model: VARYING STRING(25), price: INTEGER, length:INTEGER, kind: INTEGER, desc: OVERLAY sail: RECORD sail_area:INTEGER, beam: INTEGER, END RECORD, power:RECORD horsepower:INTEGER, beam: INTEGER, END RECORD, canoe:RECORD construction:INTEGER, beam: INTEGER, END RECORD, END OVERLAY, END RECORD; The advantage of using an overlay variable in this example is that a boat is described by a single record, not three (one for sailboats, another for power boats, another for canoes). The various data we wish to hold for each type of boat is expressed using the overlay variable. Each instance of this record can describe only one kind of boat at one time. The integer variable kind indicates what type of boat is currently stored in the record and, thus, whether the overlay currently holds sail, power, or canoe information. Variables 7–19 7.10 File Variables A file variable is used to reference VAX/VMS files. File variables do not have a value. Instead, they have a state of either open or closed. When in the open state, they are bound to a VAX/VMS file that you can either read or write. A file variable can be passed as a parameter, or can be the object of a pointer, in addition to specifying a file to use in an I/O operation. Example 7–12 shows reading a VAX/VMS file using file variables. Example 7–12: File Variables MODULE filevar; DECLARE infile : FILE; !+ this is the file variable DECLARE inbuf : VARYING STRING (80); PROCEDURE demovar MAIN; OPEN FILE( infile ) AS ’[]filevar.scn’ FOR INPUT; READ FILE( infile ) inbuf; WHILE NOT ENDFILE(infile); WRITE inbuf; !+ will write to sys$output READ FILE( infile ) inbuf; END WHILE; CLOSE FILE( infile); END PROCEDURE /* demovar */; END MODULE /* filevar */; As shown in Example 7–12, a file variable must be declared to be used in a program. Once declared, a file variable can be opened and closed, and your program can read from it and write to it. Table 7–2 summarizes the operations that can be performed with the file variable. Table 7–2: File Variable Operations 7–20 Variables Operation Effect OPEN Binds to VAX/VMS file and opens the file for use Table 7–2 (Cont.): File Variable Operations Operation Effect CLOSE Dissociates with VAX/VMS file and closes for use READ Reads from VAX/VMS file WRITE Writes to VAX/VMS file ENDFILE Checks if at end of file The initial status of a file variable is closed. Once opened by an OPEN statement, it remains open until either a CLOSE statement is executed, or the program terminates. The ENDFILE built-in function returns a value of FALSE if the file variable is closed. If it is open for input, then ENDFILE may be used to test for the end-of-file condition. If it is open for output, ENDFILE returns a value of FALSE. The list of operations in Table 7–2 does not include operations common to many of the other data types, such as assignment and comparison. The rationale for not permitting these operations on files is that the operations could have multiple meanings. Assigning one file variable to another could mean duplicating the contents of the file, or it could just be two variables bound to the same file. VAX SCAN does not define the operations. Pointers to file variables, however, is one way of binding two variables to the same file. In addition, because pointers can be assigned and compared, you now have a mechanism for assigning files and determining if two files are alike. The use of pointers is shown in the following example. Variables 7–21 DECLARE fp: POINTER TO FILE; DECLARE in_file: STRING; DECLARE command_file: FILE; IF need_input_file THEN ALLOCATE fp; READ PROMPT( ’input file; ’) in_file; OPEN FILE( fp-> ) AS in_file FOR INPUT; ELSE fp = POINTER( command_file ); END IF; . . . CLOSE FILE( command_file ); IF fp <> POINTER( command_file ) THEN CLOSE FILE( fp-> ); FREE fp; END IF; 7–22 Variables Chapter 8 Declaration of Variables This chapter discusses how to declare the variables described in Chapter 7. The following three statements are used to declare variables: • • • DECLARE TYPE CONSTANT 8.1 Specification of Variable Type Central to the declaration of any variable is its type. The specification of a type in VAX SCAN is the same in all statements. The following diagram shows the syntax of a type specification. Declaration of Variables 8–1 8 INTEGER > > > > BOOLEAN > " # > > > > > > STRING DYNAMIC > > > > > " # > > > > > > STRING ( ct-integer-expression ) FIXED > > > > < VARYING STRING ( ct-integer-expression ) > > FILL ( ct-integer-expression ) > > > > POINTER TO type > > > > TREEPTR ( subscript-type ) TO type > > > > tree-type > > > > record-type > > > > overlay-type > > > > : type-name FILE Tree-type has the following syntax: TREE ( subscript-type ,... ) OF type Subscript-type has the following syntax: n STRING o INTEGER Record-type has the following syntax: RECORD { component-name : type , } ... END RECORD Overlay-type has the following syntax: OVERLAY { component-name : type , } ... END OVERLAY 8–2 Declaration of Variables 9 > > > > > > > > > > > > > > > > > > > > > > > > > > = > > > > > > > > > > > > > > > > > > > > > > > > > > ; 8.2 DECLARE Statement The DECLARE statement is used to declare new variables. The DECLARE statement specifies the following: • • • The name of the variables The type of the variables The storage class of the variables The syntax of the DECLARE statement is as follows: DECLARE variable-name , . . . : 2 STATIC 66 AUTOMATIC 64 COMMON GLOBAL 3 77 75 type ; EXTERNAL One or more variables may be declared with a single DECLARE statement. The names of the variables appear to the left of the colon ( : ), separated by commas. As discussed in Section 4.5, the variables are local to the block in which they are declared. A variable can be declared with one of the five storage attributes listed in the syntax diagram. These attributes control the type of storage allocated for the variable. If no storage attribute is specified, variables declared in the module body have the STATIC attribute and variables declared in a procedure or macro body have the AUTOMATIC attribute. The AUTOMATIC attribute says to allocate storage for the variable when the procedure or macro in which it is declared is invoked. The storage is deallocated when the macro or procedure completes execution. The AUTOMATIC attribute is useful in limiting the amount of storage used concurrently by the program. Only the variables of the procedures and macros that are currently invoked will be allocated. The AUTOMATIC attribute is also useful when writing recursive procedures or macros. The STATIC attribute says to allocate storage for the variable when the program starts execution. The storage is deallocated when the program terminates. The STATIC attribute is useful for sharing data between procedures or macros in the same module without passing parameters. Declaration of Variables 8–3 The COMMON attribute is much like the STATIC attribute. The storage for the variable is allocated for the duration of the program. In addition, all variables in other modules, procedures, and macros with the same name and the COMMON attribute will share the same storage as this variable. The GLOBAL and EXTERNAL attributes work together. Like the STATIC attribute, GLOBAL and EXTERNAL indicate that the storage for the variable is allocated for the duration of the program. Like the COMMON attribute, this pair allows the sharing of data between procedures and macros. With COMMON storage, however, all the declarations of the variable are alike. With GLOBAL and EXTERNAL, on the other hand, only one declaration has the GLOBAL attribute. It ‘‘owns’’ the storage. Any number of other procedures and macros that need to reference the GLOBAL variable may do so by declaring the same variable with the EXTERNAL attribute. The COMMON, GLOBAL, and EXTERNAL attributes are useful for sharing data between procedures or macros in different modules. The choice between COMMON or GLOBAL and EXTERNAL may depend on the other modules in your program. If they are written in FORTRAN or PL/I, COMMON is the natural choice. If they are written in BLISS or MACRO, GLOBAL and EXTERNAL is the natural choice. If they are written in VAX SCAN, it is up to you. The final part of a DECLARE statement is the type specification. Example 8–1 shows variable declarations. 8.3 TYPE Statement The TYPE statement declares a user-defined type. The user-defined types declared by the TYPE statement can be used like predefined types, such as INTEGER and STRING, to declare variables or other user-defined types. The syntax of the TYPE statement is as follows: TYPE type-name : type ; 8–4 Declaration of Variables Example 8–1: Variable Declarations MODULE declarations; ! these are module declarations DECLARE a,b,c: STATIC INTEGER; ! declare 3 static integers ! this tree is static because it is declared in the module body DECLARE key: TREE( STRING ) OF STRING; ! this record is common and thus can be referenced in other modules DECLARE buffer: COMMON RECORD key1: INTEGER, field1: FILL( 20 ), key2: STRING( 5 ), field2: FILL( 40 ), END RECORD; PROCEDURE sub; ! these declarations are local to sub and are ! automatic by default DECLARE result: BOOLEAN; DECLARE list_head: EXTERNAL POINTER TO STRING( 10 ); END PROCEDURE; END MODULE; Example 8–2: User-Defined Type Declaration TYPE point: RECORD x: INTEGER, y: INTEGER, END RECORD; TYPE box: RECORD lower_left: upper_right: END RECORD; TYPE zip_code: TYPE byte: TYPE table: ! x coordinate ! y coordinate POINT, POINT, ! x,y pair of lower left corner ! x,y pair of upper right corner INTEGER; FILL( 1 ); TREE( STRING ) OF STRING(10); User-defined types are typically used to define frequently used types, as shown in Example 8–2. Declaration of Variables 8–5 Presumably, you would then declare variables of these user-defined types. A type declaration has two advantages. First, it saves retyping the same type specification. Second, it ensures all declarations are consistent. Example 8–3 shows declarations based on point and box. Example 8–3: User-Defined Variable Type PROCEDURE box_center ( input_box: box ) OF point; /* This procedure calculates the geometric center */ /* of the box and returns it as a point. */ DECLARE center: point; center.x = (input_box.upper_left.x + input_box.lower_right.x)/2; center.y = (input_box.upper_left.y + input_box.lower_right.y)/2; RETURN center; END PROCEDURE; A user-defined type retains the characteristics of the predefined type used to define it. Thus, zip_code retains the properties of an integer. Consequently, any variable declared of type zip_code can be added to any other integer. In general, a type must be defined before it is referenced in another statement such as DECLARE, PROCEDURE, or TYPE. It may, however, be referenced in another TYPE statement as the object of a pointer before being defined. This exception is needed to accommodate a case such as the one shown in Example 8–4. This example defines two records, each of which contains pointers to the other type of record. There is no way to avoid a forward reference. Note that the forward reference is permitted only if the type is the object of a pointer. Parent must be defined, however, before child can be used in a declaration. 8–6 Declaration of Variables Example 8–4: Multiple Reference of User-Defined Type MODULE linked_lists; TYPE child: RECORD next: POINTER parent: POINTER data: STRING( END RECORD; TYPE parent: RECORD next: POINTER first: POINTER data: STRING( END RECORD; END MODULE; TO child, TO parent, 30 ), TO parent, TO child, 190 ), 8.4 CONSTANT Statement A CONSTANT statement assigns a name to a literal and has the following syntax: ( = ct-expression ) CONSTANT constant-name GLOBAL = ct-expression ; EXTERNAL type The syntax diagram shows the three classes of constants: local, external, and global. Local constants are local to the block in which they are declared. Global and external constants permit the sharing of constants between modules. A local constant declaration consists of a name and a value. The type of the value becomes the type of the constant. Example 8–5 shows several local constant declarations. A global constant declaration also consists of a name and a value, with the addition of the keyword GLOBAL. The type of the value becomes the type of the constant. In the case of global constants, however, the type is limited to integer or Boolean. Example 8–6 shows two global constant declarations. Declaration of Variables 8–7 Example 8–5: Local Constant Declarations CONSTANT CONSTANT CONSTANT CONSTANT greeting = ’Welcome to VAX SCAN’; greeting_len = length( greeting ); yes = TRUE; max_size = min( greeting_len*4, 256 ); ! ! ! ! string constant integer constant Boolean constant integer constant Example 8–6: Global Constant Declarations CONSTANT internal_error GLOBAL = 5 ; CONSTANT failure GLOBAL = FALSE; ! integer constant ! Boolean constant Example 8–7: External Constant Declarations CONSTANT ss$_normal EXTERNAL INTEGER; CONSTANT internal_error EXTERNAL INTEGER; CONSTANT failure EXTERNAL BOOLEAN; ! integer constant ! integer constant ! Boolean constant An external constant declaration consists of a name, a type, and the keyword EXTERNAL. The value of the constant is defined in another module, procedure, or macro as a global constant. External constants, like global constants, are limited to the types integer and Boolean. Example 8–7 shows several external constant declarations. Assigning a name to a literal has two advantages. First, it makes your code easier to read, as shown in Example 8–8. Assigning a name to a literal also allows you to change a constant. For example, you may need to change the value of red to 5. Because red is a constant, you can change its value and recompile. If the literal 5 was used, you would need to identify all the 5s in your program and change only those that represent the color red. 8–8 Declaration of Variables Example 8–8: Naming Literal Constants CONSTANT CONSTANT CONSTANT . . . IF color THEN . . . END IF; blue = 1; red = 2; white = 3; = white ! easier to read than color = 3 Declaration of Variables 8–9 Chapter 9 Procedures A VAX SCAN procedure is similar to a function in mathematics. It has a set of input variables called parameters and performs some computations using the values of these parameters. The following three VAX SCAN statements are used to declare procedures: • • • PROCEDURE declaration EXTERNAL PROCEDURE declaration FORWARD PROCEDURE declaration A PROCEDURE declaration declares both the interface to the procedure and the algorithm that executes when the procedure is invoked. An EXTERNAL PROCEDURE declaration declares the interface to a procedure that is defined in a separate module. A FORWARD PROCEDURE declaration declares the interface to a procedure that will be defined later in the current module. 9.1 PROCEDURE Declaration A procedure is a block-structured construct that starts with a PROCEDURE declaration. The PROCEDURE declaration itself specifies the following: • • • The name of the procedure The attributes of the procedure The names and types of the procedure’s parameters Procedures 9–1 • The type of the procedure’s result The END PROCEDURE statement ends a procedure block. Between these two statements are zero or more declarations and executable statements that are called the procedure body. The procedure body states the algorithm the procedure performs. The syntax of a PROCEDURE block is as follows: " PROCEDURE procedure-name " MAIN # (parameter , . . . ) # OF type ; 2 variable-declaration 66 type-declaration 66 constant-declaration 64 procedure-declaration external-declaration " # " forward-declaration executable-statement 3 77 77 75 ... # ... END PROCEDURE ; Parameter has the following syntax: " VALUE # type REFERENCE DESCRIPTOR Procedures fall into two categories: functions and subroutines. A function is a procedure that returns a value. The result clause introduced by the keyword OF specifies the type of the result. A subroutine does not return a value and, consequently, does not have a result clause. Example 9–1 shows a subroutine, and Example 9–2 shows a function. parameter-name : 9–2 Procedures Example 9–1: Procedure Subroutine PROCEDURE i_min ( op1: INTEGER, op2: INTEGER, min_value: INTEGER ); /* i_min is a subroutine with 3 parameters. /* All 3 parameters are of type integer. IF op1 <= op2 THEN min_value = op1; ELSE min_value = op2; END IF; END PROCEDURE; Example 9–2: Procedure Function PROCEDURE s_min( op1: STRING, op2: STRING ) OF STRING; /* s_min is a function with 2 parameters. /* Both parameters are of type dynamic string. /* The result of s_min is also a dynamic string. IF op1 <= op2 THEN RETURN op1; ELSE RETURN op2; END IF; END PROCEDURE; Subroutines are invoked with the CALL statement. Functions are invoked as operands in expressions. The value that the function returns is used as the value of the operand in the expression. Example 9–3 shows an invocation of the procedures declared in Examples 9–1 and 9–2. VAX SCAN has only one procedure attribute, MAIN. The MAIN attribute states that this procedure starts the execution of the VAX SCAN program. The main procedure may be either a subroutine or a function. The VAX/VMS operating system expects the main procedure to return the status of the program as an integer. If the main procedure is a subroutine, it returns SS$_NORMAL. Procedures 9–3 Example 9–3: Procedure Invocation DECLARE a,b,c: INTEGER; DECLARE x,y: STRING; /* Call i_min to compute the minimum of c and b*b. /* The result is placed in a. CALL i_min( c, b*b, a ); /* Determine which string comes first in the collating sequence /* x or ’abc’. The result is placed in y. y = s_min( x, ’abc’) & ’ comes first’; Example 9–4: Parameter Passing in Procedures PROCEDURE i_min ( op1: INTEGER, op2: INTEGER, min_value: INTEGER ); /* i_min is a subroutine with 3 parameters. /* All 3 parameters are of type integer. IF op1 <= op2 THEN min_value = op1; ELSE min_value = op2; END IF; END PROCEDURE; DECLARE a,b,c,d: INTEGER; a = 1; b = 2; d = 5; CALL i_min( a, b, c ); CALL i_min( c, d, c ); A procedure declared in the module body is a global procedure; that is, it can be called by procedures or macros in other modules. Procedures declared within a macro or procedure are local to that macro or procedure. 9.1.1 Parameters Most procedures require input values to perform their task, and some procedures output values as a result of their execution. Parameters are a mechanism for transferring these values between a procedure and its caller. Using the i_min subroutine again, Example 9–4 shows the use of parameters. 9–4 Procedures The procedure i_min has three parameters: • • • op1 op2 min_value It stores the minimum of the first two parameters in the third parameter. Op1 and op2 are input parameters, providing the procedure with information it needs to do its job. Min_value is the output parameter that reports the result of the computation. When the procedure is invoked, the actual arguments in the CALL statement or function reference are bound to the parameters in the procedure. A reference to the first parameter is then equivalent to a reference to the first actual argument. Therefore, in the first call to i_min, a is bound to op1, b is bound to op2, and c is bound to min_ value. In the second call to i_min, c is bound to op1, d is bound to op2, and c is bound to min_value. The binding lasts for the duration of the call to the procedure. Each parameter has both a name and a type. The name of the parameter is used in the body of the procedure to refer to the variable that is bound to the parameter. The type of the parameter, like the type of a variable, describes the value of the parameter and the operations that can be performed on the parameter. The actual arguments in a procedure reference must match the parameters of that procedure both in number and type. The meaning of ‘‘match’’ is given in Table 9–1. Table 9–1: Procedure Parameter Types Parameter Type Requirements of Actual Argument Integer Must be integer Boolean Must be Boolean Pointer to type Must be a pointer to the same type or NIL Treeptr to type Must be a treeptr to the same type or NIL Fill( n ) Must be fill( n ) Procedures 9–5 Table 9–1 (Cont.): Procedure Parameter Types Parameter Type Requirements of Actual Argument Fixed string Must be a string1 Varying string Must be a string1 Dynamic string Must be a string1 Record Must be a compatible record2 Overlay Must be a compatible overlay2 Tree Must be a tree with an identical structure File Must be a file 1 If the actual is not of the same type and maximum length as the parameter, a temporary of the type of the parameter is created. The actual is assigned to the temporary and the temporary becomes the actual argument. 2 Chapter 12 gives the rules for record and overlay compatibility. Only the root and leaf nodes of a tree can be passed as a parameter. For leaf nodes, the value of the leaf node is passed. For the root, the entire tree is passed. Any component of a record or overlay can be passed as a parameter. The formal parameter must have a compatible form. 9.1.2 Passing Mechanisms VAX SCAN will pass actual arguments so they can be modified by the procedure being called. Exceptions to this rule are literals and strings that do not exactly match the type of the parameter. In this case, a copy of the argument is passed. Thus, the original argument cannot be modified by the procedure being called. In a multilanguage environment, it is important to know how parameters are passed, because no two languages do it the same way for all types. To make interfacing with procedures written in other languages easier, parameters can take one of three attributes specifying the passing mechanism. The three attributes are as follows: • 9–6 Procedures DESCRIPTOR—The address of a descriptor for the actual argument is passed. The descriptor holds the address of the value, its data type, and often other type-sensitive information. • • REFERENCE—The address of the actual argument is passed. VALUE—The value of the actual argument is passed. Arguments passed either by descriptor or reference can be input or output parameters. Arguments passed by value can only be input parameters. Not all of the VAX SCAN types can be passed or received using all of the passing mechanisms. Table 9–2 shows the passing mechanisms and the default supported for each type. Table 9–2: Parameter-Passing Mechanisms Type Descriptor Reference Value Integer No Default Yes Boolean No Default Yes Pointer No Default Yes Treeptr No Default Yes Fill No Default No Fixed string Yes Default No Varying string Yes Default No 1 No No Dynamic string Default Yes Record No Default Overlay No Default No Tree No Default No File No Default No 1 Only to an externally defined procedure 9.2 EXTERNAL PROCEDURE Declaration The EXTERNAL PROCEDURE declaration declares a procedure that is defined in a separate module. It does this by specifying the following: • • The name of the external procedure The types of the procedure’s parameters Procedures 9–7 • The type of the procedure’s result The following is the syntax diagram of an EXTERNAL PROCEDURE declaration: EXTERNAL PROCEDURE procedure-name [ ( external-parameter ,... ) ] [ OF type ]; External-parameter has the following syntax: " VALUE # type REFERENCE DESCRIPTOR As the syntax shows, the formats of a PROCEDURE declaration and an EXTERNAL PROCEDURE declaration are almost identical. The EXTERNAL PROCEDURE declaration omits the MAIN attribute and the names of the parameters. None of these are needed to invoke the procedure. To invoke an external procedure, you need to know only the procedure’s name, the order and type of its parameters, and its result type if it is a function. Example 9–5 shows several EXTERNAL PROCEDURE declarations. Example 9–5: EXTERNAL PROCEDURE Declarations EXTERNAL PROCEDURE i_min ( INTEGER, INTEGER, INTEGER ); EXTERNAL PROCEDURE s_min ( STRING, STRING ) OF STRING; EXTERNAL PROCEDURE walk_tree( TREE( STRING, INTEGER ) OF my_record); I_min and s_min show external procedure declarations for the subroutine and function shown in Examples 9–2 and 9–3. Walk_tree declares an external subroutine that has a single parameter, a 2-level tree of records. Normally, a procedure and the EXTERNAL PROCEDURE declaration for that procedure appear in different modules. However, VAX SCAN allows them to be in the same module. This allows the external declarations for a set of subroutines to be placed in an include file. In a module that references the procedures, this include file provides the necessary information for calling the procedures. In a module that 9–8 Procedures defines the procedures, the external declarations are checked against the procedure declarations for consistency. Thus, you have a mechanism for ensuring that your procedure references are consistent with the procedure definition, even if the references and definitions are in separate modules. 9.3 FORWARD PROCEDURE Declaration A FORWARD PROCEDURE declaration declares the form of a procedure that is defined later in the same module. In VAX SCAN, objects must be defined before they are referenced. This is not always possible with procedures. For example, procedure a may call procedure b and procedure b may then call procedure a. There is no way to define b before a and also a before b. The FORWARD PROCEDURE declaration solves this circular definition problem. In fact, you can use it to create a table of routines at the top of their modules. The syntax of the FORWARD PROCEDURE declaration is as follows: FORWARD PROCEDURE procedure-name [ ( forward-parameter ,... ) ] [ OF type ] ; Forward-parameter has the following syntax: " VALUE # type REFERENCE DESCRIPTOR The syntax is identical to that of the EXTERNAL PROCEDURE declaration except for the leading keyword, that is, FORWARD, instead of EXTERNAL. The syntax is identical for a good reason—both describe the form of a procedure defined elsewhere. In the case of EXTERNAL PROCEDURE, the procedure is defined in another module. In the case of FORWARD PROCEDURE, the procedure is defined later in the same module. Example 9–6 shows the FORWARD PROCEDURE declaration. Procedures 9–9 Example 9–6: FORWARD PROCEDURE Declaration TYPE node: RECORD next_node: POINTER TO node, key: VARYING STRING( 20 ), node_data: FILL( 25 ), END RECORD; /* Table of Procedures in Module */ FORWARD PROCEDURE insert_in_list ! subroutine to insert node ( POINTER TO node, ! list head node ); ! item to insert FORWARD PROCEDURE find_in_list ! function to find a node ( POINTER TO node, ! list head VARYING STRING( 20 ) ) ! key for node to find OF node; ! returns the node found 9–10 Procedures Chapter 10 Expressions Chapter 7 described variables and the types of values that they can hold. This chapter describes how to use an expression to create a new value. An expression consists of one or more values that are combined using a set of operators to produce new values, as shown in Example 10–1. Example 10–1: Creating New Values with Expressions CONSTANT characters_per_line = 80; DECLARE lines_per_page: INTEGER; lines_per_page = 60; WRITE characters_per_line * lines_per_page; In this example, the keyword WRITE precedes an expression containing two values and an arithmetic operator. The value of the constant characters_per_line and the value of the variable lines_per_page are separated by the multiplication operator ( * ). The value of the expression is 4800. You can use an expression almost anywhere a value is required in a VAX SCAN statement. Thus, you can use an expression in an assignment statement to create the value assigned to a variable. You can also use an expression to create the value of a subscript in a tree node reference. Expressions 10–1 To effectively use expressions, you must know how to reference values and you must understand the operators that can combine these values to produce new values. 10.1 Operators Each of the expression operators takes a fixed number of input values that it uses to create a new value. Both the input and created values usually are of a specific type. For example, multiplication has two integer input values and creates an integer value. Table 10–1 lists all the VAX SCAN expression operators, the data type of their input values, and the data type of the value created. The input values are referred to as the operands of the operator, and the created value is referred to as the result of the operator. Table 10–1: Expression Operators Operator Meaning Result [] Substring String 1 Operand1: String Operand2: Integer Operand3: Integer + Unary plus Integer Operand1: Integer – Unary minus Integer Operand1: Integer * Multiplication Integer Operand1: Integer Operand2: Integer / Division Integer Operand1: Integer Operand2: Integer + Addition Integer Operand1: Integer Operand2: Integer – Subtraction Integer Operand1: Integer Operand2: Integer & Concatenation String Operand1: String Operand2: String 1 ‘‘String’’ Data Type of Operand in this chart refers to any of the string types, that is, fixed, varying, or dynamic. They may be used in any combination. 10–2 Expressions Table 10–1 (Cont.): Expression Operators Operator Meaning Result Data Type of Operand = Equal to Boolean Operand1: Any type2 Operand2: Same as Operand13 == Exact equal to Boolean Operand1: String Operand2: String <> Not equal to Boolean Operand1: Any type Operand2: Same as Operand1 < Less than Boolean Operand1: String or Integer Operand2: Same as Operand1 > Greater than Boolean Operand1: String or Integer Operand2: Same as Operand1 <= Less than or equal to Boolean Operand1: String or Integer Operand2: Same as Operand1 >= Greater than or equal to Boolean Operand1: String or Integer Operand2: Same as Operand1 NOT Complement4 Integer Boolean Operand1: Integer or Boolean AND Intersection4 Integer Operand1: Operand2: Operand1: Operand2: Integer Integer Boolean Boolean Operand1: Operand2: Operand1: Operand2: Integer Integer Boolean Boolean Operand1: Operand2: Operand1: Operand2: Integer Integer Boolean Boolean Boolean Union4 OR Integer Boolean Exclusive OR4 XOR Integer Boolean 2 ‘‘Any type’’ in this chart says that any VAX SCAN type is valid as an operand except FILE. 3 ‘‘Same as operand1’’ means that operand1 can be one of several types. Operand2 must be the same type as operand1. 4 The type of the result for NOT, AND, OR, and XOR depends on the type of the operands. If the operands are integer, the result is integer. If the operands are Boolean, the result is Boolean. Expressions 10–3 10.1.1 Substring Operator The VAX SCAN substring operator ( [ ] ) extracts a sequence of characters from a string value. The substring operator has the following three forms: Form 1: Operand1[ operand2 ] Form 2: Operand1[ operand2 .. ] Form 3: Operand1[ operand2 .. operand3 ] The sequence of characters is extracted from operand1. Form 1 extracts the single character at position operand2. Form 2 extracts the character sequence starting at the character position operand2 through the end of the string. Form 3 extracts the character sequence starting at position operand2 through position operand3. The leftmost character of a string is referred to by position 1. The restrictions placed on the operands are shown in Table 10–2. Table 10–2: Substring Operator Restrictions Operand1 Fixed, varying, or dynamic string Operand2 Integer such that 0 < operand2 <= LENGTH( operand1 )1 Operand3 Integer such that 0 <= operand3 <= LENGTH( operand1 )1 1 ‘‘LENGTH’’ is a built-in function that returns the current length of a string. If operand2 is not a valid position in the character string (less than 1 or greater than the length of the string), an error is issued. If operand3 is greater than or equal to zero but less than operand2, the resulting substring is the null string. If operand3 is greater than the length of the string or negative, an error is issued. Figure 10–1 shows the use of substring operators. 10–4 Expressions Figure 10–1: Use of Substring Operators Initial Conditions DECLARE DECLARE DECLARE DECLARE fix var dyn i = fix: var: dyn: i: FIXED STRING( 10 ); VARYING STRING( 10 ); DYNAMIC STRING; INTEGER; = ’0123456789’; = ’abcde’; = ’We hold these truths’; 5; ! current length is 10 ! current length is 5 ! current length is 20 Expression Value of Expression fix[ 3 ] dyn[ 10.. ] var[ 2..4 ] ’0123456’[ i ] fix[ i-1..i+1 ] var[ i*2 ] dyn[ 4..0 ] ’2’ ’hese truths’ ’bcd’ ’4’ ’345’ error: i*2 > length( var ) ’’ (null string) 10.1.2 Arithmetic Operators The VAX SCAN arithmetic operators are unary plus ( + ), unary minus ( - ), addition ( + ), subtraction ( - ), multiplication ( * ), and division ( / ) . They have essentially the same meaning as in mathematics. The arithmetic operators take integer operands and produce integer results. (VAX SCAN does not have floating-point numbers.) When using the arithmetic operators, you should note the following: • • • Integer values have a restricted range of –2,147,483,648 to 2,147,483,647. Operations resulting in a value outside this range cause an overflow error message to be issued. Fractional numbers cannot be represented. Thus, 5/2 equals 2, not 2.5, because the fractional result of any division is truncated. Division by zero also causes an error message to be issued. Expressions 10–5 Figure 10–2 shows the use of arithmetic operators. Figure 10–2: Use of Arithmetic Operators Initial Conditions DECLARE i,j,k: INTEGER; i = 5; j = 1000; k = -20; Expression Value of Expression i - j + k i*(-j)/k i / +j j * j * j * j k/0 -1015 or 5 - 1000 + (-20) 250 or 5 * (-1000) / -20 0 or 5 / +1000 error: overflow error: divide by zero 10.1.3 Concatenation The VAX SCAN concatenation operator ( & ) combines the values of two strings and has the following format: operand1 & operand2 The resulting value of the concatenation operator is the value of operand2 appended to the value of operand1. Concatenation is only valid for string operands. Figure 10–3 shows the results of concatenation. 10–6 Expressions Figure 10–3: Results of Concatenation Initial Conditions DECLARE fix: FIXED STRING( 10 ); DECLARE var: VARYING STRING( 10 ); DECLARE dyn: DYNAMIC STRING; fix = ’0123456789’; var = ’abcde’; dyn = ’We hold these truths’; ! current length is 10 ! current length is 5 ! current length is 20 Expression Value of Expression fix & var dyn & ’ to be self’ ’0123456789abcde’ ’We hold these truths to be self’ 10.1.4 Relational Operators A relational operator causes two values to be compared. The result of all relational operators is a Boolean value, that is, TRUE or FALSE. The relational operators are of the following three categories: • • • Equal to ( = ) and Not equal to ( <> )—These operators check whether the two operands have the same value. You can compare any two values of the same type using these operators. This includes record types, but excludes tree types. You cannot compare whole trees, just the values of their leaves. Less than ( < ), Greater than ( > ), Less than or equal to ( <= ), and Greater than or equal to ( >= )—These operators compare two values that must have an order. The types in VAX SCAN that have an order are integer (numeric order) and strings (collating sequence order). Exactly equal to ( = = )—This operator is specifically for string variables. For two string variables to be exactly equal, they must have the same value and the same length. Other operators extend the shorter of the two string operands with blanks so that it is the same length as the longer string operand, before doing the comparison. Expressions 10–7 Table 10–3 gives some further type-specific rules for the relational operators. Table 10–3: Relational Operator Rules Type Operand Rules Integer No restrictions String Shorter operand is blank padded to the length of the longer operand before comparison Boolean = and <> only Pointer = and <> only, must point to same type Treeptr = and <> only, must point to same type Fill = and <> only, must have the same length Record = and <> only, must have compatible components Tree Not allowed File Not allowed Overlay = and <> only, must have compatible components Figure 10–4 shows the use of relational operators. 10–8 Expressions Figure 10–4: Use of Relational Operators Initial Conditions DECLARE DECLARE DECLARE DECLARE var: in: p: pp: VARYING STRING( 10 ); INTEGER; POINTER TO INTEGER; POINTER TO INTEGER; var = ’abcde’; in = 100; p = pointer( in ); pp = NIL; Expression Value of Expression p = pp in > 1000 var <= ’abcde’ var == ’abcde ’ FALSE FALSE TRUE FALSE 10.1.5 Logical Operators Logical operators combine Boolean values to create a Boolean value. The logical operators are AND, OR, XOR, and NOT. They are defined by Table 10–4. Table 10–4: Logical Operators NOT TRUE is FALSE NOT FALSE is TRUE TRUE AND TRUE is TRUE TRUE AND FALSE is FALSE FALSE AND TRUE is FALSE FALSE AND FALSE is FALSE TRUE OR TRUE is TRUE TRUE OR FALSE is TRUE FALSE OR TRUE is TRUE FALSE OR FALSE is FALSE TRUE XOR TRUE is FALSE TRUE XOR FALSE is TRUE FALSE XOR TRUE is TRUE FALSE XOR FALSE is FALSE The logical operators take either Boolean or integer values as operands. If the operands are Boolean, Table 10–4 states the result. This concept is shown in Example 10–2. Expressions 10–9 Example 10–2: Logical Operators DECLARE person: RECORD name: VARYING STRING( 40 ), employed: BOOLEAN, salaried: BOOLEAN, END RECORD; IF person.employed AND person.salaried THEN . . . END IF; Example 10–3: Logical Operators Used with Integer Operands DECLARE a,b,c: INTEGER; a = 10; ! A is FFFF FFFF FFFF FFFF b = 22; ! B is FFFF FFFF FFFF FFFF c = a OR b; ! C is FFFF FFFF FFFF FFFF c = a AND b; ! C is FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFT FFFT FFFF TFTF FTTF TTTF or 30 FFTF or 2 The IF statements are executed only if both person.employed and person.salaried have the value TRUE. If the operands are integer, the integer values are treated as a sequence of 32 Boolean values. That is, each bit that makes up the binary value representing the integer is treated as a Boolean value. If a bit is 1, it is TRUE. If a bit is 0, it is FALSE. For an AND operation, the 32 bits of operand1 are bit intersected with the 32 bits of operand2 to produce the 32 bits of the result as shown in Example 10–3. 10–10 Expressions 10.2 References A reference is the means of specifying a variable. Variables are referenced for the following two reasons: • • To retrieve their value To set their value Whether a variable is referenced to retrieve its value or to set its value can only be determined from context, as shown in the assignment statement in Example 10–4. Example 10–4: Variable References DECLARE a,b: INTEGER; a = b; The reference on the left side of the equal sign, a, specifies the variable whose value is to be set. The reference on the right side of the equal sign, b, specifies the variable whose value is to be retrieved. References have several forms: • • • • • • Scalar Record Tree Function Built-in function Pointer This section discusses each form in detail. Expressions 10–11 10.2.1 Scalar Reference A scalar reference is the simplest of all references. It refers to a scalar variable. To reference a scalar variable, use its name as shown in Example 10–5: Example 10–5: Scalar Variable Reference DECLARE a,b: STRING; a = b & a; This example contains three scalar references: a and b in the expression b & a and a to the left of the equal sign ( = ). The two references in the expression to the right of the equal sign specify the values to be used as the operands of the concatenation operator ( & ). The reference to the left of the equal sign specifies the variable to be assigned the result of the concatenation. 10.2.2 Record Reference A record reference specifies the component in a record that you wish to retrieve or set. It is more complicated than a scalar reference because a record contains multiple components, and you must specify the one you want. You reference a record component by specifying the path through the record hierarchy to find that component. Each of the components is separated with a dot ( . ) as shown in Example 10–6. 10–12 Expressions Example 10–6: Record Reference TYPE circle: RECORD radius: INTEGER, center: RECORD x_coord: INTEGER, y_coord: INTEGER, END RECORD, END RECORD; DECLARE c1,c2: circle; c1.center.x_coord = 100; c1.center.y_coord = c1.center.x_coord + 100; c2.center = c1.center; The DECLARE statement declares two records of the type circle called c1 and c2. The example contains the following three assignments: 1. The first assignment uses a record reference to set the x coordinate of the c1 circle. The record reference specifies that the value 100 be stored in the x_coord component of the center component of the c1 record. 2. The second assignment includes a record reference for retrieving the value stored in the first assignment. The value of this record reference is added to 100 and stored in the y coordinate of the c1 record. 3. The final assignment shows that record references need not be to scalar values. The center record of c1 is assigned to the center record of c2. 10.2.3 Tree Reference A tree reference specifies a node in a tree. Specifying a node in a tree requires giving the path of subscripts from the root of the tree to the node of interest. The name of the tree is given first, followed by a list of subscripts in parentheses that give the path. This is shown in Example 10–7. Expressions 10–13 Example 10–7: Tree Reference TYPE person: RECORD last_name: VARYING STRING( 20 ), first_name: VARYING STRING( 15 ), END RECORD; DECLARE phone_book1: TREE( STRING, STRING ) OF INTEGER; DECLARE phone_book2: TREE( INTEGER ) OF PERSON; DECLARE first, last: STRING; phone_book1( ’Smith’, ’William’ ) = 1230000; phone_book2( 1230000 ).last_name = ’Smith’; phone_book2( 1230000 ).first_name = ’William’; phone_book1( ’Doe’, ’John’ ) = 5246000; phone_book2( 5246000 ).last_name = ’Doe’; phone_book2( 5246000 ).first_name = ’John’; IF EXISTS( phone_book1( last, first ) ) THEN WRITE first , ’ ’ , last , ’ number is: ’, phone_book1( last, first ); END IF; The first six assignment statements store values in trees. A tree reference to the left of the equal sign designates the leaf node that is to be given a value. The last tree reference retrieves the value of a leaf node. A tree reference in an expression or as the target of an assignment must always reference a leaf node in a tree. It must not reference interior nodes. In expressions and assignments, you retrieve or set the values in the tree, and these values are associated with the leaf nodes. Tree references to interior nodes are permitted in a few special contexts. Many of the tree-traversing built-in functions accept arbitrary nodes as arguments. EXISTS in the example is such a built-in function that checks whether a node exists in a tree. The example is checking for the presence of a leaf node. However, the EXISTS built-in function in the following example is also valid. It checks whether phone_ book1( last ) exists in the tree. EXISTS( phone_book1( last ) ) 10–14 Expressions Example 10–8: Passing a Tree as a Parameter CALL process_tree( phone_book1, ! legal phone_book1( last ), ! NOT legal phone_book1( last, first )); ! legal The second special case is passing an entire tree as a parameter to a procedure, as shown in Example 10–8. To pass an entire tree, you must specify the root node, as in the case of the first parameter. You cannot pass an interior node of a tree. 10.2.4 Function Reference A function reference invokes a function procedure. The value returned by the function is the value of the function reference. Most references can be used to retrieve a value, or to specify a variable to be set. This is not true of a function reference. It can be used only to retrieve a value. A function reference consists of the name of the function followed in parentheses by a list of the arguments to the function. The parentheses are required even if the function has no parameters. Example 10–9 defines several functions and shows references to these functions. Expressions 10–15 Example 10–9: Function Reference EXTERNAL PROCEDURE LIB$INDEX( STRING, STRING ) PROCEDURE COPY( count:INTEGER, seq:STRING ) OF DECLARE i: INTEGER; DECLARE s: STRING; FOR i = 1 to count; s = s & seq; END FOR; RETURN s; END PROCEDURE; DECLARE x,y: STRING; x = copy( 3, ’abc’ ) & copy( 4, ’xy’ ); ! y = x[ LIB$INDEX( x, ’cxy’ ) .. ]; ! OF INTEGER; STRING; x is ’abcabcabcxyxyxyxy’ y is ’cxyxyxyxy’ The function copy is referenced twice in the first assignment statement. Each reference returns a string that is used as an operand of the concatenation operator. LIB$INDEX is an external function that returns an integer. The result of the LIB$INDEX function reference is used as an operand of the substring operator. When a function reference is encountered in an expression, the arguments are evaluated from left to right. The arguments must match the parameters of the function both in number and type. For more information on invoking a function, see Chapter 9. 10.2.5 Built-In Function Reference Built-in functions are function procedures supplied by the VAX SCAN language to perform commonly needed operations. Because they are provided as part of the language, built-in functions do not require a procedure declaration. These functions are described individually in Chapter 11. A built-in function reference has the same form as a function reference, that is, the name of the built-in function, followed by the list of arguments to the function enclosed in parentheses. Example 10–10 shows references to several built-in functions. 10–16 Expressions Example 10–10: Built-In Function Reference DECLARE date: STRING; DECLARE i: INTEGER; /* TIME returns dd-mmm-yyyy hh:mm:ss */ /* Extract the date */ date = TIME(); date = date[ 1 .. INDEX( date, ’:’)-4 ]; i = MOD( ABS( i ), 512 ); Example 10–11: Pointer Reference TYPE rec_type: RECORD comp1: INTEGER, comp2: BOOLEAN, END RECORD; DECLARE fix: STRING( 10 ); DECLARE rec: rec_type; DECLARE tree: TREE( STRING ) OF STRING; DECLARE pfix: POINTER TO STRING( 10 ); DECLARE prec: POINTER TO rec_type; DECLARE ptree: POINTER TO TREE( STRING ) OF STRING; pfix = POINTER( fix ); prec = POINTER( rec ); ptree = POINTER( tree ); Some of the built-in functions have special argument rules. For example, they may have a variable number of arguments, or they may accept trees of varying depth. In this sense, they do not adhere strictly to the format of functions. 10.2.6 Pointer Reference A pointer reference is used to reference a variable whose address is stored in a pointer. The symbol ‘‘->’’ after a pointer specifies that you want to reference the variable whose address is stored in the pointer. Example 10–11 shows pointer references. Table 10–5 defines each pointer reference. Expressions 10–17 Table 10–5: Pointer Reference Meanings Reference Meaning pfix Reference to the pointer PFIX and, thus, has a value of the address of FIX pfix-> Reference to FIX, a fixed string of length 10 prec Reference to the pointer PREC and, thus, has a value of the address of REC prec->.comp2 Reference to REC.COMP2, a Boolean record component ptree Reference to the pointer PTREE and, thus, has a value of the address of TREE ptree->(’a’) Reference to TREE(’a’), a dynamic string The item to the left of the symbol ‘‘->’’ is the pointer holding the address of the variable to reference. The item to the right of the symbol ‘‘->’’ is the balance of the pointer reference that specifies the path to the component of the record or the path to the leaf node of the tree. All other reference forms start with the name of the variable being referenced. In a pointer reference, this name is replaced by pointer ->, which specifies the scalar, record, or tree being referenced. Pointers are typically used to access dynamically allocated storage. Example 10–12 shows a procedure that traverses a list of records containing lines of text, freeing those that contain only spaces. Example 10–12: Pointer to Dynamically Allocated Storage MODULE free_lines; TYPE line: RECORD next_line: POINTER TO line, data: VARYING STRING( 256 ), END RECORD; FORWARD PROCEDURE blank_line ( VARYING STRING (256) ) OF BOOLEAN; Example 10–12 Cont’d. on next page 10–18 Expressions Example 10–12 (Cont.): Pointer to Dynamically Allocated Storage PROCEDURE remove_blank_lines ( first_record: POINTER TO line ); DECLARE current_record: POINTER TO line; DECLARE previous_record: POINTER TO line; DECLARE save_record: POINTER TO line; current_record = first_record; previous_record = NIL; WHILE current_record <> NIL; IF blank_line( current_record->.data ) THEN /* contains only blanks so remove */ save_record = current_record; current_record = current_record -> .next_line; FREE save_record; IF previous_record = NIL THEN first_record = current_record; ELSE previous_record -> .next_line = current_record; END IF; ELSE /* non blank line */ previous_record = current_record; current_record = current_record -> .next_line; END IF; END WHILE; END PROCEDURE /* remove_blank_lines */; PROCEDURE blank_line( data: varying string( 256 ) )OF BOOLEAN; DECLARE i: INTEGER; FOR i = 1 TO LENGTH( data ); IF data[ i ] <> ’ ’ THEN RETURN false; END IF; END FOR; RETURN true; END PROCEDURE /* blank_line */; END MODULE /* free_lines */; 10.3 Expression Operator Precedence The precedence of the expression operators is given in Table 10–6. Parentheses can be used to emphasize or override standard precedence. Expressions 10–19 Table 10–6: Expression Operator Precedence Operator Meaning Precedence [] Substring 1 (Highest—done first) + Unary plus 2 – Unary minus 2 * Multiplication 3 / Division 3 + Addition 4 – Subtraction 4 & Concatenation 5 = Equal to 6 == Exactly equal to 6 <> Not equal to 6 < Less than 6 > Greater than 6 <= Less than or equal to 6 >= Greater than or equal to 6 NOT Complement 7 AND Intersection 8 OR Union 9 XOR Exclusive OR 9 (Lowest—done last) If two or more operators with the same precedence appear in succession, the operators are performed from left to right. Thus, the following two expressions are equivalent: a * b / c * d ((a * b) / c) * d 10–20 Expressions Chapter 11 Built-In Facilities Two types of VAX SCAN built-in facilities support frequently used operations. These are built-in tokens and built-in functions. You use built-in tokens in macro pictures to perform specific tasks directly involved in picture matching. The use of built-in functions in expressions in VAX SCAN is similar to their use in other languages, such as in conversions and useful string operations. Built-in facilities do not require a declaration, because they are provided as part of the VAX SCAN language. The names of built-in facilities are unreserved keywords; thus, their names can be used to declare other objects. Note that if the name of a built-in facility is used to declare another object, that built-in facility can no longer be referenced in that scope. 11.1 Built-In Tokens Table 11-1 lists the built-in tokens that are used in macro pictures to perform a task or to return a value—they cannot be used to trigger a macro. Table 11–1: Built-In Tokens ANY COLUMN FIND INSTANCE NOTANY SEQUENCE SKIP Built-In Facilities 11–1 11.1.1 ANY Built-In Token The built-in token ANY checks whether the next character in the input stream is a member of the set specified in the string expression. The syntax diagram for ANY is as follows: [ picture-variable: ] ANY( string-expression ) ... ANY is successful if any member of the string-expression matches the next character encountered in the input stream; if the optional picture variable is present, it is set to the successfully matched character. If repetition is specified ( . . . ), the testing continues until either a match is not found, or the end of the input stream is reached. For example: x : ANY(’aeiouy’) In this example, the next character in the input stream is tested to see whether it is a vowel (’aeiouy’). If it is, x is set to that vowel. 11.1.2 COLUMN Built-In Token The COLUMN built-in token matches text in the input stream to a specific column. COLUMN is used to look at everything in your present line, up to the column specified. The syntax of COLUMN is as follows: [ picture-variable: ] COLUMN( integer-expression ) If the current column number is greater than that specified by the integer expression, then COLUMN fails. If the optional picture-variable is present, it is set to all the characters in the line, up to the specified column. For example: y : COLUMN(40) As an example, if the current column is 5, the characters in columns 1 through 4 have already been matched. In this case, the picture variable y will be set to all the characters in columns 5 through 39. If the line is less than 40 characters long, y contains the characters in column 5 through the end of the line. If the current column is 45, however, the built-in token fails. 11–2 Built-In Facilities 11.1.3 FIND Built-In Token FIND is a built-in token used to locate specified text and to optionally assign all prior text to a picture variable. It can perform either an exact search or a caseless search, as specified by a second Boolean argument. The syntax of the FIND built-in token is as follows: " [picture-variable:] FIND( string-expression # ,boolean ) If the string-expression is found, the optional picture-variable is set equal to all the text up to the string-expression. The comparison test can be made caseless by supplying the Boolean value TRUE. The default Boolean value is FALSE. Example 11–1 shows a use of the FIND built-in token. Example 11–1: Use of FIND Built-In Token a : FIND(’the’,TRUE) In this example, when the word ‘‘the’’ is encountered (regardless of case), the picture variable a assumes the value of all the intervening text, starting from the current position and continuing to this instance of ‘‘the’’. 11.1.4 INSTANCE Built-In Token The INSTANCE built-in token initially builds a token. Then, it tests whether the text matched by the token is equivalent to the stringexpression. The syntax diagram of INSTANCE is as follows: " INSTANCE( string-expression # ,boolean ) Built-In Facilities 11–3 The test for equivalence may be made caseless by supplying the Boolean value TRUE. The default Boolean value is FALSE. If the built-in token and the string-expression are equivalent, the built-in token succeeds. If they are not equal, the built-in token fails. Example 11–2 shows a use of INSTANCE where that token fails. Example 11–2: Use of INSTANCE Built-In Token TOKEN word {alpha...}; INSTANCE(’END’) text in input stream: ...End... token built = word text of token = End result = failure, because of case mismatch Because the caseless option is FALSE by default, an exact match is required in this example. Here the string-expression is in all uppercase; thus, the token fails. 11.1.5 NOTANY Built-In Token The NOTANY built-in token functionally performs the inverse to ANY. NOTANY is testing for the mismatch of any of the characters in the string-expression. The syntax diagram of NOTANY is as follows: [ picture-variable: ] NOTANY( string-expression ) If the next character in the input stream is not represented in stringexpression, NOTANY succeeds. If the optional picture-variable is present it is set to the character. Example 11–3 shows a use of NOTANY. This example matches up to the next consonant in the input stream. 11–4 Built-In Facilities Example 11–3: Use of NOTANY Built-In Token NOTANY(’aeiouy’)... Example 11–4: Use of SEQUENCE Built-In Token pvar : SEQUENCE(’power boats’,TRUE) 11.1.6 SEQUENCE Built-In Token The SEQUENCE built-in token is sensitive to the length of the stringexpression. It compares the text of the string-expression with the next n characters, in the input stream where n is the length of the stringexpression. The comparison test can be made caseless by supplying the Boolean value TRUE. The default Boolean value is FALSE. The following is the syntax diagram of SEQUENCE: " [ picture-variable: ] SEQUENCE( string-expression # ,boolean ) The use of the SEQUENCE built-in token is shown in Example 11–4. In this example, the next 11 characters in the input stream (11=length of the string expression ‘‘power boats’’) are checked as to whether they are equal to the specified string expression. If they are, and note that the cases must be correct, then SEQUENCE succeeds. Also, the picture variable pvar is set equal to the string expression. 11.1.7 SKIP Built-In Token The SKIP built-in token can be used to jump over n characters in the input stream, where n is specified by the integer-expression, or it can be used to collect the next n characters in the optional picture-variable. The following shows the syntax diagram of SKIP: [ picture-variable: ] SKIP( integer-expression ) Built-In Facilities 11–5 SKIP always succeeds. A typical use is shown in Example 11–5. Example 11–5: Use of SKIP Built-In Token dozen: SKIP(12) This example collects the next 12 characters in the input stream and assigns them to the picture variable dozen. 11.2 Built-In Functions Table 11–2 summarizes the VAX SCAN built-in functions. Table 11–2: Built-In Functions Function Name Function Performed TREEPTR Returns a treeptr for a node in a tree EXISTS Tests whether a node exists in a tree FIRST Finds the first node in a tree LAST Finds the last node in a tree NEXT Finds the next node in a tree PRIOR Finds the prior node in a tree VALUE Returns the value of a leaf node in a tree VALUEPTR Returns a pointer to the value of a leaf node in a tree SUBSCRIPT Returns the subscript of a node in a tree INDEX Finds the position of one string within another LENGTH Returns the current length of a string LOWER Converts a string to lowercase UPPER Converts a string to uppercase MEMBER Finds the first member of a set in a string 11–6 Built-In Facilities Table 11–2 (Cont.): Built-In Functions Function Name Function Performed TRIM Trims characters from a string INTEGER Converts a value to an integer STRING Converts a value to a string POINTER Returns the address of a variable ABS Returns the absolute value of an integer MAX Returns the maximum of a list of integers MIN Returns the minimum of a list of integers MOD Returns the modulus of two integers TIME Returns the current date and time ENDFILE Tests for the end of a file 11.2.1 Tree Traversing Built-In Functions The tree traversing built-in functions aid in traversing VAX SCAN trees. A tree is a hierarchy of nodes, and a treeptr holds the address of one of these nodes. Each of the tree traversing built-in functions is discussed in the sections that follow. The examples and figures in these sections are based on Example 11–6. Figure 11–1 is a graphical representation of this tree. Built-In Facilities 11–7 Example 11–6: Tree Traversing Code Example !+ ! ! ! ! ! !- This is a 2 level tree: level 1 holds the names of cities level 2 holds the wards of each city the integer values are the number of voters in that ward of the city DECLARE voters: TREE( STRING, INTEGER ) OF INTEGER; voters( ’salem’, 1 ) = 2500; voters( ’salem’, 2 ) = 1500; voters( ’salem’, 3 ) = 2000; voters( voters( voters( voters( ’hudson’, ’hudson’, ’hudson’, ’hudson’, 1 2 3 4 ) ) ) ) = = = = 3500; 3200; 2900; 3600; voters( ’zork’, 1 ) = 1000; Figure 11–1: Tree Structure ARTFILE ZK–4296–85 The numbers in parentheses at the bottom of the tree are the values associated with the leaves. The symbols in square brackets to the right of each node are not part of the tree, but are a means of identifying a node in the tree. For example, voters(’zork’) is node [4]. 11–8 Built-In Facilities Each of the tree traversing built-in functions takes a tree reference as an argument. A tree reference can take two forms. The first form is a reference to a treeptr variable. The second form is the name of a tree optionally followed by parentheses enclosing a list of zero or more subscripts. In the context of the tree traversing built-in functions, a tree reference identifies a node in a tree, not a value stored in the tree. Several tree references are shown in Figure 11–2. Figure 11–2: Tree References Given: DECLARE DECLARE DECLARE DECLARE city_ptr: TREEPTR( STRING ) TO TREE( INTEGER ) OF INTEGER; ward_ptr: TREEPTR( INTEGER )TO INTEGER; city: STRING; ward: INTEGER; city = ’salem’; ward = 2; 11.2.1.1 Tree Reference Node Referenced voters voters( ’hudson’ ) voters( city, ward ) city_ptr ward_ptr Root node [1] Interior node [2] Leaf node [A] Interior node pointed to by city_ptr Leaf node pointed to by ward_ptr TREEPTR Built-In Function The TREEPTR built-in function returns the treeptr of a node in a tree. It takes one argument, a tree reference to the node of interest. The tree reference can be to a root, interior, or leaf node. The syntax of TREEPTR is as follows: TREEPTR ( tree-reference ) If the tree reference specified as the argument to TREEPTR does not exist in the tree, the built-in function returns the value NIL. Example 11–7 declares two treeptr variables and initializes them using the built-in function TREEPTR. Built-In Facilities 11–9 Example 11–7: Use of TREEPTR Built-In Function DECLARE city_ptr: TREEPTR( STRING ) TO TREE( INTEGER ) OF INTEGER; DECLARE ward_ptr: TREEPTR( INTEGER ) TO INTEGER; /* get a treeptr for node [A], ward 2 in city salem */ ward_ptr = TREEPTR( voters( ’salem’, 2 )); /* get a treeptr for node [2], the city hudson */ city_ptr = TREEPTR( voters( ’hudson’ )); 11.2.1.2 EXISTS Built-In Function The EXISTS built-in function checks for the existence of a node in a tree. EXISTS returns the value TRUE if the tree reference passed as the argument is currently a node in the tree; otherwise, the value FALSE is returned. The syntax of EXISTS is as follows: EXISTS ( tree-reference ) Figure 11–3 shows a use of the EXISTS built-in function. 11–10 Built-In Facilities Figure 11–3: Use of EXISTS Built-In Function Function Reference EXISTS( voters( ’salem’ ) ) EXISTS( voters( ’concord’ ) ) EXISTS( voters( ’zork’, 2 ) ) EXISTS( voters( ) ) 11.2.1.3 Result of Built-In Function TRUE FALSE FALSE TRUE FIRST Built-In Function Given a tree reference to a node at level n in a tree, the FIRST built-in function returns a treeptr variable to the first node at level n+1. Thus, given the tree root as an argument, it returns a treeptr variable for the first node at level 1. Given a level 1 tree reference, FIRST returns a treeptr variable to the first node at level 2. The syntax of FIRST is as follows: FIRST ( tree-reference ) The argument of FIRST must be a root or interior node. If the argument is not currently a node in the tree, an error is issued. If the argument is a node in the tree, but has no nodes at the next level (due to pruning), the NIL treeptr variable is returned. A use of the built-in function FIRST is shown in Figure 11–4. Built-In Facilities 11–11 Figure 11–4: Use of FIRST Built-In Function 11.2.1.4 Function Reference Result of Built-In Function FIRST( voters ) FIRST( voters( ’salem’ ) ) FIRST( city_ptr ) Node [2] Node [9] Node [5] if city_ptr points to [2] LAST Built-In Function Given a tree reference to a node at level n in a tree, the LAST built-in function returns a treeptr variable to the last node at level n+1. Thus, given the tree root as an argument, it returns a treeptr variable for the last node at level 1. Given a level 1 tree reference, LAST returns a treeptr variable to the last node at level 2. The syntax of LAST is as follows: LAST ( tree-reference ) The argument of LAST must be a root or interior node. If the argument is not currently a node in the tree, an error is issued. If the argument is a node in the tree, but has no nodes at the next level, the NIL treeptr variable is returned. A use of the LAST built-in function is shown in Figure 11–5. 11–12 Built-In Facilities Figure 11–5: Use of LAST Built-In Function Function Reference LAST( voters ) LAST( voters( ’salem’ ) ) LAST( city_ptr ) 11.2.1.5 Result of Built-In Function Node [4] Node [B] Node [8] if city_ptr points to [2] NEXT Built-In Function Given a tree reference to a node at level n in a tree, the NEXT built-in function returns a treeptr variable to the next node at level n. The syntax of the NEXT built-in function is as follows: The argument of NEXT must be an interior or leaf node. If the argument is not currently a node in the tree, an error is issued. If the argument is a node in the tree, but no more nodes exist at the same level, the NIL treeptr variable is returned. Figure 11–6 shows a use of the NEXT built-in function. Figure 11–6: Use of NEXT Built-In Function Function Reference NEXT( voters( ’salem’ ) ) NEXT( voters( ’zork’ ) ) NEXT( ward_ptr ) 11.2.1.6 Result of Built-In Function Node [4] NIL Node [6] if ward_ptr points to [5] PRIOR Built-In Function Given a tree reference to a node at level n in a tree, the PRIOR built-in function returns a treeptr variable to the prior node at level n. The syntax of PRIOR is as follows: PRIOR ( tree-reference ) The argument of PRIOR must be an interior or leaf node. If the argument is not currently a node in the tree, an error is issued. If the argument is a node in the tree, but no prior nodes exist at this level, the NIL treeptr variable is returned. Built-In Facilities 11–13 A use of the PRIOR built-in function is shown in Figure 11–7. Figure 11–7: Use of PRIOR Built-In Function Function Reference Result of Built-In Function PRIOR( voters( ’salem’ ) ) PRIOR( voters( ’hudson’, 1 ) ) FIRST( ward_ptr ) Node [2] NIL NIL if ward_ptr points to [5] Example 11–8 uses these built-in functions to traverse all the nodes of the tree voters. Example 11–8: Using Built-In Functions to Traverse a Tree DECLARE city_ptr: TREEPTR( STRING ) TO TREE( INTEGER ) OF INTEGER; DECLARE ward_ptr: TREEPTR( INTEGER ) TO INTEGER; city_ptr = FIRST( voters ); ! get the first level 1 node WHILE city_ptr <> NIL; ! any level 1 nodes left? ward_ptr = FIRST( city_ptr ); ! get the first level 2 node WHILE ward_ptr <> NIL; . . . ward_ptr = NEXT( ward_ptr ); ! any level 2 nodes left? ! get the next level 2 node END WHILE; city_ptr = NEXT( city_ptr ); ! get the next level 1 node END WHILE; This example traverses the tree from left to right (in terms of the diagram at the start of the section). By replacing FIRST with LAST and NEXT with PRIOR, your program could traverse the tree from right to left. 11–14 Built-In Facilities 11.2.1.7 VALUE Built-In Function The VALUE built-in function returns the value associated with a node in a tree. VALUE takes one argument, a tree reference to a leaf node. The syntax of the VALUE built-in function is as follows: VALUE ( tree-reference ) The type of the value returned by VALUE depends on the argument passed to the built-in function. If the argument refers to a tree of integers, like voters, VALUE returns an integer. If the argument refers to a tree of varying strings, VALUE returns a varying string. Figure 11–8 shows a use of VALUE. Figure 11–8: Use of VALUE Built-In Function Function Reference Result of Built-In Function VALUE( voters( ’salem’ ) ) VALUE( voters( ’hudson’, 1 ) ) VALUE( ward_ptr ) Error: argument is not a leaf node 3500 1000 if ward_ptr points to [C] When traversing a tree, you often need to get to the data of the tree node pointed to by a treeptr variable. VALUE makes that possible without having to provide the subscript path from the root. 11.2.1.8 VALUEPTR Built-In Function The VALUEPTR built-in function is similar to VALUE. However, rather than returning the value of a leaf node, it returns a pointer to this value. VALUEPTR takes one argument, a tree-reference to a leaf node. The syntax of VALUEPTR is as follows: VALUEPTR( tree-reference ) The type of pointer returned by VALUEPTR depends on the argument passed to the built-in. If the argument refers to a tree of integers, like voters, VALUEPTR returns a pointer to an integer. If the argument refers to a tree of varying strings, VALUEPTR returns a pointer to a varying string. This holds true for all leaf data types. Built-In Facilities 11–15 The VALUEPTR built-in is useful in two situations, as shown in Figure 11–9. Figure 11–9: Use of VALUEPTR Built-In Function 1. To change the value of a tree node pointed to by a treeptr variable: DECLARE t: TREE( INTEGER ) OF INTEGER; DECLARE tp: TREEPTR( INTEGER ) TO INTEGER; tp = FIRST( t ); WHILE tp <> NIL; VALUEPTR( tp ) -> = 0; tp = NEXT ( tp ); END WHILE; 2. To reference a component of a RECORD: TYPE add : RECORD comp1 : INTEGER, comp2 : STRING( 20 ), END RECORD; DECLARE t : TREE( STRING ) OF add; DECLARE tp : TREEPTR( STRING ) TO add; tp = FIRST( t ); WHILE tp <> NIL; WRITE VALUEPTR( tp ) -> .comp1, VALUEPTR( tp ) -> .comp2; tp = NEXT( tp ); END WHILE; 11.2.1.9 SUBSCRIPT Built-In Function The SUBSCRIPT built-in function returns the subscript associated with a node in a tree. The tree reference passed as an argument to SUBSCRIPT must be either an interior or leaf node. The syntax of SUBSCRIPT is as follows: SUBSCRIPT ( tree-reference ) The type of the value returned by SUBSCRIPT depends on the tree reference passed to the built-in function. If the argument references an integer level of a tree, an integer is returned. If the argument references a string level of a tree, a dynamic string is returned. 11–16 Built-In Facilities SUBSCRIPT is shown in Figure 11–10. Figure 11–10: Use of SUBSCRIPT Built-In Function Function Reference Result of Built-In Function SUBSCRIPT( SUBSCRIPT( SUBSCRIPT( SUBSCRIPT( ’salem’ 1 ’zork’ if city_ptr points to [4] 4 if ward_ptr points to [8] voters( ’salem’ ) ) voters( ’zork’,1 ) ) city_ptr ) ward_ptr ) Example 11–9 shows many of the tree built-in functions. It traverses voters in reverse order, printing out the number of voters in each ward. Example 11–9: Use of Tree Built-In Functions city_ptr = LAST( voters ); WHILE city_ptr <> NIL; ward_ptr = LAST( city_ptr1 ); WHILE ward_ptr <> NIL; WRITE ’voters( ’, SUBSCRIPT( city_ptr ), ’, ’, SUBSCRIPT( ward_ptr ), ’) = ’, VALUE( ward_ptr ); ward_ptr = PRIOR( ward_ptr ); END WHILE; city_ptr = PRIOR( city_ptr ); END WHILE; ! ! ! ! ! ! ! get the last level 1 node any level 1 nodes left? get the last level 2 node any level 2 nodes left? WRITE voters( city, ward ) = integer ! get the prior level 2 node ! get the prior level 1 node 11.2.2 String Built-In Functions The VAX SCAN string built-in functions aid in the manipulation of string values: • • INDEX LENGTH Built-In Facilities 11–17 • • • • 11.2.2.1 LOWER UPPER MEMBER TRIM INDEX Built-In Function The INDEX built-in function locates the position of one character string within another. The syntax of INDEX is as follows: INDEX ( search-expression , locate-expression ) Search-expression Is the string expression to be searched. Locate-expression Is the string expression to look for in searchexpression. The first argument is the string to be searched. The second argument is the string to be located within the search string. If the locate string is not found, INDEX returns an integer zero. If the locate string is found, INDEX returns the integer position in the searched string of the first occurrence of the locate string. If the locate string is the null string ( " ), INDEX returns an integer zero. The INDEX built-in function is shown in Figure 11–11. 11–18 Built-In Facilities Figure 11–11: Use of INDEX Built-In Function 11.2.2.2 Function Reference Result of Built-In Function INDEX( INDEX( INDEX( INDEX( 3 5 0 0 ’ababc’, ’abc’ ) ’ababc’ & ’dd’, ’cdd’ ) ’ababc’, ’abx’ ) ’ababc’, ’’ ) not found by definition LENGTH Built-In Function The LENGTH built-in function returns the current length of a string expression. The syntax of LENGTH is as follows: LENGTH ( string-expression ) The LENGTH built-in function returns an integer value specifying the length of the string expression that is its argument. Figure 11–12 shows a use of the LENGTH built-in function. Figure 11–12: Use of LENGTH Built-In Function Given: DECLARE fix: FIXED STRING( 25 ); DECLARE var: VARYING STRING( 25 ); DECLARE fix: DYNAMIC STRING; fix = ’in a galaxy far far away’; var = ’’; dyn = ’1234567’; Function Reference Result of Built-In Function LENGTH( LENGTH( LENGTH( LENGTH( 25 0 14 2 fix ) var ) dyn & dyn ) fix[ 5 .. 6 ] ) Built-In Facilities 11–19 11.2.2.3 LOWER Built-In Function The LOWER built-in function converts a string expression to lowercase. The syntax of LOWER is as follows: LOWER ( string-expression ) The result of the LOWER built-in is a string value identical to its argument, except that all uppercase alphabetic characters have been changed to their lowercase equivalent. Characters that are not uppercase characters are unaffected. The uppercase characters are indicated in Appendix E. Figure 11–13 shows a use of the LOWER built-in function. Figure 11–13: Use of LOWER Built-In Function 11.2.2.4 Function Reference Result of Built-In Function LOWER( ’A b C d E’ ) LOWER( ’{}|)(*&09876’ ) LOWER( ’’ ) ’a b c d e’ ’{}|)(*&09876’ ’’ UPPER Built-In Function The UPPER built-in function converts a string expression to uppercase. The syntax of UPPER is as follows: UPPER ( string-expression ) The result of the UPPER built-in is a string value identical to its argument, except that all lowercase alphabetic characters have been changed to their uppercase equivalent. Characters that are not lowercase characters are unaffected. The lowercase characters are indicated in Appendix E. Figure 11–14 shows a use of the built-in function UPPER. 11–20 Built-In Facilities Figure 11–14: Use of UPPER Built-In Function 11.2.2.5 Function Reference Result of Built-In Function UPPER( ’A b C d E’ ) UPPER( ’{}|)(*&09876’ ) UPPER( ’’ ) ’A B C D E’ ’{}|)(*&09876’ ’’ MEMBER Built-In Function The MEMBER built-in function locates the first position of a member of a set within a string. The syntax of MEMBER is as follows: MEMBER ( search-expression , member-expression ) Search-expression Is the string expression to search. Member-expression Is the string expression specifying the set of characters to look for in search-expression. The first argument is the string to be searched. The second argument is the string whose contents are the set of characters to be searched for within the searched string. If no member of the string member-expression is found, MEMBER returns an integer zero. If a member of the string member-expression is found, MEMBER returns an integer position of the first occurrence of that member in the search-expression. Figure 11–15 shows a use of the MEMBER built-in function. Built-In Facilities 11–21 Figure 11–15: Use of MEMBER Built-In Function Given: DECLARE nums : STRING; nums = ’0123456789’; 11.2.2.6 Function Reference Result of Built-In Function MEMBER( ’the 3 pigs’, nums ) MEMBER( ’the three pigs’, nums ) 0 MEMBER( ’ 0 1 2’, nums ) 5 not found 2 TRIM Built-In Function The TRIM built-in function deletes leading and trailing characters from a string expression. The syntax of TRIM is as follows: " TRIM ( string-expression # , trim-expression ) String-expression Is the string expression to trim. Trim-expression Is the string expression specifying what characters to trim. TRIM returns a string value identical to its first argument, except that all leading and trailing characters that are members of the second argument are removed. A leading character is any character in the trim-expression that appears in string-expression before the first character that is not in the trim-expression. A trailing character is any character in the trim-expression that appears in string-expression after the last character that is not in the string trim-expression. The second argument of TRIM is optional. If it is omitted, tabs and blanks are assumed. 11–22 Built-In Facilities Figure 11–16 shows a use of the TRIM built-in function. Figure 11–16: Use of TRIM Built-In Function Given: DECLARE filter : STRING; filter = ’*/!’; Function Reference Result of Built-In Function TRIM( TRIM( TRIM( TRIM( ’the rain in’ ’Spain stays mainly’ ’ ’ ’- ****//// ’ ’ the rain in ’) ’Spain stays mainly ’) ’*/*! ///!!’, filter ) ’- ****//// ’, filter ) 11.2.3 Conversion Built-In Functions The conversion built-in functions convert an expression from one data type to another. 11.2.3.1 INTEGER Built-In Function The INTEGER built-in function converts an expression to an integer value. The syntax of INTEGER is as follows: INTEGER ( expression ) Expression Is a string, integer, or Boolean expression. The conversion performed depends on the type of the argument, as shown in Table 11–3. Table 11–3: Integer Conversion Results Argument Result Integer Value of the argument. Built-In Facilities 11–23 Table 11–3 (Cont.): Integer Conversion Results Argument Result String Value of the argument interpreted as a base 10 integer. The string must have the following form: [sp] . . . [‘‘+’’ | ‘‘-’’] [sp] . . . digit . . . [sp] . . . The sp is a blank or horizontal tab. Boolean Value 1 if the argument is TRUE. Value 0 if the argument is FALSE. Figure 11–17 shows a use of the INTEGER built-in function. Figure 11–17: Use of INTEGER Built-In Function Function INTEGER( INTEGER( INTEGER( INTEGER( INTEGER( 11.2.3.2 Reference 5+6*4 ) TRUE ) ’ + 1435 ’) ’11111111111111’ ) ’-1,234’ ) Result of Built-In Function 29 1 1435 error: overflow error: invalid format due to comma STRING Built-In Function The STRING built-in function converts an expression to a string value. The syntax of STRING is as follows: STRING ( expression ) Expression Is a Boolean, fill, integer, pointer, string, or treeptr expression. The conversion performed depends on the type of the argument, as shown in Table 11–4. 11–24 Built-In Facilities Table 11–4: String Conversion Results Argument Result Integer String containing the base 10 representation of the argument. The string contains a sign only if the argument is negative. The string contains no blanks. String String identical to the argument. Boolean String ’TRUE’ if the argument is TRUE. String ’FALSE’ if the argument is FALSE. Pointer String containing the base 16 representation of the argument. The string contains no sign or blanks. Treeptr String containing the base 16 representation of the argument. The string contains no sign or blanks. Fill String containing the base 16 representation of the argument. The string contains no sign or blanks. Figure 11–18 a use of the STRING built-in function. Figure 11–18: Use of STRING Built-In Function 11.2.3.3 Function Reference Result of Built-In Function STRING( STRING( STRING( STRING( STRING( ’-4005’ ’3’ ’FALSE’ ’ a b c’ ’00000000’ -4005 ) 100/33 ) FALSE ) ’ a b c’ ) NIL ) POINTER Built-In Function The POINTER built-in function returns the address of a variable. The syntax of POINTER is as follows: POINTER ( reference ) Reference Is a scalar, record, or tree. In the case of a tree, the argument must be either a root or leaf node. Built-In Facilities 11–25 The pointer returned is bound to a type, like all pointers. This type is the type of the argument. Thus, the result of the function is valid only in contexts where the original argument was valid. Example 11–10 shows a use of the POINTER built-in function. Example 11–10: Use of POINTER Built-In Function TYPE rec_type: RECORD var1: VARYING STRING( 20 ), var2: VARYING STRING( 50 ), END RECORD; DECLARE var: VARYING STRING( 50 ); DECLARE rec: rec_type; DECLARE tree: TREE( STRING ) OF VARYING STRING( 50 ); DECLARE ptr: POINTER to VARYING STRING( 50 ); ptr = POINTER( var ); ! ptr points to var ptr = POINTER( rec.var2 ); ! ptr points to rec.var2 ptr = POINTER( tree( ’aaa’ ) ); ! ptr points to data in tree leaf 11.2.4 Mathematical Built-In Functions VAX SCAN provides built-in functions for frequently used mathematical operations. 11.2.4.1 ABS Built-In Function The ABS built-in function returns the absolute value of an integer expression. The syntax of ABS is as follows: ABS ( integer-expression ) 11–26 Built-In Facilities Figure 11–19 shows a use of ABS. Figure 11–19: Use of ABS Built-In Function 11.2.4.2 Function Reference Result of Built-In Function ABS( -101 ) ABS( 101 ) 101 101 MAX Built-In Function The MAX built-in function returns the maximum integer value of two or more integer expressions. The syntax of MAX is as follows: MAX ( integer-expression,... ) Figure 11–20 shows a use of the MAX built-in function. Figure 11–20: Use of MAX Built-In Function 11.2.4.3 Function Reference Result of Built-In Function MAX( -10, 20 ) MAX( 0, 1, 2, 3 ) 20 3 MIN Built-In Function The MIN built-in function returns the minimum integer value of two or more integer expressions. The syntax of MIN is as follows: MIN ( integer-expression,... ) Built-In Facilities 11–27 Figure 11–21 shows a use of the MIN built-in function. Figure 11–21: Use of MIN Built-In Function 11.2.4.4 Function Reference Result of Built-In Function MIN( -10, 20 ) MIN( 0, 1, 2, 3 ) -10 0 MOD Built-In Function The MOD built-in function returns the remainder of the division of two integer expressions. The syntax of MOD is as follows: MOD ( integer-expression1 , integer-expression2 ) The integer value returned by the MOD built-in function is given by the following expression: integer-expression1 ( integer-expression1 / integer-expression2 ) * integer-expression2 Figure 11–22 shows a use of the MOD built-in function. 11–28 Built-In Facilities Figure 11–22: Use of MOD Built-In Function Function Reference MOD( 11, 3 MOD(-11, 3 MOD( 10,-3 MOD(-10,-3 MOD( 12, 3 ) ) ) ) ) Result of Built-In Function 2 -2 1 -1 0 11.2.5 Other Built-In Functions There are two other built-in functions: ENDFILE and TIME. They are described in the following two subsections. 11.2.5.1 ENDFILE Built-In Function The ENDFILE built-in function tests whether the end of a VAX SCAN file has been reached. The syntax of ENDFILE is as follows: ENDFILE ( [ file-variable ] ) The argument specifies the file to be tested for the end-of-file state. If the argument is omitted, the primary input file is assumed. ENDFILE returns the value FALSE if the file is not in the open state, or if the file is opened FOR OUTPUT. ENDFILE returns the value TRUE if the file is opened FOR INPUT and no records remain to be read from the file. Example 11–11 shows a use of the ENDFILE built-in function. Built-In Facilities 11–29 Example 11–11: Use of ENDFILE Built-In Function MODULE endfile; PROCEDURE enfi MAIN; DECLARE line : DYNAMIC STRING; DECLARE input_file : FILE; OPEN FILE (input_file) AS ’first.dat’ FOR INPUT; READ FILE (input_file) line; WHILE NOT ENDFILE( input_file ); ! test for end of file ! process line READ FILE (input_file) line; END WHILE; CLOSE FILE (input_file); END PROCEDURE /* enfi */; END MODULE /* endfile */; 11.2.5.2 TIME Built-In Function The TIME built-in function returns the current date and time as a string value. The syntax of TIME is as follows: TIME( ) The format of the string returned by TIME is as follows: DD-MMM-YYYY HH:MM:SS The following table describes the format of the string. 11–30 Built-In Facilities Substring Meaning DD The day of the month MMM The first three characters of the month YYYY The year HH The hour (24 hour format) MM The minute SS The second Single digit days have a blank for the left D. For single digit hours, the left H is zero. Example 11–12 shows a use of the TIME built-in function. Example 11–12: Use of TIME Built-In Function MODULE time_check; PROCEDURE display_time MAIN; DECLARE last_time, current_time: STRING; WHILE TRUE; current_time = TIME(); IF last_time <> current_time THEN WRITE current_time; last_time = current_time; END IF; END WHILE; END PROCEDURE /* display_time */; END MODULE /* time_check */; Built-In Facilities 11–31 Chapter 12 Executable Statements Each executable statement performs an action. In the body of a procedure, executable statements state the algorithm the procedure is to perform. In the body of a macro, executable statements state the algorithm needed to create the macro’s replacement text. A list of VAX SCAN executable statements is shown in Table 12–1. Each of these statements is discussed in detail in this chapter. Table 12–1: VAX SCAN Executable Statements Statement Action Assignment Assigns a variable a new value CALL Invokes a subroutine GOTO Transfers control to a label CASE Transfers control based on an integer value IF Transfers control based on a Boolean value WHILE Loops while a Boolean value is TRUE FOR Loops for a range of integer values RETURN Returns from a procedure or macro START SCAN Starts picture matching STOP SCAN Stops picture matching ANSWER Answers replacement text FAIL Causes a macro to fail Executable Statements 12–1 Table 12–1 (Cont.): VAX SCAN Executable Statements Statement Action OPEN Opens a file CLOSE Closes a file READ Reads a record from a file WRITE Writes a record to a file ALLOCATE Allocates memory for a pointer variable FREE Deallocates pointer variable’s memory PRUNE Removes a set of nodes from a tree All of the executable statements, except assignment, start with a reserved keyword. The keywords are verbs describing the action the statement performs. The keywords are also used to name the statements. For example, a statement starting with ANSWER is an ANSWER statement. 12.1 Labels Each executable statement may be preceded by one or more labels. Labels are names that represent points in the VAX SCAN program where control can be transferred by other VAX SCAN statements, such as GOTO. Example 12–1 shows the use of labels. The READ statement is preceded by the definition of two labels, top_ of_loop and read_next_line. Each label is followed by a colon ( : ). The second of these two labels is referenced by a GOTO statement at the bottom of the loop. Labels are local to a procedure or macro. VAX SCAN limits transferring control to labels as follows: • In the body of a macro or a procedure, control can be transferred only to labels defined in that macro or procedure. 12–2 Executable Statements Example 12–1: Program Labels OPEN FILE (input_file) AS ’input.dat’ FOR INPUT; top_of_loop: ! first label marking top of loop read_next_line: ! second label marking read point READ FILE (input_file) line; IF ENDFILE (input_file) THEN GOTO end_of_loop; END IF; WRITE line; GOTO read_next_line; end_of_loop: RETURN; • ! transferring control to loop end ! transferring control to read the ! next line ! third label marking loop end You cannot transfer control into a CASE, FOR, WHILE, or IF statement. 12.2 Assignment Statements The assignment statement lets you set the value of a variable. As the syntax diagram shows, an assignment has two parts: variable = expression ; The target variable to set is to the left of the equal sign. To the right of the equal sign is an expression whose value is stored in the target. The target is a reference to a scalar, a leaf node of a tree, or a component of a record or overlay. If the reference is to a string variable, the reference may include a substring operator. The substring operator specifies that the target is a substring of the referenced string variable. The type of the expression must be appropriate to the type of the reference, as specified in Table 12–2. Executable Statements 12–3 Table 12–2: Assignment Statement Requirements Target Type Requirements of Expression Integer Must be integer Boolean Must be Boolean Pointer to type Must be a pointer to same type or NIL Treeptr to type Must be a treeptr to same type or NIL File Not allowed Fill( n ) Must be fill( n ) Fixed string Must be a string1 Varying string Must be a string1 Dynamic string Must be a string1 Record Must be a compatible record2 Overlay Must be a compatible overlay2 Tree Not allowed3 1 You can assign any string value to any string variable. 2 The record and overlay compatibility rules are covered in Section 12.2.2 3 The target of an assignment cannot be a root or interior node. It must be a leaf node. If the target is a leaf node, the assignment sets the value of that leaf node. If the target contains any expressions, such as subscripts or substring positions, they are evaluated before the expression is evaluated. However, you should not rely on such side effects. Example 12–2 shows assignment statements. 12–4 Executable Statements Example 12–2: Assignment Statements DECLARE DECLARE DECLARE DECLARE DECLARE in: INTEGER; boo: BOOLEAN; fix: FIXED STRING( 5 ); var: VARYING STRING( 5 ); dyn: DYNAMIC STRING; in = 1000000; boo = TRUE; fix = ’.’; var = ’abcdef’; dyn = ’1234567’; ! ! ! ! ! set set set set set in to 1,000,000 boo to TRUE fix to ’. ’ (blank pad) var to ’abcde’ (truncate) dyn to ’1234567’ 12.2.1 Assigning to a Substring If the target of an assignment is a string type, you can assign the expression’s value to a substring of the target using the substring operator. The rules for substring assignment are very similar to those for substring extraction. Substring assignment has three forms. Form 1: Form 2: Form 3: Reference[ operand1 ] Reference[ operand1 .. ] Reference[ operand1 .. operand2 ] The variable being partly replaced is reference. Form 1 replaces the single character at position operand1. Form 2 replaces the character sequence starting at the character position operand1 through the end of the string. Form 3 replaces the character sequence starting at position operand1 through position operand2. The leftmost character of the reference has the position 1. The restrictions placed on the operands are shown in Table 12–3. Executable Statements 12–5 Table 12–3: Assignment Operand Restrictions Reference Fixed, Varying, or Dynamic String Operand1 Integer such that 0 < operand1 <= LENGTH( reference )1 Operand2 Integer such that 0 <= operand2 <= LENGTH( reference )1 1 LENGTH is a built-in function that returns the current length of a string. If operand1 is not a valid position in the character string (that is, less than 1 or greater than the length of the string), an error is issued. If operand2 is greater than or equal to zero but less than operand1, the reference is unchanged. If operand2 is greater than the length of the string or negative, an error is issued. Substring assignment is shown in Example 12–3. Example 12–3: Substring Assignment DECLARE DECLARE DECLARE DECLARE fix var dyn i = fix: var: dyn: i: FIXED STRING( 10 ); VARYING STRING( 10 ); DYNAMIC STRING; INTEGER; = ’0123456789’; = ’abcde’; = ’We hold these truths’; 5; ! current length is 10 ! current length is 5 ! current length is 20 fix[ 2 .. 9 ] = ’........’; var[ 4 .. ] = ’xx’; dyn[ 5 ] = ’e’; ! set fix to ’0........9’ ! set var to ’abcxx’ ! set dyn to ’We held these truths’ var[ 2 .. ] = ’ ’; dyn[ 4 .. 7 ] = ’thought’; ! set var to ’a’ ! set dyn to ’We thou these truths’ 12–6 Executable Statements Note that the size of the target variable is unchanged by the assignment. If the value of the string expression is longer than the target substring, the string value is truncated on the right to the length of the target substring. If the value of the string expression is shorter than the target substring, the string value is blank padded on the right to the length of the target substring. 12.2.2 Assigning to a Record or Overlay (Record Compatibility) Assignment is generally limited to single values. Record assignment is an extension of this concept, allowing a record or an overlay that is a sequence of values to be stored in another record or overlay. This is shown in Example 12–4. Example 12–4: Assigning to a Record TYPE point: RECORD x_coord: INTEGER, y_coord: INTEGER, END RECORD; DECLARE a,b: point; a.x_coord = 10; a.y_coord = -10; ! set a.x_coord to 10 ! set a.y_coord to -10 b = a; ! record assignment that sets ! b.x_coord to 10 ! b.y_coord to -10 The third assignment assigns the value of each component of a to the corresponding component of b. You cannot assign a record (or overlay) to any record (or overlay). The two need to be compatible. Two records or two overlays are compatible if their components are identical in type, length, and order. The names and the storage attributes of the components need not be identical, as shown in Example 12–5. Executable Statements 12–7 Example 12–5: Record Compatibility TYPE person: RECORD first: STRING( 10 ), last: STRING( 20 ), residence: RECORD street: STRING( 30 city: STRING( 20 zip: FILL( 5 ), END RECORD, age: INTEGER, END RECORD; TYPE address: RECORD street: STRING( 30 town: STRING( 20 zipcode: FILL( 5 ), END RECORD; DECLARE a,b: person; DECLARE c,d: address; DECLARE e: STRING( 5 ); DECLARE my_address: RECORD street: STRING( 20 city: STRING( 30 zip: FILL( 5 ), END RECORD; a = b; a.residence = c; d.town = e; a = d; d.zipcode = e; my_address = d; ! ! ! ! ! ! 1) 2) 3) 4) 5) 6) ), ), ), ), ), ), okay - both of type person okay - fields are identical okay - 2 string scalars illegal - structures do not match illegal - data types do not match illegal - string lengths differ The records in assignment 1 are compatible because both the target and the value are records of the same type. Although the names of the components differ in assignment 2, the records are still compatible because the component types, lengths, and order are the same. Assignment 3 is not a record assignment; it assigns one fixed string to another that happens to be a component of a record. The last three record assignments are illegal because they do not have the same type, length, and order. 12–8 Executable Statements 12.3 CALL Statement The CALL statement invokes a subroutine. The syntax of a CALL statement is as follows: CALL procedure-name 2 64 ( argument , . . . ) 3 75 ; Argument has the following syntax: ( expression ) variable * The name of the subroutine to be invoked follows the keyword CALL. This subroutine may be defined either in this module or in a separate module. If it is defined in a separate module, there must be an EXTERNAL PROCEDURE declaration in this module that specifies the type, passing mechanism, and order of the procedure’s parameters. If the procedure is defined in this module, this information is contained in the procedure declaration. The list of arguments to be passed to the procedure follows the procedure name. These arguments must match the parameters of the procedure in type, passing mechanism, and order. Section 9.1.1 on parameters describes how the arguments must ‘‘match’’. See that section for the interaction between arguments and parameters. If an argument is an asterisk ( * ), VAX SCAN passes an integer 0 by value for that argument. No checking of the parameter type is done. An asterisk allows you to interface with many system services and VAX/VMS Run-Time Library (RTL) routines that follow the convention that a zero value argument signals the default value for that argument. Following the return from the invoked procedure, execution continues with the statement following the CALL statement. The CALL statement is shown in Example 12–6. Executable Statements 12–9 Example 12–6: CALL Statement MODULE call_example; EXTERNAL PROCEDURE lib$get_input( STRING, STRING ); PROCEDURE init_tree( symbols: TREE( STRING ) OF INTEGER, prompt_string: STRING ); DECLARE symbol: STRING; WHILE true; IF prompt_string = ’’ THEN CALL lib$get_input (symbol,*) ELSE CALL lib$get_input( symbol, prompt_string ) END IF; IF symbol = ’****’ THEN RETURN; END IF; tree( symbol ) = 0; END WHILE; END PROCEDURE; PROCEDURE main_routine MAIN; DECLARE keywords: TREE( STRING ) OF INTEGER; CALL init_tree( keywords, ’next keyword: ’ ); START SCAN; END PROCEDURE; END MODULE; 12.4 GOTO Statement The GOTO statement transfers flow of control to the statement specified by a label. The syntax of the GOTO statement is as follows: GOTO label-name; There are certain restrictions on the transfer of control. You cannot transfer control into a FOR, WHILE, CASE, IF, MACRO, or PROCEDURE construct with a GOTO statement. In addition, you cannot transfer control out of a MACRO or PROCEDURE construct. 12–10 Executable Statements GOTO statements should be used sparingly in a program. They complicate the logic of the program and, in most cases, the logic is more straightforward if they are not used. Example 12–7 shows the GOTO statement. Example 12–7: GOTO Statement WHILE true; READ command; IF command = ’exit’ THEN GOTO done; END IF; . . . END WHILE; done: ! continue processing here after ’exit’ 12.5 CASE Statement The CASE statement transfers control to one of n sequences of executable statements based on the value of an integer expression. When that sequence of statements is executed, control is transferred to the statement following the END CASE statement. The syntax of the CASE statement is as follows: CASE integer-expression FROM ct-integer-expression TO ct-integer-expression; case-alternative . . . END CASE ; Case-alternative has the following syntax: Executable Statements 12–11 8 case-value > < case-value .. [ > : INRANGE case-value 9 " # > = , ... ]: executable-statement > ; ... OUTRANGE Case-value Is ct-integer-expression in the range of the FROM and TO values of the case statement. The case index follows the keyword CASE. The index is an integer expression whose value specifies the case to choose. The index is followed by two integer constants that specify the legal range of values for the index. Each of the choices that can be selected starts with a list of the integer values (in brackets ( [ ] )) that can cause the choice to be selected. The list is followed by zero or more statements to be executed if that choice is selected. This is shown in Example 12–8. Example 12–8: CASE Statement ind = index( ’exit list copy init type’, command ); CASE ind FROM 1 TO 24; [ 1 ]: RETURN; ! exit command [ 6,21 ]: ! list or type command CALL my_list_routine(); [ 16 ]: ! init command x = NIL; y = 1000; z = init_state; [ 11 ]: ! copy command CALL my_copy_routine(); [ inrange,outrange ]: ! unknown command WRITE ’unknown command’; END CASE; 12–12 Executable Statements The index in this example is ind and the range of legal values is 1 to 24. If the index is 1, a RETURN statement is executed. If the index is either 6 or 21, the routine my_list_routine is called. If the index is 16, three assignments are done. If the index is 11, the routine my_ copy_routine is called. If the value is outside the range of 1 to 24, or if the value is in the range but not specified by any of the other cases, the last case that writes out a message is chosen. The case values that start each case can have several forms, as shown in Table 12–4. Table 12–4: Case Values Case Value Meaning Integer Select this case if the index’s value is equal to the integer Integer .. integer Select this case if the index’s value is in the range of integer .. integer INRANGE Select this case if the index’s value is in range but no other case exists for this value OUTRANGE Select this case if the index’s value is out of range Several restrictions are placed on case values. Each value of the index can resolve to, at most, one case. Thus, INRANGE and OUTRANGE can occur only once in a CASE statement and the integer case values cannot overlap or occur more than once. The integer case values must all be in the range between the lower and upper limit of the index. An error is issued if the index (at run time) has no corresponding case. After the statements of a case are executed, control is transferred to the statement following the END CASE statement. 12.6 IF Statement The IF statement executes different sequences of statements based on whether an expression is TRUE or FALSE. The syntax of the IF—THEN—ELSE statement is as follows: IF boolean-expression Executable Statements 12–13 THEN " # ... executable-statement ELSE " # ... executable-statement END IF; The syntax diagram of a simple IF—THEN statement is as follows: IF boolean-expression THEN " # executable-statement ... END IF; The Boolean expression following IF controls the statements that are executed. If the Boolean expression is TRUE, the statements following the THEN are executed. After this list is executed, control is transferred to the statement following the END IF. The ELSE segment of the IF statement is optional. If ELSE is present, it specifies the statements to be executed if the Boolean expression evaluates to FALSE. Following the execution of these statements, control is transferred to the statement following the END IF. If the ELSE segment is not present and the Boolean expression evaluates to FALSE, control is transferred to the statement following the END IF. This is shown in Example 12–9. 12–14 Executable Statements Example 12–9: IF . . . THEN . . . ELSE Statement IF command = ’exit’ THEN RETURN; END IF; ! return only if command’s value is ’exit’ ! reach this point only if command’s value ! is not ’exit’ IF x > y THEN WRITE ’reactor meltdown has started - shutting down’; CALL shutdown(); ELSE WRITE ’okay to go to lunch’; END IF; 12.7 WHILE Statement The WHILE statement repetitively executes a sequence of statements zero or more times. The syntax of the WHILE statement is as follows: WHILE boolean-expression ; executable-statement . . . END WHILE ; The WHILE statement is a looping construct that works as follows: 1. Evaluate the Boolean expression following the keyword WHILE. If it is FALSE, go to step 4. 2. Executes the statement sequence between WHILE and END WHILE. 3. Goes to step 1. 4. Transfers control to the statement following END WHILE. Example 12–10 shows the WHILE statement. Executable Statements 12–15 Example 12–10: WHILE Statement DECLARE a : VARYING STRING(30); READ a; WHILE NOT ENDFILE (); WRITE a; READ a; END WHILE; 12.8 FOR Statement The FOR statement executes a sequence of statements zero or more times. The syntax of the FOR statement is as follows: FOR integer-variable = integer-expression TO " integer-expression STEP integer-expression " # ; # executable-statement ... END FOR; The FOR statement is a looping construct that works as follows: 1. Evaluates the initial (first integer-expression), final (second integer-expression), and step (third integer-expression) value. If a step value is not present, it assumes the step value is 1. 2. Assigns the initial value to the index variable. 3. Compares the value of the index variable with the final value. If the step value is positive, it goes to step 7 if the index value is greater than the final value. If the step value is negative, it goes to step 7 if the index value is less than the final value. 4. Executes the statement sequence between the FOR and END FOR statements. 5. Increments the index variable by the step value. 6. Goes to step 3. 7. Transfers control to the statement following END FOR. 12–16 Executable Statements As the algorithm indicates, the initial, final, and step values are evaluated only once. The index variable must be a simple integer variable. It cannot be a tree node or a record component. The final value of the index variable after the loop terminates is the last value that was assigned to it by either step 2 or step 5. The value of the index variable can be changed within the FOR loop. Example 12–11 shows a FOR loop. Example 12–11: FOR Loop n_factorial = 1; FOR i = 1 to n; n_factorial = i * n_factorial; END FOR; 12.9 RETURN Statement The RETURN statement terminates the execution of a macro or procedure. The syntax of the RETURN statement is as follows: " RETURN # expression ; The expression following RETURN is required only if the RETURN statement is contained within a function. The expression specifies the value to be returned by the function. The type of the expression must match the type of the function. The meaning of ‘‘match’’ is the same as for assignment. A RETURN statement not followed by an expression terminates the execution of a subroutine or macro. In the case of a subroutine, control is transferred to the statement following the CALL that invoked the subroutine. In the case of a macro, control is returned to picture matching. The macro reports success. Executable Statements 12–17 The RETURN statement is shown in Example 12–12. Example 12–12: RETURN Statement MODULE factorial; SET digit ( ’0’..’9’ ); TOKEN number { digit... }; TOKEN exclaim ALIAS ’!’ { ’!’ }; PROCEDURE factorial (n: INTEGER ) OF INTEGER; DECLARE i,n_fact: INTEGER; n_fact = 1; FOR i = 1 TO n; n_fact = n_fact * i; END FOR; RETURN n_fact; END PROCEDURE /* factorial */; MACRO reduce_factorial TRIGGER EXPOSE { d: number ’!’ }; ANSWER STRING( factorial( INTEGER( d )) ); RETURN; END MACRO /* reduce_factorial */; PROCEDURE main MAIN; START SCAN INPUT FILE ’sys$input’ OUTPUT FILE ’sys$output’; END PROCEDURE /* main */; END MODULE /* factorial */; 12.10 START SCAN Statement The START SCAN statement starts the picture matching process. The syntax of the START SCAN statement is as follows. 12–18 Executable Statements 2 INPUT FILE string-expression 66 INPUT PROCEDURE procedure-name 66 INPUT STRING string-expression 66 INPUT WIDTH integer-expression START SCAN 6 OUTPUT FILE string-expression 66 OUTPUT PROCEDURE procedure-name 66 OUTPUT STRING string-variable 4 OUTPUT WIDTH integer-expression 3 77 77 77 77 77 75 ... ; DATA STACK integer-expression The execution of the START SCAN statement begins the picture matching process. The list of options that can follow the keywords START SCAN specifies the input and output streams to be used by picture matching. Table 12–5 summarizes each of the options. Table 12–5: START SCAN Options Option Meaning INPUT FILE The file specified is the input stream. INPUT FILE ’SCN$INPUT’ is the default input stream. INPUT PROCEDURE The procedure specified is invoked each time a new input stream line is needed. INPUT STRING The string expression specified is the input stream. INPUT WIDTH The input buffer length is the specified number of characters. The default is 132. OUTPUT FILE The file specified is the output stream. OUTPUT FILE ’SCN$OUTPUT’ is the default output stream. OUTPUT PROCEDURE The procedure specified is invoked each time a new output stream line is produced. Executable Statements 12–19 Table 12–5 (Cont.): START SCAN Options Option Meaning OUTPUT STRING The string reference specified is the output stream. OUTPUT WIDTH The output buffer length is the specified number of characters. The default is 132. DATA STACK The stack used for capturing picture variable text is the specified number of characters. The default is 2048. Program control is transferred to the statement following the START SCAN statement when picture matching terminates. A START SCAN statement can be executed while picture matching is already in progress. When this happens, picture matching for the first activity is suspended until picture matching invoked by the second START SCAN statement completes. 12.10.1 INPUT FILE Clause Use of the INPUT FILE option indicates that the source of the input stream is a file. VAX SCAN then creates a buffer to read the input stream, and each record is read into this buffer using VAX RMS. (INPUT WIDTH specifies the size of this buffer that VAX SCAN allocates for reading the records.) The string expression following INPUT FILE is interpreted as a VAX/VMS file specification. This file must exist and will be read sequentially. VAX SCAN does not modify the file. The file is treated as a stream of characters. VAX SCAN precedes the first record with an S’SOS’ character (start of stream). Each record break (that is, end of one record and the start of the next) is marked with an S’EOL’ character (end of line). A terminating sequence consisting of an S’EOL’ followed by an S’EOS’ character (end of stream) follows the last record. 12–20 Executable Statements Example 12–13: File as Input Stream DECLARE file_name: STRING; READ file_name; !+ ! ! !- FILE_NAME holds the input file specification. The output stream is not specified so it is the file SCN$OUTPUT. START SCAN INPUT FILE file_name; A file as the input stream is shown in Example 12–13. 12.10.2 INPUT PROCEDURE Clause The INPUT PROCEDURE option indicates that the source of the input stream is a procedure. VAX SCAN calls this procedure each time it needs a new input stream record. The text received from this procedure is treated as a stream of characters. VAX SCAN precedes the first record with an S’SOS’ character (start of stream). Each record break (that is, the end of one record and the start of the next) is marked with an S’EOL’ character (end of line). A terminating sequence consisting of an S’EOL’ followed by an S’EOS’ character (end of stream) follows the last record. VAX SCAN calls the procedure as a function with two parameters. The result of the function is a status. SS$_NORMAL indicates that the procedure produced another line. SCN$_ENDINPSTM indicates that the procedure encountered the end of the input stream. The parameters to the function are both input and output parameters. As input parameters, they provide the input procedure with a buffer to use for input. Use of this buffer is not mandatory. As output parameters from the input procedure, they specify the buffer that contains the input record. The first parameter is the length of the buffer. It is an integer passed by reference. The second parameter is a pointer to an input buffer. This pointer is passed by reference. The length of the buffer can be controlled with the INPUT WIDTH option. Executable Statements 12–21 On output from the function, the parameters hold the actual length of the record and a pointer to the start of the input buffer. Example 12–14 shows a procedure as the input stream. Example 12–14: Procedure as Input Stream !+ ! !- The statuses returned by the input routine. CONSTANT scn$_endinpstm EXTERNAL INTEGER; CONSTANT ss$_normal EXTERNAL INTEGER; !+ ! The input procedure. !PROCEDURE input_proc ( len: INTEGER, bptr: POINTER TO FIXED STRING(132)) OF INTEGER; DECLARE dyn: STRING; READ PROMPT ( ’input: ’ ) dyn; IF NOT ENDFILE() THEN len = length( dyn ); bptr->[ 1 .. len ] = dyn; RETURN ss$_normal; ELSE RETURN scn$_endinpstm; END IF; END PROCEDURE; PROCEDURE main MAIN ( ); !+ ! The input stream is supplied by the procedure INPUT_PROC. ! The output stream is not specified thus it is the ! file SCN$OUTPUT. !START SCAN INPUT PROCEDURE input_proc; END PROCEDURE; 12–22 Executable Statements 12.10.3 INPUT STRING Clause The INPUT STRING option is used when the source of the input stream is a string. The input string is not modified. The string is treated as a stream of characters. VAX SCAN precedes the first character with an S’SOS’ character (start of stream). An S’EOS’ character (end of stream) follows the last character. Example 12–15 shows a string as the input stream. Example 12–15: String as Input Stream DECLARE string_to_parse: STRING; READ string_to_parse; !+ ! ! !- STRING_TO_PARSE holds the input stream. The output stream is not specified so it is the file SCN$OUTPUT. START SCAN INPUT STRING string_to_parse; 12.10.4 OUTPUT FILE Clause Use of the OUTPUT FILE option indicates that the destination of the output stream is a file. The string expression following OUTPUT FILE is interpreted as a VAX/VMS file specification. This file is created by VAX SCAN as a sequential file with varying length records. OUTPUT WIDTH specifies the maximum size of the records that can be written to the file. VAX SCAN converts the stream of characters in the output stream to a sequence of records. S’SOS’ characters (start of stream) are discarded. Each S’EOL’ character (end of line) causes a record break. That is, it marks the end of a record. A record cannot exceed the number of characters specified by OUTPUT WIDTH. If the record length reaches this limit, VAX SCAN breaks the output into two records. The Executable Statements 12–23 remaining characters are placed in the next record and no data is lost. An S’EOS’ character (end of stream) causes VAX SCAN to write an end-of-file and terminates picture processing. Example 12–16 shows a file as the output stream. Example 12–16: File as Output Stream !+ ! ! !- The input stream is the file SYS$INPUT and the output stream is the file SYS$OUTPUT. START SCAN INPUT FILE ’sys$input’ OUTPUT FILE ’sys$output’; 12.10.5 OUTPUT PROCEDURE Clause When the OUTPUT PROCEDURE option is used, the destination of the output stream is a procedure. VAX SCAN calls this procedure each time it produces a new output stream record. VAX SCAN converts the stream of characters in the output stream to a sequence of records. S’SOS’ characters (start of stream) are discarded. Each S’EOL’ character (end of line) causes a record break. That is, it marks the end of a record. A record cannot exceed the number of characters specified by OUTPUT WIDTH. If the record length reaches this limit, VAX SCAN breaks the output into two records. The remaining characters are placed in the next record and no data is lost. Each time a record is created, the output procedure is called. An S’EOS’ character (end of stream) signifies the end of the output stream and terminates picture processing. VAX SCAN calls the procedure as a subroutine with two parameters. The first parameter is the length of the record and the second is the buffer containing the text. 12–24 Executable Statements Example 12–17: Procedure as Output Stream !+ ! The output procedure. !PROCEDURE output_proc ( len: integer, fix: fixed string( 132 ) ); WRITE fix[ 1..len ]; END PROCEDURE; PROCEDURE main MAIN ( ); !+ ! Input stream is not specified, thus it is the file ! SCN$INPUT. The output stream is the procedure ! OUTPUT_PROC. !START SCAN OUTPUT PROCEDURE output_proc; END PROCEDURE; Example 12–17 shows a procedure as the output stream. 12.10.6 OUTPUT STRING Clause The OUTPUT STRING option indicates that the destination of the output stream is a string variable. VAX SCAN assigns the stream of characters in the output stream to the string variable with the following modifications: • • • S’SOS’ characters (start of stream) are discarded. S’EOL’ characters (end of line) are not removed. An S’EOS’ character (end of stream) marks the end of the output stream. Note that the terminating S’EOS’ is not placed in the string variable, but terminates picture processing. Example 12–18 shows the use of a string variable as the output stream. Executable Statements 12–25 Example 12–18: String Variable as Output Stream DECLARE out_string: VARYING STRING(100); !+ ! The input stream is a string and so is the output stream. !START SCAN INPUT STRING ’now is the time for all good men’ OUTPUT STRING out_string; 12.10.7 INPUT WIDTH Clause VAX SCAN uses a buffer to read the input stream when the input stream is a file or a procedure. The default size of this buffer is 132 bytes, but you may modify this up or down, using the INPUT WIDTH clause. For example, if your maximum record size is 200 characters, you must set the size of the input buffer to accommodate that record length. In this case you would specify: INPUT WIDTH 200 Thus, the size specified by this clause is the maximum length of the records in your input stream. The maximum size that you can specify for INPUT WIDTH is 65,535 characters. The INPUT WIDTH clause is ignored if the input stream is a string. 12.10.8 OUTPUT WIDTH Clause VAX SCAN creates a buffer used to collect text going to the output stream. The OUTPUT WIDTH clause permits you to set the width of this buffer and, thus, controls the maximum size of a record sent to the output stream. VAX SCAN writes the buffer to the output stream when the buffer is full, or when an S’EOL’ character is encountered. The next step is determined by the way you specified the output stream in your program. • If the output stream is a file, the contents of the buffer become the next record in the file. 12–26 Executable Statements • • If the output stream is a procedure, the buffer is passed as a parameter to the output procedure. If the output stream is a string, the contents of the buffer are appended to the end of the text already in the output string. The default size or width of this buffer is 132 characters. This means that VAX SCAN writes up to 132 character records to a file. If you have an output line that exceeds 132 characters, VAX SCAN writes the first 132 characters as one record, then places the remaining characters in the next record. Thus, if VAX SCAN encounters 300 characters before an S’EOL’ character, the first 132 are placed in the first record, the second 132 are placed in the second record, and the final 36 characters are placed in a third record. If your application encounters records of up to 512 characters, you should specify the necessary width as follows: OUTPUT WIDTH 512 The maximum size that you can specify for OUTPUT WIDTH is 65,535 characters. 12.10.9 DATA STACK Clause VAX SCAN uses a buffer to capture the text assigned to picture variables. The default buffer size is 2048 characters, which is ample for most applications. If you exceed this figure, you get the following error message when running your application: OVFTOKTEX - Captured token text overflowed its buffer You must then estimate the correct size for the buffer and use the DATA STACK option to set this size. The size of the buffer can be estimated as follows. Determine the maximum number of characters you expect to capture in a picture variable. If the picture variable is to capture the text of a token that is a trigger, double the size allotted for that token. Figure 12–1 shows an estimation of buffer size. Executable Statements 12–27 Figure 12–1: Estimation of Buffer Size for DATA STACK MACRO x TRIGGER { k:keyword d:{ arg type }... }; Token Max Token Size keyword arg type 31 300 21 Variable Variable Max Size k d keyword * 2 = 62 (times 2 because keyword is a trigger) arg + type = 321 The greater of k and d is d. Thus, setting DATA STACK size to 321 should be enough for the example program. Because this is less than the default of 2048 characters, no change is necessary. You should need to use this clause only if 2048 is not adequate for your application. If, however, you had determined that the buffer size had to be increased to 4096, you would use the DATA STACK option on the START SCAN statement: START SCAN DATA STACK 4096; . . . 12.11 STOP SCAN Statement The STOP SCAN statement stops the scanning of the input stream. The syntax of the STOP SCAN statement is as follows: STOP SCAN; When a STOP SCAN statement is executed, the following events occur: 1. Any macros that are active FAIL. Thus, any text that is in the process of being matched is not put in the output stream. 2. The input and output streams are closed. The text in the output stream consists only of text processed at the point the STOP SCAN statement was executed. 12–28 Executable Statements 3. Control is returned to the statement following the START SCAN statement that initiated picture matching. Thus, no further statements in the macro are executed. If more than one START SCAN statement is in progress when a STOP SCAN statement is executed, only the most recent START SCAN statement is terminated. An error is issued if a STOP SCAN statement is encountered when no picture matching is taking place. The following example shows the STOP SCAN statement : MACRO end_of_world TRIGGER{ ’!!’ }; /* Once you find the termination token, you do not need /* to analyze any more of the input stream. STOP SCAN; END MACRO; 12.12 ANSWER Statement The ANSWER statement specifies replacement text for the text matched by a macro’s picture. The syntax of the ANSWER statement is as follows: " ANSWER # TRIGGER string-expression , . . . ; The goal of the body of a macro is to construct the text to replace the text matched by the picture. Conceptually, the macro body creates a buffer that contains the replacement text. This buffer is empty at the time the macro body starts execution. Each ANSWER statement appends text to this buffer. If the macro completes successfully, that is, no FAIL statement is executed, the text in the buffer is the replacement text. You can have any number of ANSWER statements in a macro body. Each ANSWER statement can have one or more string expressions. The string expressions are appended to the buffer in the order that they appear. If no ANSWER statement is executed during the execution of the macro body, the buffer remains empty. Executable Statements 12–29 Example 12–19: ANSWER Statement CONSTANT mask = ’xxxxxxxxxxxxxxxxxxxx’; MACRO replace_time TRIGGER { hour:number ’:’ minute:number [ ’:’ second:number [ ’.’ fract:number ] ] }; ANSWER mask[1..length(hour)], ’:’, mask[1..length(minute)] ; IF length(second) > 0 THEN ANSWER ’:’, mask[1..length(second)]; IF length(fract) > 0 THEN ANSWER ’.’, mask[1..length(fract) ]; END IF; END IF; END MACRO; Example 12–19 shows the ANSWER statement: 12.12.1 TRIGGER Attribute The replacement text of a trigger macro is always rescanned to check for further transformations. The optional TRIGGER attribute on the ANSWER statement controls whether the text in your ANSWER statement is scanned for further triggers. If the TRIGGER attribute is present, the answered text causes further triggering. To understand the usefulness of this option, consider an application that is processing text containing special bolding flags. This application may need to keep track of those bolding constructs and also index a selected list of words. For bolding, it needs to match a construct of this form: For indexing, the application must check whether each word is on a list. A trigger macro is set up for each construct. The code could look like Example 12–20. 12–30 Executable Statements Example 12–20: ANSWER Attribute Program Segment SET alpha TOKEN start_bold TOKEN end_bold TOKEN word ( { { { ’a’..’z’ OR ’A’..’Z’ ); ’’ }; alpha... }; MACRO find_bold TRIGGER { start_bold w:[ word... ] end_bold }; . . . ANSWER w; . . . END MACRO; MACRO find_index TRIGGER { word }; END MACRO; The problem that arises is that words in the bolding sequence do not cause the find_index macro to trigger. This is because by design no triggering takes place while find_bold is matching its picture. There are two solutions to the problem. The solution you choose depends on the situation and your program needs. The first solution is to add the EXPOSE attribute to the trigger macro find_bold. This allows the macro find_index to still trigger, while find_bold is matching its picture. (See Section 5.4.3 for more information on the EXPOSE attribute.) The code to do this could look like Example 12–21. The second solution is to add the TRIGGER attribute to the ANSWER statement in the body of the macro find_bold. This indicates that the text being answered by this statement should be scanned for further transformations. The code would then look like Example 12–22. Executable Statements 12–31 Example 12–21: Using EXPOSE to Enable ANSWER Rechecking SET alpha TOKEN start_bold TOKEN end_bold TOKEN word ( { { { ’a’..’z’ OR ’A’..’Z’ ); ’’ }; alpha... }; MACRO find_bold TRIGGER EXPOSE { start_bold w:[ word... ] end_bold }; . . . ANSWER w; . . . END MACRO; MACRO find_index TRIGGER { word }; END MACRO; Example 12–22: Using TRIGGER Attribute to Enable ANSWER Rechecking SET alpha TOKEN start_bold TOKEN end_bold TOKEN word ( { { { ’a’..’z’ OR ’A’..’Z’ ); ’’ }; alpha... }; MACRO find_bold TRIGGER { start_bold w:[ word... ] end_bold }; . . . ANSWER TRIGGER w; . . . END MACRO; MACRO find_index TRIGGER { word }; END MACRO; The distinction between this approach and the use of EXPOSE is in the order of operations. Using the TRIGGER attribute with the ANSWER statement causes the macro find_index to be activated after the picture matching is complete for the macro find_bold. 12–32 Executable Statements Because the text answered by a macro can be answered by one or more ANSWER statements, each of which may or may not have the TRIGGER attribute, you can—on a character by character basis—mark the text to be scanned for further triggering. For a token to trigger a macro, it must consist solely of text that can cause triggering. Text that can cause triggering is either text from the original input stream, or text answered with the TRIGGER attribute. (This is explained in Section 5.4.5.1.) 12.13 FAIL Statement The FAIL statement causes a macro to fail after its picture has been successfully matched. The syntax of the FAIL statement is as follows: FAIL ; Normally, the matching of a macro’s picture determines whether the macro succeeds or fails. The body of a macro only generates the replacement text. The FAIL statement simulates the effect of the picture failing from within the macro body. The only difference between a FAIL statement being executed and the picture failing is that the statements executed in the body of the macro before the FAIL statement cannot be reversed. Thus, I/O to files, or the assignment of values to variables outside the scope of the macro, is not rolled back. A FAIL statement must occur within the body of a macro. Any statements following the FAIL statement are not executed. The FAIL statement is shown in Example 12–23. 12.14 OPEN Statement The OPEN statement opens a VAX/VMS file and binds it to a VAX SCAN file variable. Once opened, you can either read or write to this VAX/VMS file by referencing the file variable. The syntax of the OPEN statement is as follows: Executable Statements 12–33 Example 12–23: FAIL Statement MACRO find_keyword TRIGGER{ key: keyword }; IF EXISTS( key_tab( UPPER( key ) ) ) THEN /* do keyword processing */ ELSE /* not a keyword so cause macro to FAIL */ FAIL; END IF; END MACRO; OPEN FILE ( file-variable) AS string-expression FOR n INPUT o OUTPUT VAX SCAN supports files that can be read sequentially. The OPEN statement either opens an existing file to be read sequentially or creates a file to be written sequentially. ; The VAX SCAN file variable is in parentheses following the keyword FILE. This is the variable you use to reference this file in the other I/O statements. The string expression following the keyword AS is a VAX/VMS file specification. The file specified by the file specification is bound to the VAX SCAN file variable when the OPEN statement is executed. VAX SCAN issues an error if you attempt to open a file that is already in the open state. A VAX SCAN file is in the open state between the time the OPEN statement is executed on that file and the time the corresponding CLOSE statement is executed. Files in the open state at program termination are closed automatically. The open option FOR INPUT says that the file is to be read. The file must exist or an error is issued. The open option FOR OUTPUT says that the file is to be written. FOR OUTPUT creates a new file. All files must be explicitly opened before being read or written with the exception of the primary input and primary output file. The primary output file, SYS$OUTPUT, is the file you write to if no file is specified on a WRITE statement. The primary input file, SYS$INPUT, is the file you read from if no file is specified on a READ statement. 12–34 Executable Statements Example 12–24: OPEN Statement DECLARE include_file,listing: FILE; OPEN FILE (include_file) AS current_include_file FOR INPUT; OPEN FILE (listing) AS ’a.lis’ FOR OUTPUT; Example 12–24 shows the OPEN statement. 12.15 CLOSE Statement The CLOSE statement closes a VAX SCAN file that is in the open state. The syntax of the CLOSE statement is as follows: CLOSE FILE ( file-variable ) ; The file variable following the keyword FILE must name a file that is in the open state; otherwise, an error is issued. All VAX SCAN files opened by the VAX SCAN program (that are still open when the program terminates) are closed automatically when the program terminates. The following example shows the CLOSE statement: CLOSE FILE (listing); CLOSE FILE (include_file); 12.16 READ Statement The READ statement reads one record from a VAX SCAN file. The syntax of the READ statement is as follows: " READ # " FILE ( file-variable ) # PROMPT ( string-expression ) variable ; If a file variable is present, it specifies the VAX SCAN file to be read. This VAX SCAN file must be opened FOR INPUT or an error is issued. If a file variable is not present, the file read is the primary input file, SYS$INPUT. A prompt message is allowed and it is enabled by including the keyword PROMPT. The string expression following Executable Statements 12–35 PROMPT is written to SYS$OUTPUT as a prompt if you are reading from a terminal device. The program shown in Example 12–25 shows the use of the READ statement in conjunction with a prompt message. Example 12–25: READ Statement with PROMPT MODULE echo; DECLARE response : STRING; CONSTANT phrase1 = ’ Is this a’; CONSTANT phrase2 = ( s’bel’ & s’vt’ ) ; CONSTANT phrase3 = ’ vertical tab? ’ ; CONSTANT words = ’ Your answer: ’; PROCEDURE toplevel MAIN; !++ ! The literal ’Type something’ is the prompt message below: !-READ PROMPT (’Type something: ’) response; WRITE ’This is what you typed: ’,response; !++ ! The string values of the 3 string variables ! below will be concatenated to form the next ! prompt message: !-READ PROMPT ( phrase1 & phrase2 & phrase3 ) response; WRITE words,response ; END PROCEDURE /* toplevel */; END MODULE /* echo */; A READ statement reads one record from the file. The record is interpreted as a sequence of characters. The target may be of type Boolean, integer, or any of the string types. The value of the record is assigned to the target according to the rules for assignment. If the target is not of type string, the appropriate conversion built-in function is applied to the value of the record before doing the assignment as shown in Table 12–6. 12–36 Executable Statements Table 12–6: READ Statement Target Variables Target Type Value Assigned to Target String Value of record Integer INTEGER( value of record ) Boolean BOOLEAN( value of record ) Once the end of a file is reached, a READ operation of that file does nothing. Thus, the value of the target remains unchanged. You can test for the end of a file using the ENDFILE built-in function. There is an exception to the end-of-file rule. If the file supports multiple end of files, such as the primary input file, or tapes, then a READ operation following the end-of-file will read the next record in the file. Example 12–26 shows the READ statement and the use of ENDFILE. Example 12–26: Use of ENDFILE with READ Statement OPEN FILE ( my_file ) AS vms_file_spec FOR INPUT; WHILE true; READ FILE ( my_file ) line; IF ENDFILE( my_file ) THEN GOTO done; END IF; END WHILE; done: 12.17 WRITE Statement The WRITE statement writes one record to a VAX SCAN file. The syntax of the WRITE statement is as follows: Executable Statements 12–37 " WRITE # " FILE ( file-variable ) # expression , ... ; If a file variable is present, it specifies the VAX SCAN file to be written to. This VAX SCAN file must be opened FOR OUTPUT or an error is issued. If no file variable is present, the file written to is the primary output file, SYS$OUTPUT. A WRITE statement writes one record to the file. The record written is a string whose value is the concatenation of expressions in the expression list. The expressions in the list can be of type Boolean, integer, or any of the string types. If an expression is not of type string, it is converted to type string by the rules of the STRING built-in function. Example 12–27 shows an example of the WRITE statement. Example 12–27: WRITE Statement DECLARE keyword: TREE( STRING ) OF INTEGER; DECLARE ptr: TREEPTR(STRING) OF INTEGER; ptr = FIRST( keyword ); WHILE ptr <> NIL; WRITE SUBSCRIPT( ptr ), ’ occurred ’, VALUE( PTR ), ’ times’; ptr = NEXT( ptr ); END WHILE; 12.18 ALLOCATE Statement The ALLOCATE statement sets aside memory for p->, that is, the variable to which the pointer variable p refers. This memory allocation is carried out at run time, when the ALLOCATE statement is executed. The syntax of the ALLOCATE statement is as follows: ALLOCATE pointer-variable , . . . ; 12–38 Executable Statements The variables that follow the keyword ALLOCATE must be pointer variables. These pointer variables specify the following: • • What type storage to allocate and, thus, how much Where to save the address of the storage that has been allocated The initial value of a variable defined in the ALLOCATE statement depends on the type of variable allocated. For example, if you allocate a fixed string, the initial value is blank. The initial value for each type is shown in Table 12–7. Note that this is consistent with the way VAX SCAN initializes other variables. Table 12–7: Initialization Value for Variable Types Variable Type Initialization Value Integer 0 Treeptr NIL Pointer NIL Fill S’nul’ Fixed string Blanks Boolean FALSE Varying string Null string Dynamic string Null string Record S’nul’ Tree Empty Overlay S’nul’ File Closed The ALLOCATE statement is shown in Example 12–28. This declaration establishes pti as a pointer variable that points to an integer variable. The integer variable does not exist until the ALLOCATE statement is executed. The example allocates a variable of type integer at run time. The address of the allocated integer is Executable Statements 12–39 Example 12–28: ALLOCATE Statement DECLARE pti : POINTER TO INTEGER; ALLOCATE pti; pti -> = 1000; ! set the allocated variable value WRITE pti -> ; ! will write the 1000 out to 1000 Example 12–29: FREE Statement DECLARE pts : POINTER TO STRING(100); ALLOCATE pts; pts-> = ’a fixed string’; FREE pts; assigned to pti . You can reference the integer through the pointer as shown in Example 12–28. 12.19 FREE Statement The FREE statement deallocates memory that was allocated by the ALLOCATE statement. The syntax of the FREE statement is as follows: FREE pointer-variable , . . . ; The variable list following the keyword FREE must contain only pointer variables. These pointer variables must point to storage that was previously allocated by an ALLOCATE statement. When this statement is executed (at run time), the storage pointed to by each of the pointer variables is freed. Example 12–29 is an example of the use of the FREE statement. 12–40 Executable Statements The declaration establishes pts as a pointer variable that refers to a fixed string. The fixed string does not exist until the ALLOCATE statement is executed. The memory allocated for pts-> is then deallocated and the variable is destroyed by the FREE statement. The value of the pointer pts becomes NIL. The general usage of ALLOCATE and FREE is as follows: 1. 2. 3. 4. Declare the pointer variable Allocate the storage for use in this program Make use of the storage Free the storage, returning it for reuse It is important to free storage that has been dynamically allocated in a program after you are finished using that storage. If you do not free it, that storage will be inaccessible for the duration of the execution of the current program. Thus, it is effectively a temporary loss of system resources (through mismanagement). 12.20 PRUNE Statement The PRUNE statement deletes one or more nodes from a tree. The arguments of the PRUNE statement are tree references that specify the nodes to delete. The nodes specified are deleted and so are any nodes subordinate to these nodes in the tree. The syntax of the PRUNE statement is as follows: PRUNE tree-reference , . . . ; An error is issued if any tree reference is not currently a node in a tree. A tree reference can specify a root, interior, or leaf node. Referencing a tree root frees all the nodes in the tree, returning it to its initial state. Figure 12–2 shows the PRUNE statement. Executable Statements 12–41 Figure 12–2: PRUNE Statement ARTFILE ZK-4297-85 Refer to Section 11.2.1 for additional information on Figure 12–2. 12–42 Executable Statements Chapter 13 Directive Statements Directives are statements that control how the VAX SCAN program is compiled. Table 13–1 lists and describes VAX SCAN directives. Table 13–1: VAX SCAN Directive Statements Directive Purpose LIST Controls listing of the VAX SCAN program INCLUDE Includes part of the source program from an alternate file REDEFINE Defines the values of the VAX SCAN special characters Each of these directives is discussed in detail in this chapter. 13.1 LIST Directive The LIST directive controls how the source listing generated by the VAX SCAN compiler is printed. The syntax of the LIST directive is as follows: 8 ON > < OFF LIST > : PAGE TITLE ct-character-expression 9 > = ; > ; The LIST directive has no effect unless the VAX SCAN compiler has been requested to generate a listing of the program. A listing is generated by default if the compiler is run in batch mode. The /LISTING qualifier causes a listing to be generated in interactive mode. Directive Statements 13–1 The meaning of each listing option is shown in Table 13–2: Table 13–2: Listing Options Option Meaning ON Starts generating listing information OFF Stops generating listing information PAGE Continues listing at the top of a new page TITLE Sets the page title LIST options are affected by the INCLUDE directive. At the start of the compilation, the listing is in the ON state and has a TITLE of null string ( " ). At the start of an INCLUDE file, the listing state and title are the same as they were at the INCLUDE directive. Following the end of the INCLUDE file, the listing state and title are also the same as they were at the INCLUDE directive. Thus, a LIST directive affects only the INCLUDE file and any INCLUDE files nested within it, where the LIST directive appears. The ON option has no effect unless the listing is OFF at the time it is encountered. The OFF option has no effect unless the listing is ON at the time it is encountered. The PAGE option has no effect unless the listing is ON at the time it is encountered. The TITLE option causes the current listing page and all subsequent listing pages to have a title associated with them. If multiple TITLE options apply to a page, only the last one encountered is associated with the page. Example 13–1 shows the LIST directive. Example 13–1: LIST Directive LIST ON; LIST TITLE ’MACRO ABC’; LIST PAGE; 13–2 Directive Statements ! turn the listing back on ! set page title to "MACRO ABC" ! force a new page 13.2 INCLUDE Directive The INCLUDE directive redirects the source program to an alternate file. The syntax of the INCLUDE directive is as follows: INCLUDE FILE ct-character-expression ; When the VAX SCAN compiler encounters an INCLUDE directive, it stops reading the source program from the current input file and starts reading the source program from the file specified by the INCLUDE directive. Once the entire INCLUDE file has been read, the compiler continues reading the source program at the statement following the INCLUDE directive. The INCLUDE file must contain zero or more complete statements, not statement fragments. Following the keyword FILE is a string constant expression that specifies the VAX/VMS file specification of the file to include. If the file specification contains no directory specification, the current default directory is used. An INCLUDE file can itself contain INCLUDE files. The VAX SCAN compiler imposes no restriction on how deeply INCLUDE files are nested. The following example shows the INCLUDE directive: INCLUDE FILE ’common.def’; ! include source in file COMMON.DEF ! in the default directory 13.3 REDEFINE Directive The VAX SCAN language defines three special characters, as shown by Table 13–3. Table 13–3: VAX SCAN Special Characters Character Meaning Default Hexadecimal Value S’SOS’ Start of stream 02 S’EOL’ End of line 85 S’EOS’ End of stream 03 Directive Statements 13–3 The REDEFINE directive permits you to change the value of these characters. The syntax of the REDEFINE directive is as follows. ( S’SOS’ ) REDEFINE = ct-character-expression ; S’EOL’ S’EOS’ A macro set must have a consistent set of definitions for the VAX SCAN special characters. Therefore, all REDEFINE directives must occur before any SET, TOKEN, or MACRO definitions and also before any reference to a special VAX SCAN character. The string constant expression specifying the new value must have a length of one. The REDEFINE directive is useful if your particular application ascribes special meaning to the characters X’02’, X’03’, and X’85’. If these defaults are unsuitable, REDEFINE allows you to map the VAX SCAN special characters to other values. Example 13–2 shows the REDEFINE directive. Example 13–2: REDEFINE Directive REDEFINE s’eol’ = x’01’; REDEFINE s’sos’ = s’del’; 13–4 Directive Statements Chapter 14 VAX/VMS Run-Time Library Routines and System Services System routines are procedures and functions provided by the VAX/VMS operating system. Each system routine has an entry point (the routine or service name) and an argument list. Each system routine may also return a function value or condition value to the program that calls it. System routines perform common tasks, such as finding the square root of a number or allocating virtual memory. If you use system routines, you will not have to rewrite code every time you want to perform a common task. Using system routines allows you to concentrate on application-specific tasks, not utility tasks. Some system routines even help independent parts of programs to allocate resources cooperatively. A system routine can be called from any VAX/VMS language that supports the data structures required by the particular routine. The results of a system routine are the same, regardless of the language used. The system routines that are most commonly called from user programs are VAX/VMS Run-Time Library routines and VAX/VMS system services. These system routines are documented in the (VMS_RTLROUT_R) and the (VMS_ SYSROUT_R). VAX/VMS Run-Time Library Routines and System Services 14–1 14.1 VAX/VMS Run-Time Library Routines VAX/VMS Run-Time Library routines are assigned facility names that represent specific types of common tasks. These facilities and the types of tasks they perform are shown in Table 14–1. Table 14–1: VAX/VMS Run-Time Library Facilities Facility Tasks LIB$ General purpose procedures that obtain records from devices, manipulate strings, convert data types for I/O, allocate resources, obtain the system date or time, signal exceptions, establish condition handlers, enable detection of hardware exceptions, and process cross-reference data. MTH$ Mathematics procedures that perform arithmetic, algebraic, and trigonometric calculations. OTS$ Language-independent support procedures that perform tasks such as data type conversions as part of a compiler’s generated code. SMG$ Screen management procedures that assist you in designing, composing, and keeping track of complex images on a video screen and that provide terminal-independent tasks. STR$ String manipulation procedures that perform tasks such as searching for substrings, concatenating strings, and prefixing and appending strings. 14.2 System Services Routines VAX/VMS system services are routines that perform various tasks such as controlling processes, communicating among processes, and coordinating I/O. Unlike VAX/VMS Run-Time Library routines that are grouped by facility name, all VAX/VMS system services share the same facility prefix (SYS$). However, these services are logically divided into groups of services that perform similar tasks. Table 14–2 describes these groups. 14–2 VAX/VMS Run-Time Library Routines and System Services Table 14–2: Groups of VAX/VMS System Services Groups Tasks AST Allow processes to control the handling of ASTs Change Mode Changes the access mode of particular routines Condition Handling Designates condition handlers for special purposes Event Flag Clears, sets, reads, and waits for event flags, and associates with event flag clusters Information Returns information about the system, queues, jobs, processes, locks, and devices Input/Output Performs I/O directly, without going through VAX RMS Lock Management Enables processes to coordinate access to shareable system resources Logical Names Provides methods of accessing and maintaining pairs of character string logical names and equivalence names Memory Management Increases or decreases available virtual memory, control paging and swapping, and creates and accesses shareable files of code or data Process Control Creates, deletes, and controls execution of processes Security Enhances the security of VAX/VMS systems Timer and Time Conversion Schedules events, and obtains and formats binary time values 14.3 Calling System Routines from VAX SCAN The following seven steps are required to call any system routine: 1. Determine the type of call (procedure or function) 2. Declare the arguments 3. Declare the system routine VAX/VMS Run-Time Library Routines and System Services 14–3 4. 5. 6. 7. Include symbol definitions (if applicable) Call the system routine Check the condition value (if applicable) Locate the result As an example, you can follow these steps in writing a program to call LIB$STAT_TIMER, which returns to its caller one of five statistics: ( 1 ) elapsed time, ( 2 ) CPU time, ( 3 ) buffered I/O count, ( 4 ) direct I/O count, or ( 5 ) page fault count. 14.3.1 Determine the Type of Call (Procedure or Function) Before you can set up a call to a system routine, you must determine whether the call to the routine or service should be a subroutine call or a function call. A system routine must be called as a function if it returns either of the following: • • A function value A condition value NOTE A system routine should be called as a subroutine only if it does not return a function value or a condition value. Although it is possible to call most of the system routines as subroutines, it is recommended that you do so only when the text in the Returns section contains: RETURNS None. You may call a system routine as a subroutine if you are not interested in the condition code. However, this is highly discouraged because not checking the condition code can lead to many undiscovered errors. (Checking condition values is described in Section 1.2.6.) To determine whether a routine returns a function value or a condition value, look at the description provided in the Returns section of the system routine description. For example, the Returns section of 14–4 VAX/VMS Run-Time Library Routines and System Services the LIB$STAT_TIMER system routine documentation contains the following description. RETURNS VMS Usage: type: access: mechanism: cond_value longword (unsigned) write only by value If this text appears in the Returns section, the system routine returns a condition value and must be called as a function. In routines that return function values, the function value is described in the Returns section. Because LIB$STAT_TIMER does return condition values, you must call it as a function. 14.3.2 Declare the Arguments Most system routines have one or more arguments. These arguments are used to pass information to the system routine and to obtain information from the system routine. Arguments can be either required or optional. For example, consider the arguments for the VAX/VMS Run-Time Library routine LIB$STAT_TIMER. This routine has three arguments: two are required and one is optional. You can tell which arguments are required by looking at the Format section in the documentation of the system routine. In the case of LIB$STAT_TIMER, the format is as follows: " LIB$STAT_TIMER code ,value # ,handle-adr The handle-adr argument appears in brackets ( [ ] ), indicating that it is an optional argument. For this example, you want to use only the two required arguments, so you need declare only the first two arguments. To declare an argument for a system routine, you need to first look at that argument’s description. The argument description provided for the code argument is as follows: VAX/VMS Run-Time Library Routines and System Services 14–5 code VMS Usage: type: access: mechanism: function_code longword integer (signed) read only by reference Code that specifies the statistic to be returned. The code argument contains the address of a signed longword integer that is this code. It must be an integer from one to five. Next, look at the VMS Usage entry, function_code. Table 14–3 lists the VAX SCAN equivalent for each of the VMS Usages. You can declare the argument using the code provided in Table 14–3. In this case, the declaration appears as follows: DECLARE code: INTEGER; Follow this same procedure for the value argument as well. First, check the description of the value argument. value VMS Usage: varying_arg type: unspecified access: write only mechanism: by reference The statistic returned by LIB$STAT_TIMER. The value argument contains the address of a longword or quadword that is this statistic. All statistics are longword integers except elapsed time, which is a quadword. The VMS Usage varying_arg indicates that the data type returned by the routine is dependent on other factors. In this case, the data type returned is dependent upon which statistic you wish to return. For this example, the statistic that you wish to return is code 5, page fault count. This statistic is returned in a signed longword integer. Therefore, you need to check Table 14–3 to find the VAX SCAN statements that are used to declare a longword_signed. DECLARE page_faults: INTEGER; The declaration statements for all VAX/VMS Run-Time Library routine or system services arguments can be found by looking up the VMS Usage in Table 14–3. 14–6 VAX/VMS Run-Time Library Routines and System Services Table 14–3: VAX/VMS Data Structures VAX/VMS Data Structure VAX SCAN Equivalent access_bit_name FILL( 8*32 )1 access_mode FILL( 1 )1 address POINTER address_range RECORD start: POINTER, end: POINTER, END RECORD arg_list RECORD count: INTEGER, arg1: POINTER, arg2: INTEGER, ... END RECORD ! if by reference ! if by value ! depending on need 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 length complex_number FILL( x ) where x is length1 cond_value INTEGER context INTEGER date_time FILL( 8 )1 device_name FIXED STRING( x ) where x is length ef_cluster_name FIXED STRING( x ) where x is length ef_number INTEGER exit_handler_block FILL( x ) where x is length1 1 FILL is a data type that can always be used. A FILL is an object that is between 0 and 65K bytes in length. VAX SCAN makes no interpretation of the object’s contents. Thus, it can be used to pass or return the object to another language that does understand the type. 2 VAX SCAN BOOLEAN is one byte. VAX/VMS Run-Time Library Routines and System Services 14–7 Table 14–3 (Cont.): VAX/VMS Data Structures VAX/VMS Data Structure VAX SCAN Equivalent fab Too complex to include in this chart. Most of it can be described with a VAX SCAN record. However, it is much simpler and less prone to error to access fabs from other languages that have the record predefined. file_protection FILL( 2 )1 floating_point FILL( x ) where x is length1 function_code INTEGER io_status_block FILL( 8 )1 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_quota_list RECORD item1: RECORD type: FILL( 1 ), value: INTEGER, END RECORD, item2: RECORD type: FILL( 1 ), value: INTEGER, END RECORD, ... terminator: FILL( 1 ), lock_id INTEGER 1 FILL ! depending on need ! depending on need is a data type that can always be used. A FILL is an object that is between 0 and 65K bytes in length. VAX SCAN makes no interpretation of the object’s contents. Thus, it can be used to pass or return the object to another language that does understand the type. 14–8 VAX/VMS Run-Time Library Routines and System Services Table 14–3 (Cont.): VAX/VMS Data Structures VAX/VMS Data Structure VAX SCAN Equivalent lock_status_block RECORD status : FILL( 2 ), reserved: FILL( 2 ), lock_id : INTEGER, END RECORD1 lock_value_block FILL( 16 )1 logical_name FIXED STRING( x ) where x is 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 * 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 length quadword_signed FILL( 8 )1 quadword_unsigned FILL( 8 )1 rights_holder RECORD rights_id: INTEGER, bitmask : INTEGER, END RECORD 1 FILL is a data type that can always be used. A FILL is an object that is between 0 and 65K bytes in length. VAX SCAN makes no interpretation of the object’s contents. Thus, it can be used to pass or return the object to another language that does understand the type. VAX/VMS Run-Time Library Routines and System Services 14–9 Table 14–3 (Cont.): VAX/VMS Data Structures VAX/VMS Data Structure VAX SCAN Equivalent rights_id INTEGER rab Too complex to include in this chart. Most of it can be described with a VAX SCAN record. However, it is much simpler and less prone to error to access rabs from other languages that have the record predefined. second_name FILL( 8 )1 section_name FIXED STRING( x ) where x is length system_access_id FILL( 8 )1 time_name FIXED STRING( x ) where x is length uic INTEGER user_arg INTEGER varying_arg INTEGER vector_byte_signed FILL( x ) where x is length1 vector_byte_unsigned FILL( x ) where x is length1 vector_longword_signed FILL( 4*x ) where x is length1 vector_longword_unsigned FILL( 4*x ) where x is length1 vector_quadword_signed FILL( 8*x ) where x is length1 vector_quadword_unsigned FILL( 8*x ) where x is length1 vector_word_signed FILL( 2*x ) where x is length1 vector_word_unsigned FILL( 2*x ) where x is length1 word_signed FILL( 2 )1 word_unsigned FILL( 2 )1 1 FILL is a data type that can always be used. A FILL is an object that is between 0 and 65K bytes in length. VAX SCAN makes no interpretation of the object’s contents. Thus, it can be used to pass or return the object to another language that does understand the type. 14.3.3 Declare the System Routine Declare a system routine in your program as you would declare any other external procedure. The declaration will vary depending on whether the system routine is being called as a subroutine or function. 14–10 VAX/VMS Run-Time Library Routines and System Services The procedure declaration for calling LIB$STAT_TIMER as a function should appear as follows: EXTERNAL PROCEDURE lib$stat_timer (INTEGER,INTEGER) OF INTEGER; The procedure declaration for calling LIB$STAT_TIMER as a subroutine should appear as follows: EXTERNAL PROCEDURE lib$stat_timer(INTEGER,INTEGER); 14.3.4 Include Symbol Definitions Many system routines depend on values that are defined in separate symbol definition files. For example, when you call any VAX/VMS Run-Time Library routine in the SMG$ facility, you would include SMGDEF. VAX SCAN has no capability for including symbol definitions from text libraries. This can be accomplished by creating an INCLUDE file with the desired symbol definitions. You would then use the INCLUDE directive in each VAX SCAN module that uses these definitions. The following is a segment of INCLUDE file SMGDEF.INC, which was created for an example program: EXTERNAL PROCEDURE smg$create_pasteboard ( integer, string, integer, integer ); EXTERNAL PROCEDURE smg$create_virtual_display ( integer, integer, integer, integer, integer ); EXTERNAL PROCEDURE smg$read_string ( integer, string, string, value integer, value integer, value integer, value integer, value integer, value integer, integer ) of integer; CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT bold reverse blink underline normal = = = = = 1; 2; 4; 8; 0; This can be referenced in each VAX SCAN module as follows: INCLUDE FILE ’smgdef.inc’; LIB$STAT_TIMER does not use any included definition files, so this step is not applicable for this example. VAX/VMS Run-Time Library Routines and System Services 14–11 14.3.5 Call the Routine or Service The call to the routine or service is set up as an external call in VAX SCAN. The syntax of the call statement will depend on whether the call is a function call or a subroutine call. 14.3.5.1 Calling a System Routine in a Function Call In this example, LIB$STAT_TIMER returns a condition value called ret_status. To call a system routine, set up the function call in the same order as the FORMAT in the routine or service description. In this case, the format is as follows: " LIB$STAT_TIMER code ,value # ,handle-adr As stated earlier, you are not using the optional handle-arg argument. In a format statement, an optional argument can appear in one of two ways: " # ,optional-argument or , " # optional-argument If the comma appears outside of the brackets (,[optional-argument]), you must pass a zero by value ( * ) to indicate the place of the omitted argument. If the comma appears inside the brackets ([,optional-argument]), you can omit the argument altogether as long as it is the last arguments in the list. For example, look at the optional arguments of an imaginary routine, LIB$EXAMPLE_ROUTINE: LIB$EXAMPLE_ROUTINE arg1 [,arg2] [,arg3] [,arg4] In VAX SCAN the number of arguments in a call to a procedure must be the same as the number of arguments declared in the EXTERNAL PROCEDURE declaration. Thus, you could declare and reference the function as follows: 14–12 VAX/VMS Run-Time Library Routines and System Services EXTERNAL PROCEDURE lib$example_routine (arg1_type) OF INTEGER; ret_status = LIB$EXAMPLE_ROUTINE(arg1); This EXTERNAL PROCEDURE declaration dictates that all references to the function have one argument. Consequently, it is usually better to declare the procedure in VAX SCAN with all its potential arguments: EXTERNAL PROCEDURE lib$example_routine (arg1_type,arg2_type,arg3_type,arg4_type) OF INTEGER; ret_status = LIB$EXAMPLE_ROUTINE(arg1,arg2,arg3,arg4); Now if you wish to call the function with fewer arguments, use an asterisk ( * ) for those arguments you wish to omit. ret_status = LIB$EXAMPLE_ROUTINE(arg1,*,*,*); ret_status = LIB$EXAMPLE_ROUTINE(arg1,*,arg3,*); In general, VAX/VMS Run-Time Library routines use the format [,optional-argument], while system services use the format ,[optionalargument]. In passing the arguments to the procedure, you must declare the passing mechanism required if it is not the default. The default values for VAX SCAN are listed in Table 14–4. Table 14–4: Default Passing Mechanisms in VAX SCAN VAX SCAN Data Type Default Passing Mechanism Integer Reference Boolean Reference Pointer Reference Treeptr Reference Fill Reference Fixed string Reference Varying string Reference Dynamic string Descriptor Record Reference Overlay Reference Tree Reference File Reference VAX/VMS Run-Time Library Routines and System Services 14–13 The passing mechanism required for a system routine argument is indicated in the argument description. This is shown in the following description of the one-char-str argument to LIB$CHAR: one-char-str VMS Usage: char_string type: character string access: write only mechanism: by descriptor In this case, the passing mechanism required is ‘‘by descriptor.’’ The passing mechanisms allowed in system routines are those listed in the VAX Procedure Calling and Condition Handling Standard in the Introduction to VAX/VMS System Routines. When the passing mechanism expected by the routine or service is different from the default mechanism in VAX SCAN, you must override the default. To force an argument to be passed by a specific passing mechanism, use the specifiers listed in Table 14–5. Table 14–5: Overriding the Default Passing Mechanism Passing Mechanism Desired Specifier Required By value VALUE By reference REFERENCE By descriptor DESCRIPTOR NOTE Any passing mechanisms not listed in this table are both unnecessary and unsupported in VAX SCAN. If a system routine requires a passing mechanism not listed in this table, it is not possible to call that routine from VAX SCAN. Even when you are using the default passing mechanism, you can insert the specifier to document exactly what passing mechanism was used. For example, to call LIB$STAT_TIMER you may use either of the following two declarations: EXTERNAL PROCEDURE lib$stat_timer (REFERENCE INTEGER,REFERENCE INTEGER) OF INTEGER; or EXTERNAL PROCEDURE lib$stat_timer (INTEGER,INTEGER) OF INTEGER ; 14–14 VAX/VMS Run-Time Library Routines and System Services 14.3.5.2 Calling a System Routine in a Subroutine Call If the routine or service you are calling does not return a function value or condition value, you may call the system routine as a subroutine. The same rules apply to optional arguments, and you still follow the calling sequence presented in the Format section. One system routine that does not return a condition value or function value is the VAX/VMS Run-Time Library routine LIB$SIGNAL. LIB$SIGNAL should always be called as a subroutine, as shown in the following code: EXTERNAL PROCEDURE lib$signal( INTEGER ); CONSTANT lib$_invarg EXTERNAL INTEGER; CALL lib$signal( lib$_invarg ); 14.3.6 Check the Condition Value After you call the system routine and control is returned to your program, you should check the condition value returned, if there is one. In general, all system routines return a condition value with the following exceptions: • • • • The system routine returns a function value. (If the routine returns a function value, this is described in the Returns section.) The Condition Values Returned section states ‘‘None.’’ There is no Condition Values Returned section, but rather a Condition Values Signaled section. (Success conditions are not signaled.) The call to the routine was made as a subroutine call. (In this case, no condition values are returned.) If any of the conditions listed above apply, there is no condition value to check. If there is a condition value, you must check this value to make sure that it indicates success. All success condition values are listed in the Condition Values Returned section of the system routine description. Success condition values always appear first in this list. VAX/VMS Run-Time Library Routines and System Services 14–15 Many system routines return the condition value SS$_NORMAL as a success value. If this is the only possible success condition, you can test for its presence in the following way: EXTERNAL PROCEDURE lib$stop( INTEGER ); EXTERNAL PROCEDURE lib$stat_timer(INTEGER,INTEGER) OF INTEGER; CONSTANT ss$_normal EXTERNAL INTEGER; DECLARE ret_status,code,value : INTEGER; ret_status = lib$stat_timer( code,value ); IF ret_status <> ss$_normal THEN CALL lib$stop( ret_status ); END IF; It is also possible to check for any success code because all success codes have an odd value (not evenly divisible by two). The following code will continue execution if any success code is returned. ret_status = lib$stat_timer( code,value ); IF ( ret_status AND 1 ) = 0 THEN CALL lib$stop( ret_status ); END IF; Sometimes several success condition values are possible. You may only want to continue execution on specific success codes. For example, the system service $SETEF returns one of two success values, SS$_ WASSET or SS$_WASCLR. If you only want to continue when the success code SS$_WASSET is returned, you can check for this condition value as follows: EXTERNAL PROCEDURE sys$setef( INTEGER ); CONSTANT ss$_wasset EXTERNAL INTEGER; ret_status = sys$setef( efnumber ); IF ret_status = ss$_wasset THEN . . ! necessary steps . END IF; If the condition value returned is not a success condition, then the routine did not complete normally, and the information it was supposed to return may be missing, incomplete, or incorrect. 14–16 VAX/VMS Run-Time Library Routines and System Services If the condition value returned was not a success code, you can check for a particular error condition, as shown in the following example. EXTERNAL PROCEDURE sys$setef( INTEGER ); CONSTANT ss$_wasset EXTERNAL INTEGER; CONSTANT ss$_wasclr EXTERNAL INTEGER; ret_status = sys$setef( efnumber ); IF ret_status = ss$_wasset THEN WRITE ’EVENT FLAG was set’; GOTO continue; END IF; IF ret_status = ss$_wasclr THEN WRITE ’EVENT FLAG was clear’; GOTO continue; END IF; !+ ! Unexpected status returned - signal error !CALL lib$signal( ret_status ); continue: . . . 14.3.7 Locate the Result After you have declared the arguments, called the procedure, and checked the condition value, you are ready to use the result. To find out where the result is returned, look at the description of the system routine you are calling. 14.3.7.1 Function Results If the routine is a function, the result is written into the argument that appears to the left of the equal sign in the function call. For example, in this call to LIB$INDEX the result is written into the variable result: VAX/VMS Run-Time Library Routines and System Services 14–17 EXTERNAL PROCEDURE lib$index( STRING,STRING ) OF INTEGER; DECLARE result : INTEGER; result = lib$index( ’The rain in Spain’, ’in’ ); This result is described in the Returns section of the system routine description. 14.3.7.2 Subroutine Results If the system routine is called as a subroutine, the result is written into one or more of the arguments. To determine which argument(s) holds the result, examine the ‘‘access’’ entry in the argument descriptions. If the access entry in an argument description says ‘‘write only’’ or ‘‘modify’’, that argument contains output information written by the subroutine. For example, LIB$CURRENCY returns the default system currency symbol ( $ ). Looking at the argument descriptions, you know that the currency string is returned in the currency_str argument. currency_str VMS Usage: char_string type: character string access: write only mechanism: by descriptor In all system routines, the output information returned by the routine or service has an access of ‘‘write only’’ or ‘‘modify’’. EXTERNAL PROCEDURE lib$currency ( DESCRIPTOR FIXED STRING (10), INTEGER ); DECLARE currency_symbol : FIXED STRING (10); DECLARE currency_length : INTEGER; CALL lib$currency( currency_symbol, currency_length ); WRITE ’Currency symbol is ’, currency_symbol[1..currency_length]; 14.4 Examples The following examples demonstrate calls to system routines in VAX SCAN programs. 14–18 VAX/VMS Run-Time Library Routines and System Services Example 14–1 is a VAX SCAN program that calls the VAX/VMS RunTime Library routine LIB$FIND_FILE. VAX/VMS Run-Time Library Routines and System Services 14–19 Example 14–1: VAX SCAN Program Calling LIB$FIND_FILE MODULE global_replace; !+ ! Replace the string ’1985’ with the string ’1986’ in a set of files. !CONSTANT source_text = ’1985’; ! text to be replaced CONSTANT replacement_text = ’1986’; ! text to replace with TOKEN source_token { source_text }; ! text to be replaced MACRO replace_string TRIGGER { source_token }; ANSWER replacement_text; END MACRO; CONSTANT rms$_nmf EXTERNAL INTEGER; ! No more files EXTERNAL PROCEDURE lib$find_file ( STRING, STRING, INTEGER ) OF INTEGER; EXTERNAL PROCEDURE lib$find_file_end ( INTEGER ) OF INTEGER; EXTERNAL PROCEDURE lib$stop ( VALUE INTEGER ); PROCEDURE main MAIN; DECLARE file_spec, in_file_name, out_file_name : STRING; DECLARE status, context: INTEGER; !+ ! !- Get the optionally wildcarded file specification to be processed. READ PROMPT ( ’Enter file specification to process: ’ ) file_spec; context = 0; status = lib$find_file ( file_spec, in_file_name, context ); WHILE ( status AND 1 ) = 1; Example 14–1 Cont’d. on next page 14–20 VAX/VMS Run-Time Library Routines and System Services Example 14–1 (Cont.): VAX SCAN Program Calling LIB$FIND_FILE !+ ! ! !- The output file will be a new version of the input file, so we strip off the semicolon from the input file name. out_file_name = in_file_name [ 1 .. index ( in_file_name, ’;’ ) - 1 ]; !+ ! !- Display the name of each file as it is processed. WRITE ’processing: ’, in_file_name; START SCAN INPUT FILE in_file_name OUTPUT FILE out_file_name; status = lib$find_file ( file_spec, in_file_name, context ); END WHILE; !+ ! !- Be sure we finished normally IF status <> rms$_nmf THEN CALL LIB$STOP ( status ); END IF; !+ ! !- Free the find_file context status = lib$find_file_end ( context ); IF ( status AND 1 ) <> 1 THEN CALL LIB$STOP ( status ); END IF; END PROCEDURE /* main */; END MODULE /* global_replace */ ; Example 14–2 is a complete VAX SCAN program that calls the SYS$FILESCAN system service. VAX/VMS Run-Time Library Routines and System Services 14–21 Example 14–2: VAX SCAN Program Calling SYS$FILESCAN MODULE decompose_file_spec; !+ ! Describe an item descriptor of $FILESCAN and ! a list of such items. !TYPE item : RECORD ctrl : INTEGER, data_ptr: POINTER TO FIXED STRING( 100 ), END RECORD; TYPE item_args : RECORD node: device: directory: name: ext: version: end_flag: END RECORD; !+ ! ! !- item, item, item, item, item, item, INTEGER, These are the Item Codes for $FILESCAN. They are multiplied by 65536 to place them in the high order word of the integer. CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT fscn$_node fscn$_device fscn$_directory fscn$_name fscn$_ext fscn$_version = = = = = = 2 3 5 6 7 8 * * * * * * 65536; 65536; 65536; 65536; 65536; 65536; EXTERNAL PROCEDURE sys$filescan ( DESCRIPTOR DYNAMIC STRING, REFERENCE item_args, REFERENCE INTEGER ) OF INTEGER; Example 14–2 Cont’d. on next page 14–22 VAX/VMS Run-Time Library Routines and System Services Example 14–2 (Cont.): VAX SCAN Program Calling SYS$FILESCAN PROCEDURE parse_file_spec ( file_spec: STRING ); DECLARE args: item_args; DECLARE status: INTEGER; !+ ! Place the item codes in the item descriptors. !args.node.ctrl = fscn$_node; args.device.ctrl = fscn$_device; args.directory.ctrl = fscn$_directory; args.name.ctrl = fscn$_name; args.ext.ctrl = fscn$_ext; args.version.ctrl = fscn$_version; !+ ! !- Mark the end of the list. args.end_flag = 0; status = sys$filescan( file_spec, args, * ); !+ ! ! !- Check status returned by system service. (odds) continue; Failures return. Success codes IF (status AND 1) = 0 THEN RETURN; END IF; !+ ! !- Write out the file spec components. Example 14–2 Cont’d. on next page VAX/VMS Run-Time Library Routines and System Services 14–23 Example 14–2 (Cont.): VAX SCAN Program Calling SYS$FILESCAN WRITE ’node: ’, args.node.data_ptr-> [1 .. (args.node.ctrl AND 65535) ]; WRITE ’device: ’, args.device.data_ptr-> [1 .. (args.device.ctrl AND 65535) ]; WRITE ’directory: ’, args.directory.data_ptr-> [1 .. (args.directory.ctrl AND 65535) ]; WRITE ’name: ’, args.name.data_ptr-> [1 .. (args.name.ctrl AND 65535) ]; WRITE ’ext: ’, args.ext.data_ptr-> [1 .. (args.ext.ctrl AND 65535) ]; WRITE ’version: ’, args.version.data_ptr-> [1 .. (args.version.ctrl AND 65535) ]; END PROCEDURE /* parse_file_spec */; END MODULE /* decompose_file_spec */; 14.5 For Additional Information The information provided in this chapter is general to all VAX/VMS system services and VAX/VMS Run-Time Library routines. For specific information on these routines, refer to the (VMS_ RTLROUT_R) and the (VMS_SYSROUT_R). For additional information on coding considerations when using external routines, refer to the (VMS_ROUTINTRO_R) and the (VMS_APPLICATIONS_H). Chapter 2 of the (VMS_ROUTINTRO_R) contains the VAX Procedure Calling and Condition Handling Standard. The VAX/VMS Modular Programming Standard can be found in Appendix A of the (VMS_APPLICATIONS_H). All of these manuals can be found in the VAX/VMS documentation set. 14–24 VAX/VMS Run-Time Library Routines and System Services Chapter 15 Error Messages and HELP 15.1 Error Messages Two types of errors can occur in a VAX SCAN program. The first is a syntactic error in the source program when the program does not conform to the syntax diagrams or syntactic rules described in this manual. The VAX SCAN compiler issues diagnostics for this type of error. The second type of error occurs when a syntactically correct program performs an action that is forbidden. Examples of this type of error are integer overflow, opening a file that is already in the open state, and answering text when no picture matching is in progress. Many errors of this type are diagnosed by the VAX SCAN compiler. Others are diagnosed only when the program is executed. Each error message is a one-line explanation of the problem. The VAX SCAN HELP library lists both the compile-time and run-time error messages. Each message in the HELP library is accompanied by a further short explanation. 15.2 Accessing VAX SCAN HELP To access the VAX SCAN HELP library on your system at the DCL level, type HELP and press the RETURN key. Then, at the Topic? prompt in the HELP facility, type SCAN and press the RETURN key. (To directly access the VAX SCAN HELP library from the DCL level, simply type HELP SCAN and press the RETURN key.) This section shows the steps to obtain information on a specific subject. For Error Messages and HELP 15–1 example, if you have run a VAX SCAN program, which results in the error message OVFTOKTEX, type the following: $ HELP SCAN RETURN The system responds as follows: SCAN VAX SCAN is a string manipulation language. The language is particularly useful for building preprocessors, translators, and filters. The SCAN command invokes the VAX SCAN compiler to compile a VAX SCAN source program. Format SCAN filespec[,...] Additional information available: /DIAGNOSTICS[=file-spec] /DEBUG[ =(options,...) ] /ERROR_LIMIT [=n] /LIST[=file-spec] /MACHINE_CODE /OBJECT[=file-spec] /OPTIMIZE /SHOW=(option,...) /WARNINGS Parameters Runtime_Errors Compile_Time_Errors Release_Notes Using_Scan Language_topics SCAN Subtopic? You reply by entering the name of the category for which you need additional help, as follows: RUNTIME_ERRORS RETURN The system responds as follows: SCAN Runtime_Errors Additional information available: 15–2 Error Messages and HELP ANSWER BADDATTYP CASERANGE ENDRECORD FILCLSFAL FILPRVCLS INPSTMCLS INTERROR INVGSBTAG INVTRECLS INVTSBTAG NILTREPTR OUTFILWRT OUTSTMOPN OVFTOKTEX PRUNETREE STOPSCAN STRTOOLON TOKOUTRAN UNKDSCCLA WRAPREC ANSWERTXT BADSUBTYP ENDINPSTM EPILOG FILNOTOPN FILPRVOPN INPSTMOPN INTOVFL INVINSTR INVTREPTR MAXTRELEV NOTOKDEF OUTRECTRN OUTSTMWRT PASENDSTM RECOVER_PICTURE STRBOLFMT SUBSTRERR TRENODNOT VARASSIGN BADBUFLEN BADTREPTR ENDOUTSTM FAIL FILOPNFAL INPFILREA INPSTMREA INVGSBLEV INVSTMTYP INVTREROO NILPTR NOVALURET OUTSTMCLS OVFPICSTK PICTURE STASCAARG STRINTFMT TOKEN UNDPICSTK VARPRUNE SCAN Runtime_errors Subtopic? Find the name of the error message that you received, in this case, OVFTOKTEX, and enter it as follows: OVFTOK RETURN (Typing the least ambiguous sequence of characters is sufficient.) The system responds as follows: SCAN Runtime_Errors OVFTOKTEX Fatal error. The text stored in a picture variable is initially captured in a buffer of fixed length. The error indicates that the buffer is full. User action. Use the DATA STACK clause of the START SCAN to increase the size of the buffer. statement This example shows the steps to follow upon receiving any error message, or for obtaining information on any HELP topic. Error Messages and HELP 15–3 Chapter 16 Debugging VAX SCAN Programs The VAX/VMS Debugger can be used to locate errors that happen during execution of your VAX SCAN program. The majority of debugging actions (including both your logical approach and the commands you use) are conventional and customary to programming; in addition, there are features and tools built into the debugger to allow isolation and correction of program bugs involving unique elements and constructs of the VAX SCAN language. For detailed information on the VAX/VMS Debugger, see the VAX/VMS Debugger Reference Manual. 16.1 Activating the VAX/VMS Debugger At each step in compiling, linking, and executing your program, you can specify command qualifiers that affect how the debugger is used. At compile time, you use the /DEBUG qualifier to cause the compiler to include local symbol and traceback information in the object module that will be used as input to the linker. At link time, use of the /DEBUG qualifier will cause local symbol and traceback information created by the compiler to be included in the executable image. At run time, the debugger will automatically be entered if the /DEBUG qualifier was used with the SCAN and LINK commands. If you did not specify the /DEBUG qualifier at link time, you may do so with the RUN command; however, it will not be possible to debug using local symbols. If you compiled and linked with the /DEBUG qualifier but do not wish to enter the debugger at run time, you can add the /NODEBUG qualifier to the RUN command. Debugging VAX SCAN Programs 16–1 Table 16–1 lists the effects of the SCAN, LINK, and RUN commands when used with the VAX/VMS Debugger qualifiers. Table 16–1: DEBUG Command Qualifiers Command Qualifier Effect SCAN /DEBUG The VAX SCAN compiler creates symbolic data needed by the debugger. SCAN {none} No symbol table is built for debugging. You may debug using traceback only. LINK /DEBUG Symbolic data created by the VAX SCAN compiler is passed to the debugger. The debugger will be entered at run time. LINK {none} No symbols passed to the debugger. You may call the debugger at run time, but you cannot debug using local symbols. The VAX SCAN program source will not be available in screen mode debugging. RUN /DEBUG Invokes the debugger. Not needed if LINK/DEBUG was specified. RUN /NODEBUG Suppresses the debugger if it was specified in the LINK command. 16.2 VAX SCAN Symbolic Debugging To perform symbolic debugging, you must use the /DEBUG qualifier with both the SCAN and LINK commands, but you need not specify it with the RUN command. If /DEBUG is omitted from either the SCAN or LINK command, you can still use it with the RUN command to invoke the debugger. However, any debugging you perform must then be done by specifying virtual addresses rather than symbolic names. 16–2 Debugging VAX SCAN Programs 16.2.1 VAX SCAN Elements Available for Debugging The VAX/VMS Debugger allows you to refer to symbolic names and line numbers. The VAX/VMS Debugger maintains a symbol table that describes the VAX SCAN program symbols you can reference during a debugging session. When you are debugging VAX SCAN programs, you can reference variables and constants symbolically (just as in FORTRAN, PASCAL, and other VAX/VMS family languages). 16.2.1.1 Names When debugging VAX SCAN programs you can use the names of the following constructs: • • • • • 16.2.1.2 Procedures Macros Constants Variables Labels Line Numbers The line numbers assigned by the compiler may be used to debug at the statement level. To break just prior to the execution of a VAX SCAN statement, you set a break on the line number that contains the semicolon ( ; ) that terminates that statement. Because VAX SCAN (like other similar languages) allows statements to span several lines, it is important to identify the correct line number to the VAX/VMS Debugger. For example, an IF . . . THEN statement may begin on line 34 of a program and end on line 64 (which is the line containing the semicolon ( ; )). In this case, a break must be identified for line 64. The following example sets a break on source line 125: DBG> SET BREAK %LINE 125 To find the line number that corresponds to a statement, you can look at either the source listing produced by the VAX SCAN compiler, or at the source display in the debugger itself. Debugging VAX SCAN Programs 16–3 16.2.2 Controlling Program Execution To see what happens during execution of your VAX SCAN program, you can suspend and resume the program at specific breakpoints, tracepoints, or on specified events. The following commands are available for these purposes: SET SHOW CANCEL y y y ...where y is: BREAK TRACE WATCH You can also use the following commands: SHOW CALLS EXIT STEP GO ! ! ! ! show the currently active procedures leave the debugger execute the current statement resume execution These commands may be entered as above, or by using one of the DEBUG-defined keypad functions. A description of the keypad can be displayed by depressing the PF2 key while in the debugger. 16.2.2.1 Breakpoints and Tracepoints Breakpoints and tracepoints may be set or canceled on the following: • • • • • Procedures Trigger Macros Syntax Macros Labels Line numbers For example: DBG> DBG> DBG> DBG> SET TRACE SET BREAK CANCEL BREAK SET BREAK %line 200 find_keyword exit compare_trees 16–4 Debugging VAX SCAN Programs ! ! ! ! trace a line number break on a trigger macro cancel break on label break on a procedure 16.2.2.2 Break on Event and Trace on Event The use of standard breakpoints and tracepoints is not especially convenient for monitoring VAX SCAN’s picture matching. Where do you set a breakpoint or tracepoint to observe the tokens built by your VAX SCAN program? There is no statement in your program on which to set such a breakpoint. To solve this problem, VAX SCAN defines several events. By setting one or more breaks or traces on these events, you can observe the picture matching process. VAX SCAN defines the following events: TRIGGER_MACRO Each time a trigger macro is activated or terminated SYNTAX_MACRO Each time a syntax macro is activated or terminated TOKEN Each time a token is built PICTURE Each time a picture is compared to the input stream INPUT Each time a new input stream line is read OUTPUT Each time a new output stream line is written ERROR Each time error recovery is entered or exited Thus, by setting a break on the TOKEN event, the debugger will suspend execution of your program each time a token is built. Set or cancel the monitoring of an event as follows: SET BREAK/EVENT= x SET TRACE/EVENT= x CANCEL BREAK/EVENT= x x Represents one of the events. VAX SCAN events may be abbreviated to three or more characters. For example: DBG> SET TRACE/EVENT=TOK RETURN DBG> SET BREAK/EVENT=TRIG RETURN Debugging VAX SCAN Programs 16–5 16.2.2.3 Watchpoints You can set and cancel watchpoints on VAX SCAN variables. However, there are special cases and considerations which must be observed, depending on the variable type and storage class. The general format is as follows: SET WATCH variable_name See Chapter 7 for information on variable types and storage classes. Some important points when using the debugger are as follows: 1. Location of the variable declaration is critical to debugging: • Variables declared at MODULE level are STATIC by default. • Variables declared at PROCEDURE or MACRO level are AUTOMATIC by default. 2. You cannot SET WATCH on variables with the AUTOMATIC attribute. 3. DYNAMIC STRING variables are dynamically built. The storage used to hold the value of the string can change when the value of the string changes. Thus, the storage the debugger is watching may not be the correct storage if the string’s value is changed. 16.2.3 Examining and Depositing You can examine contents or deposit a value into variables of all types and storage classes if they have been allocated by the compiler. The general format is: EXAMINE variable_name DEPOSIT variable_name = some_value Special properties of the following VAX SCAN variables require further discussion in connection with examining and depositing: • • • • STRING FILL POINTER TREE and TREEPTR 16–6 Debugging VAX SCAN Programs • 16.2.3.1 RECORD STRING Variables If you deposit into a FIXED STRING variable, truncation will occur if the deposited string is longer than the size established by the declaration of that variable. If you deposit into a VARYING STRING variable, truncation will occur if the deposited string is longer than the maximum size established by the declaration of that variable. If you deposit into a DYNAMIC STRING variable, truncation will occur if the deposited string is longer than the current size of the variable. With FIXED and DYNAMIC STRING variables, if the deposited string is shorter than the current size of the variable, the unfilled portion of the variable will be blank padded to the right, with the new string left justified in the variable. In the case of VARYING STRING variables, the current size of the variable storage space will be adjusted to the size of the deposited string. 16.2.3.2 FILL Variables Examining a FILL variable causes the contents of the specified variable to be displayed as a string, and so may have little meaning. If the characteristics (or type) of the fill are known, the appropriate qualifier applied to the command will produce a more meaningful display. The following command example shows a fill x that is known to be a single floating number: DBG> EXAMINE/FLOAT x 16.2.3.3 RETURN POINTER Variables You can examine a POINTER by name to find the address of the variable it points to. Use the operator that combines the minus sign and the greater than symbol ( -> ) to allow you to examine the variable that is based on the POINTER. Debugging VAX SCAN Programs 16–7 Consider this example: TYPE symnode: RECORD ptr: POINTER TO symnode, vstr: VARYING STRING( 20 ), END RECORD; DECLARE x : DECLARE xptr: xptr = x.vstr = symnode; POINTER TO symnode; POINTER(x); ’prehensile’; Now consider the following two applications of POINTER examining, based on the above program segment: DBG> EXAMINE x.vstr RETURN POINTER\ MAINPOINTER\ X.VSTR: ’prehensile’ DBG> The preceding command examines the vstr component of x. DBG> EXAMINE xptr->.vstr RETURN POINTER\ MAINPOINTER\ XPTR->.VSTR: ’ prehensile ’ DBG> The preceding command examines vstr based on the pointer. 16.2.3.4 TREE and TREEPTR Variables You can examine the contents of the nodes in a VAX SCAN tree using the following syntax: " DBG> E # XAMINE 2 66 (subscript " # treename 6 4 ) ,subscript 3 77 75 As an example, the following statements in a VAX SCAN program describe a 2-level tree having both string and integer subscripts. 16–8 Debugging VAX SCAN Programs MODULE debug_tree; DECLARE voters DECLARE cityptr DECLARE wardptr : TREE ( STRING, INTEGER) OF INTEGER; : TREEPTR ( STRING ) TO TREE (INTEGER) OF INTEGER; : TREEPTR ( INTEGER ) TO INTEGER; PROCEDURE debug_exercise MAIN; voters ( ’salem’, 1 ) = 2500; voters ( ’salem’, 2 ) = 1500; voters ( ’salem’, 3 ) = 2000; voters ( ’hudson’, 1 ) = 3500; voters ( ’hudson’, 2 ) = 3200; voters ( ’hudson’, 3 ) = 2900; voters ( ’hudson’, 4 ) = 3600; voters ( ’zork’, 1 ) = 1000; cityptr = TREEPTR ( voters ( ’hudson’ ) ); wardptr = TREEPTR ( voters ( ’hudson’, 2 ) ); END PROCEDURE /* debug_exercise */; END MODULE /* debug_tree */; Figure 16–1 shows the structure of this tree. See Section 11.2.1 for a detailed discussion of the tree in this figure. Figure 16–1: Structure of VOTER Tree ZK-4296-85 If you use the examine command with the name of the tree, the VAX/VMS Debugger will return the contents of all nodes and leaves of the tree. This is shown in the following example: Debugging VAX SCAN Programs 16–9 DBG> EXAMINE voters RETURN DEBUG_TREE\ VOTERS ’hudson’ 1: 3500 2: 3200 3: 2900 4: 3600 ’salem’ 1: 2500 2: 1500 3: 2000 ’zork’ 1: 1000 You can specify an interior node by entering the subscript for that node, as shown in the following example: DBG> E voters(’salem’) RETURN DEBUG_TREE\ VOTERS(’salem’) 1: 2500 2: 1500 3: 2000 You can examine the leaf node in a tree by specifying all subscripts leading to the desired leaf, as shown in the following example: DBG> E voters(’salem’,2) RETURN DEBUG_TREE\ VOTERS(’salem’,2): 1500 If you examine a TREEPTR, such as cityptr or wardptr, the VAX/VMS Debugger will return the address of that tree node. The following example shows how to examine what a TREEPTR variable is pointing to. The example is based on the previous program example. DBG> EXAMINE cityptr-> RETURN DEBUG_TREE\ CITYPTR-> 1: 3500 2: 3200 3: 2900 4: 3600 DEBUG_TREE\ WARDPTR->: 3200 DBG> EXAMINE wardptr-> RETURN 16–10 Debugging VAX SCAN Programs 16.2.3.5 RECORD and OVERLAY Variables If you reference a RECORD by name using the EXAMINE command, all components of the RECORD will be presented. Components of the record may be individually examined by using the full name of each component. The general format is as follows: EXAMINE recordname EXAMINE recordname.componentname.componentname . . . You examine an OVERLAY in the same way. All components are again presented; thus, if a four-byte region is a FILL(4), an INTEGER, and a VARYING STRING(2), the four bytes will be displayed three different ways. 16.3 Sample Debugging Session The sample program change_times is used to illustrate several aspects of debugging VAX SCAN programs. Assume that this program source was compiled and linked using the /DEBUG qualifier: MODULE change_times; !+ ! This is a program that locates all occurrences of times ! of the form: ! 12:34:56.7890 ! and replaces them with: ! "hh:mm:ss.xxxx" ! This could be used as a filter program to eliminate ! absolute time references in a file. !CONSTANT h = ’hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh’; CONSTANT m = ’mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm’; CONSTANT s = ’ssssssssssssssssssssssssssssssssssssssss’; CONSTANT x = ’xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’; SET digit ( ’0’ .. ’9’ ); TOKEN integer { digit... }; TOKEN colon ALIAS ’:’ {’:’}; TOKEN dot ALIAS ’.’ {’.’}; Debugging VAX SCAN Programs 16–11 MACRO replace_time TRIGGER { hh:integer ’:’ mm:integer [ ’:’ ss:integer [ ’.’ xx:integer ] ] }; ANSWER h[ 1..length( hh ) ], ’:’, m[ 1..length( mm ) ]; IF ss <> ’’ THEN ANSWER ’:’, s[ 1..length(ss) ]; END IF; IF xx <> ’’ THEN ANSWER ’.’, x[ 1..length(xx) ]; END IF; END MACRO; PROCEDURE main_routine MAIN ( ); !+ ! Start the picture matching process. The output stream is ! defined via the logical name SCN$OUTPUT. (Usually your ! terminal.) !START SCAN INPUT FILE ’with_time.dat’ OUTPUT FILE ’SYS$OUTPUT’; END PROCEDURE; END MODULE; When the sample program change_times is run, the debugger is automatically entered, resulting in the following notification on your terminal screen: VAX DEBUG Version XX.X-X %DEBUG-I-INITIAL, language is SCAN, module set to ’CHANGE_TIMES’ DBG> For this example you wish to use SCREEN mode, so you press PF3 on the keypad. The full form of the command is echoed on the preview area of the debugger screen: DBG> Set Mode Screen; Set Step Nosource DBG> To display the beginning of executable code, press the keypad 2 key to scroll down the source. This results in the following display: 16–12 Debugging VAX SCAN Programs --SRC: module CHANGE_TIMES---scroll-source---------------------------------> 37: PROCEDURE main_routine MAIN ( ); 38: !+ 39: !!Start the picture matching process. The output stream is 40: !defined via the logical name SCN$OUTPUT. 41: !42: 43: START SCAN 44: INPUT FILE ’with_time.dat’ 45: OUTPUT FILE ’SYS$OUTPUT’; 46: END PROCEDURE; 48: END MODULE; --OUT---output------------------------------------------------------------- Before you scrolled, you observed that the pointer ( -> ) at line 37, the beginning of the procedure main_routine, was located on the center line of the SRC window. Pressing the keypad 2 key allows you to see more of the source by scrolling the SRC window. Next, having examined the source, you then set a combination of breaks and traces to monitor the execution of your program: DBG> DBG> DBG> DBG> DBG> DBG> SET SET set set set BREAK %line 46 RETURN TRACE/EVENT=TOK RETURN TRACE/EVENT=INPUT RETURN TRACE/EVENT=OUTPUT RETURN TRACE/EVENT=TRIG RETURN Your next step is to execute the program by pressing the comma ( , ) keypad key, which issues the ’GO’ command. The debugger then notifies you as the input stream is read, tokens are matched, macros are fired off, and text is written to the output stream. The debugger advances the pointer to line 46 of the listing, indicating that the desired breakpoint has been reached. The following example shows a portion of the output from this debugging session. (The file used for the input stream for the VAX SCAN program contained only one line of text.) WITH_TIME.DAT;6 29-OCT-1986 13:52 Note that for this example, some of the output data has been deleted. The tilde ( ~ ) is printed for nonprinting characters such as S’SOS’ and S’EOL’. Debugging VAX SCAN Programs 16–13 trace on event INPUT Input line number: 1 Input text length: 39 Input:’WITH_TIME.DAT;6 29-OCT-1986 13:52~’ Note the information provided: the event that activated the trace; the text line number; the total character count of the line, which includes the S’EOL’; and the text which appeared in the input stream. trace on event TOKEN Token built: Universal Token Length:9 Line:1 Column:1 Token text: "WITH_TIME" The universal token is built, because the sequence WITH_TIME does not match any of the program tokens. This will occur several times during the execution of this program. Note the information provided about the token: the character count of the text matched, the line and column in which the text appeared, and the text itself. trace on event TOKEN Token built: DOT Triggerable Length:1 Line:1 Column:10 Token text: "." This trace indicates the program token DOT was built. The word Triggerable states that this token was built solely of text that can cause triggering. trace on event TOKEN Token built: Universal Token Length:4 Line:1 Column:15 Token text: "DAT;" trace on event TRIGGER_MACRO Trigger Macro CHANGE_TIMES\ REPLACE_TIME Activated An integer has been found—perhaps it is followed by a colon? trace on event TOKEN Token built: INTEGER Triggerable Length:1 Line:1 Column:15 Token text: "6" trace on event TOKEN Token built: Universal Token Length:6 Line:1 Column:22 Token text: " " trace on event TRIGGER_MACRO Trigger Macro CHANGE_TIMES\ REPLACE_TIME Failed No, the integer 6 was not followed by a colon; the trigger macro has failed. trace on Token Token trace on Token Token event TOKEN built: INTEGER Triggerable Length:1 Line:1 Column:15 text: "6" event TOKEN built: Universal Token Length:6 Line:1 Column:22 text: " " 16–14 Debugging VAX SCAN Programs The tokens are rebuilt. Now skip ahead to the time reference. trace on event TRIGGER_MACRO Trigger Macro CHANGE_TIMES\ REPLACE_TIME Activated Another integer encountered; is this a time reference? (Is one of the tokens that we defined present in the input stream?) trace on event TOKEN Token built: INTEGER Triggerable Length:2 Line:1 Column:34 Token text: "13" trace on event TOKEN Token built: COLON Triggerable Length:1 Line:1 Column:36 Token text: ":" trace on event TOKEN Token built: INTEGER Triggerable Length:2 Line:1 Column:37 Token text: "52" trace on event TOKEN Token built: Universal Token Length:1 Line:1 Column:40 Token text: "~" trace on event TRIGGER_MACRO Trigger Macro CHANGE_TIMES\ REPLACE_TIME Succeeded Answered text length: 5 Answered: ’hh:mm’ Yes, this is a time reference as defined by the trigger macro in the program; the replacement text answered by the macro body is displayed. VAX SCAN now builds tokens with the answered text. trace on event TOKEN Token built: Universal Token Length:2 Answered text Token text: "hh" trace on event TOKEN Token built: COLON Length:1 Answered text Token text: ":" trace on event TOKEN Token built: Universal Token Length:2 Answered text Token text: "mm" trace on event TOKEN Token built: Universal Token Length:1 Line:1 Column:40 Token text: "~" trace on event OUTPUT Output status: Normal Output text length: 38 Output:’WITH_TIME.DAT;6 29-OCT-1986 hh:mm’ The OUTPUT event indicates that a line has been written to the output stream. The Output Status indicates that there is nothing special about this particular line. (Other statuses could indicate that the line was too long to output in a single record, or the end of the output stream was reached.) The next event records the end of the input stream. Debugging VAX SCAN Programs 16–15 trace on event INPUT Input line number: 2 Input text length: 1 Input:’~’ trace on event TOKEN Token built: Universal Token Length:1 Line:2 Column:1 Token text: "~" trace on event OUTPUT Output status: End of output stream Output text length: 0 In this sequence you see the tokens integer, colon, and dot, and the universal token being built. You also see that some text gets built into the same token more than once. This normally occurs when the token fails to match a picture and VAX SCAN has to back up and try an alternate pattern. This happens with the token 6, for example. The debugger shows the trigger macro being fired off for the 6 and failing, then being fired off for 13 and succeeding. The input stream and output stream are shown, allowing you to visually compare the input text with a time reference with the answered text that has hh:mm substituted. 16–16 Debugging VAX SCAN Programs Appendix A VAX SCAN Control Characters Table A–1: VAX SCAN Control Characters Symbol Hexadecimal Value Meaning s’nul’ 00 Null s’soh’ 01 Start of heading s’stx’ 02 Start of text s’etx’ 03 End of text s’eot’ 04 End of transmission s’enq’ 05 Enquiry s’ack’ 06 Acknowledge s’bel’ 07 Bell s’bs’ 08 Backspace s’ht’ 09 Horizontal tab s’lf’ 0A Line feed s’vt’ 0B Vertical tab s’ff’ 0C Form feed s’cr’ 0D Carriage return s’so’ 0E Shift out s’si’ 0F Shift in s’dle’ 10 Data link escape VAX SCAN Control Characters A–1 Table A–1 (Cont.): VAX SCAN Control Characters Symbol Hexadecimal Value Meaning s’dc1’ 11 Device control 1 s’dc2’ 12 Device control 2 s’dc3’ 13 Device control 3 s’dc4’ 14 Device control 4 s’nak’ 15 Negative Acknowledge s’syn’ 16 Synchronous idle s’etb’ 17 End of transmission block s’can’ 18 Cancel previous data s’em’ 19 End of medium s’sub’ 1A Substitute character s’esc’ 1B Escape s’fs’ 1C File separator s’gs’ 1D Group separator s’rs’ 1E Record separator s’us’ 1F Unit separator s’del’ 7F Delete s’ind’ 84 Index s’nel’ 85 Next line s’ssa’ 86 Start of selected area s’esa’ 87 End of selected area s’hts’ 88 Horizontal tab set s’htj’ 89 Horizontal tab with justification s’vts’ 8A Vertical tab set s’pld’ 8B Partial line down s’plu’ 8C Partial line up s’ri’ 8D Reverse index s’ss2’ 8E Single shift 2 s’ss3’ 8F Single shift 3 A–2 VAX SCAN Control Characters Table A–1 (Cont.): VAX SCAN Control Characters Symbol Hexadecimal Value Meaning s’dcs’ 90 Device control string s’pu1’ 91 Private use 1 s’pu2’ 92 Private use 2 s’sts’ 93 Set transmit state s’cch’ 94 Cancel character s’mw’ 95 Message waiting s’spa’ 96 Start of protected area s’epa’ 97 End of protected area s’csi’ 9B Control sequence introducer s’st’ 9C String terminator s’osc’ 9D Operating system command s’pm’ 9E Privacy message s’apc’ 9F Application program command VAX SCAN Control Characters A–3 Appendix B Syntax Diagrams This appendix lists VAX SCAN syntax diagrams in the following order: 1. 2. 3. 4. Executable statements Types Declarations Directives B.1 Executable Statements This section includes the syntax diagrams for the 19 types of VAX SCAN executable statements. For more information on executable statements, see Chapter 12. Syntax Diagrams B–1 Executable-statement " label-name : 2 allocate-statement 66 answer-statement 66 assignment-statement 66 call-statement 66 case-statement 66 close-statement 66 fail-statement 66 for-statement # 66 free-statement . . . 6 goto-statement 66 if-statement 66 open-statement 66 prune-statement 66 read-statement 66 return-statement 66 start-scan-statement 66 stop-scan-statement 4 while-statement write-statement 3 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 75 B.1.1 ALLOCATE-statement ALLOCATE pointer-variable , . . . ; B.1.2 ANSWER-statement " ANSWER TRIGGER # string-expression , . . . ; B.1.3 Assignment-statement variable = expression ; Variable Is a named object that has a value. It can be a simple variable-name, or a component of a record, or a leaf of a tree. B–2 Syntax Diagrams Expression Describes a value using a set of operands and operators. This value has a data type such as INTEGER, STRING, BOOLEAN or POINTER. The operands of an expression are listed in the following table. Operand Description Variable Function-reference Literal Value of a variable Value of a function Value of a literal The operators of an expression are listed in the following table. Operator Description [] + – * / & = == <> < > <= >= OR XOR AND NOT Substring Addition / unary plus Subtraction / unary minus Multiplication Division Concatenation Equal to Exactly equal to Not equal to Less than Greater than Less than or equal to Greater than or equal to Union Exclusive OR Intersection Complement B.1.4 CALL-statement 2 3 66 77 6 7 CALL procedure-name 6 h i 77 ; 64 5 ( argument , . . . ) Syntax Diagrams B–3 Argument has the following syntax: ( expression ) variable * B.1.5 CASE-statement CASE integer-expression FROM ct-integer-expression TO ct-integer-expression ; case-alternative . . . END CASE ; Case-alternative has the following syntax: 8 case-value > < case-value .. [ > : INRANGE case-value 9 " # > = , . . . ] : executable-statement ... > ; OUTRANGE Case-value Is a ct-integer-expression in the range of the FROM and TO values of the case statement. B.1.6 CLOSE-statement CLOSE FILE ( file-variable ) ; B.1.7 FAIL-statement FAIL ; B–4 Syntax Diagrams B.1.8 FOR-statement FOR integer-variable = integer-expression TO " integer-expression " STEP integer-expression # ; # ... executable-statement END FOR; B.1.9 FREE-statement FREE pointer-variable , . . . ; B.1.10 GOTO-statement GOTO label-name ; B.1.11 IF-statement IF boolean-expression THEN " # ... executable-statement ELSE " executable-statement # ... END IF; or IF boolean-expression THEN Syntax Diagrams B–5 " # ... executable-statement END IF; B.1.12 OPEN-statement OPEN FILE ( file-variable ) AS string-expression FOR n INPUT OUTPUT o ; B.1.13 PRUNE-statement PRUNE tree-reference , . . . ; Tree-reference Is a reference to a node in a tree. This reference can be: treeptr-variable 2 66 tree-name 6 h 4( 3 7 i 77 5 expression , ... ) B.1.14 READ-statement " READ # " FILE ( file-variable ) variable ; B.1.15 RETURN-statement " RETURN B–6 Syntax Diagrams expression # ; # PROMPT ( string-expression ) B.1.16 START-SCAN-statement 2 INPUT FILE string-expression 66 INPUT PROCEDURE procedure-name 66 INPUT STRING string-expression 66 INPUT WIDTH integer-expression START SCAN 6 OUTPUT FILE string-expression 66 OUTPUT PROCEDURE procedure-name 66 OUTPUT STRING string-variable 4 OUTPUT WIDTH integer-expression 3 77 77 77 77 77 75 ... ; DATA STACK integer-expression B.1.17 STOP-SCAN-statement STOP SCAN ; B.1.18 WHILE-statement WHILE boolean-expression ; " # executable-statement . . . ... END WHILE ; B.1.19 WRITE-statement " WRITE FILE ( file-variable ) # " # expression , ... ; Syntax Diagrams B–7 B.2 Types This section includes the syntax diagrams for VAX SCAN types. For more information and particular type, consult the index or the online help. Type has the following syntax: 8 INTEGER > > > > BOOLEAN > " # > > > > > > STRING DYNAMIC > > > > > " # > > > > > > STRING ( ct-integer-expression ) FIXED > > > > < VARYING STRING ( ct-integer-expression ) > > FILL ( ct-integer-expression ) > > > > POINTER TO type > > > > TREEPTR ( subscript-type ) TO type > > > > tree-type > > > > record-type > > > > overlay-type > > > > : type-name FILE B.2.1 OVERLAY-type OVERLAY { component-name : type , } . . . END OVERLAY B.2.2 RECORD-type RECORD { component-name : type , } . . . END RECORD B–8 Syntax Diagrams 9 > > > > > > > > > > > > > > > > > > > > > > > > > > = > > > > > > > > > > > > > > > > > > > > > > > > > > ; B.2.3 TREE-type TREE ( subscript-type , . . . ) OF type Subscript-type has the following syntax: n STRING o INTEGER B.3 Declarations This section includes the syntax diagrams for VAX SCAN declarations. For more information on a particular declaration, consult the index or the online help. B.3.1 CONSTANT-declaration CONSTANT constant-name ( = ct-expression GLOBAL = ct-expression EXTERNAL type B.3.2 EXTERNAL-declaration EXTERNAL PROCEDURE procedure-name " ) ; " # ( external-parameter , . . . ) # OF type ; External-parameter has the following syntax: " VALUE REFERENCE DESCRIPTOR # type Syntax Diagrams B–9 B.3.3 FORWARD-declaration FORWARD PROCEDURE procedure-name " " # ( forward-parameter , . . . ) # OF type ; Forward-parameter has the following syntax: " VALUE # REFERENCE DESCRIPTOR type B.3.4 GROUP-declaration GROUP group-name ( group-expression ) ; Group-expression Describes a collection of tokens using a set of group-operands and group-operators. The group-operands are listed in the following table. Operand Description token-name group-name A single token A previously defined group The group-operators are listed in the following table. Operator Description NOT AND OR Complement of a group Intersection of two groups Union of two groups B–10 Syntax Diagrams B.3.5 MACRO-declaration There are two kinds of macros in VAX SCAN—TRIGGER macros and SYNTAX macros. The syntax for the TRIGGER macro is as follows: " MACRO macro-name TRIGGER 2 variable-declaration 66 type-declaration 66 constant-declaration 66 procedure-declaration 64 macro-declaration 3 77 77 77 75 " # external-declaration forward-declaration # {picture} ; EXPOSE ... ... executable-statement END MACRO ; The syntax for the SYNTAX macro is as follows: " MACRO macro-name SYNTAX 2 variable-declaration 66 type-declaration 66 constant-declaration 66 procedure-declaration 64 macro-declaration 3 77 77 77 75 " # external-declaration forward-declaration executable-statement # " EXPOSE { # picture }; ... ... END MACRO ; Syntax Diagrams B–11 Picture Describes the pattern of tokens to be searched for in the input stream. The picture-expression is composed using picture-operands and picture-operators. The picture-operands are listed in the following table. Operand Description Token-name Group-name Macro-name Built-in-token Pattern Pattern Pattern Pattern described described described described by by by by a token a member of group another macro special built-in token The picture-operators are listed in the following table. Operator Description ... [] {} | \ Repetition Optional Required Alternative list You can precede any picture-operand with one to three variables and a colon, as follows: text, line, column : picture-operand The text variable is assigned the text that matched the picture-operand. The line variable is assigned the line number in the input stream of text to be matched and the column variable is assigned the column position of the start of the text. B.3.6 MODULE-declaration MODULE module-name B–12 Syntax Diagrams " # IDENT character-literal ; 2 variable-declaration 66 type-declaration 66 constant-declaration 66 set-declaration 66 token-declaration 66 group-declaration 66 procedure-declaration 66 macro-declaration 66 external-declaration 66 forward-declaration 64 redefine-directive list-directive include-directive END MODULE ; 3 77 77 77 77 77 77 77 77 77 75 ... B.3.7 PROCEDURE-declaration " PROCEDURE procedure-name " MAIN # ( parameter , . . . ) # OF type ; 2 variable-declaration 66 type-declaration 66 constant-declaration 64 procedure-declaration external-declaration " #" forward-declaration executable-statement 3 77 77 75 ... # ... END PROCEDURE ; Parameter has the following syntax: " VALUE parameter-name : REFERENCE DESCRIPTOR # type Syntax Diagrams B–13 B.3.8 SET-declaration SET set-name ( set-expression ) ; Set-expression Describes a subset of the DEC Multinational Character Set using set-operands and set-operators. The set-operands are listed in the following table. Operand Description Ct-character-expression Ct-character-expression .. ct-character-expression Single character Range of characters The set-operators are listed in the following table. Operator Description NOT AND OR Complement of a set Intersection of two sets Union of two sets B.3.9 TOKEN-declaration TOKEN token-name " CASELESS IGNORE ALIAS character-literal # . . . { token-expression }; Token-expression Describes a pattern of characters using a set of token-operands and token-operators. The token-operands are listed in the following table. B–14 Syntax Diagrams Operand Description Ct-characterexpression Set-name Pattern described by string Pattern consisting of a character from set The token-operators are listed in the following table. Operator Description ... [] {} | : Repetition Optional Required Alternation Look-ahead B.3.10 TYPE-declaration TYPE type-name : type ; B.3.11 Variable-declaration DECLARE variable-name , . . . : 2 STATIC 66 AUTOMATIC 64 COMMON GLOBAL 3 77 75 type ; EXTERNAL B.4 Directives This section includes the syntax diagrams for VAX SCAN directives. For more information on directive statements, see Chapter 13. B.4.1 INCLUDE-directive INCLUDE FILE ct-character-expression ; Syntax Diagrams B–15 B.4.2 LIST-directive 8 ON > < OFF LIST > : PAGE TITLE ct-character-expression 9 > = ; > ; B.4.3 REDEFINE-directive ( S’SOS’ ) REDEFINE B–16 Syntax Diagrams S’EOL’ S’EOS’ = ct-character-expression ; Appendix C VAX SCAN Keywords VAX SCAN has both reserved and unreserved keywords, as shown in Tables C–1 and C–2. Table C–1: Reserved Keywords ALLOCATE AND ANSWER CALL CASE CLOSE COLLATE CONSTANT DECLARE ELSE END ERROR EXTERNAL FAIL FALSE FILE FOR FORWARD FREE FROM GOTO GROUP IF INCLUDE INRANGE LIST MACRO MODULE NIL NOT OPEN OR OUTRANGE PROCEDURE PROMPT PRUNE READ REDEFINE RETURN SCAN SET START STEP STOP THEN TO TOKEN TRIGGER TRUE TYPE WHILE WRITE ANY AS XOR Table C–2: Unreserved Keywords ABS ALIAS VAX SCAN Keywords C–1 Table C–2 (Cont.): Unreserved Keywords ASCII AUTOMATIC BOOLEAN CASELESS COLUMN COMMON DATA DEC_MULTI DESCRIPTOR DYNAMIC EBCDIC EXISTS EXPOSE FILL FIND FIRST FIXED GLOBAL IDENT IGNORE INDEX INPUT INSTANCE INTEGER LAST LENGTH LOWER MAIN MAX MEMBER MIN MOD NATIVE NEXT NOTANY OF OFF ON OUTPUT OVERLAY PAGE POINTER PRIOR RECORD REFERENCE SEQUENCE SIZE SKIP STACK STATIC STRING SUBSCRIPT SYNTAX TIME TITLE TREE TREEPTR TRIM UPPER USER VALUE VARYING WIDTH C–2 VAX SCAN Keywords Appendix D VAX SCAN File Support VAX SCAN is designed to process sequential data files. The input and output functions in VAX SCAN expect to read in and to write out sequential files. Although VAX SCAN can operate on nonsequential files, the files are processed as though they were sequential. VAX SCAN does not check the characteristics of an input file to determine how to process it. Each record in an input file is processed sequentially. For more information on file attributes, see the (VMS_RMSROUT_R), the (VMS_ FDU_REF), and the (VMS_FILETUNING_H). Table D–1 and Table D–2 show the File Definition Language (FDL) descriptions for the attributes that VAX SCAN uses to process input and output files, respectively. Table D–1: FDL Description for VAX SCAN Input File Primary Attribute Secondary Attribute Associated Value FILE SEQUENTIAL_ONLY TRUE (YES) RECORD CARRIAGE_CONTROL CARRIAGE_RETURN ACCESS GET TRUE (YES) SHARING GET TRUE (YES) CONNECT LOCATE_MODE READ_AHEAD TRUE (YES) TRUE (YES) VAX SCAN File Support D–1 Table D–2: FDL Description for VAX SCAN Output File Primary Attribute Secondary Attribute Associated Value FILE SEQUENTIAL_ONLY ORGANIZATION TRUE (YES) SEQUENTIAL RECORD CARRIAGE_CONTROL FORMAT CARRIAGE_RETURN VARIABLE ACCESS PUT TRUE (YES) SHARING PROHIBIT TRUE (YES) CONNECT WRITE_BEHIND TRUE (YES) D–2 VAX SCAN File Support Appendix E DEC Multinational Character Set DEC Multinational Character Set control characters are shown as a reverse question mark on the VT200 series of terminals. They are shown as a rectangle on the VT100 series of terminals. Graphic Decimal Value Abbreviation Description ? 0 NUL null character ? 1 SOH start of heading ? 2 STX start of text ? 3 ETX end of text ? 4 EOT end of transmission ? 5 ENQ enquiry ? 6 ACK acknowledge ? 7 BEL bell ? 8 BS backspace H T L F V T F F C R ? 9 HT horizontal tabulation 10 LF line feed 11 VT vertical tabulation 12 FF form feed 13 CR carriage return 14 SO shift out ? 15 SI shift in DEC Multinational Character Set E–1 Graphic Decimal Value Abbreviation Description ? 16 DLE data link escape ? 17 DC1 device control 1 ? 18 DC2 device control 2 ? 19 DC3 device control 3 ? 20 DC4 device control 4 ? 21 NAK negative acknowledge ? 22 SYN synchronous idle ? 23 ETB end of transmission block ? 24 CAN cancel ? 25 EM end of medium ? 26 SUB substitute ? 27 ESC escape ? 28 FS file separator ? 29 GS group separator ? 30 RS record separator ? 31 US unit separator ? 32 SP space ! 33 ! exclamation point " 34 " quotation marks (double quote) # 35 # number sign $ 36 $ dollar sign % 37 % percent sign & 38 & ampersand ’ 39 ’ apostrophe (single quote) ( 40 ( opening parenthesis ) 41 ) closing parenthesis * 42 * asterisk + 43 + plus , 44 , comma E–2 DEC Multinational Character Set Graphic Decimal Value Abbreviation Description - 45 - hyphen or minus . 46 . period or decimal point / 47 / slash 0 48 0 zero 1 49 1 one 2 50 2 two 3 51 3 three 4 52 4 four 5 53 5 five 6 54 6 six 7 55 7 seven 8 56 8 eight 9 57 9 nine : 58 : colon ; 59 ; semicolon < 60 < less than = 61 = equals > 62 > greater than ? 63 ? question mark @ 64 @ commercial at A 65 A uppercase A B 66 B uppercase B C 67 C uppercase C D 68 D uppercase D E 69 E uppercase E F 70 F uppercase F G 71 G uppercase G H 72 H uppercase H I 73 I uppercase I DEC Multinational Character Set E–3 Graphic Decimal Value Abbreviation Description J 74 J uppercase J K 75 K uppercase K L 76 L uppercase L M 77 M uppercase M N 78 N uppercase N O 79 O uppercase O P 80 P uppercase P Q 81 Q uppercase Q R 82 R uppercase R S 83 S uppercase S T 84 T uppercase T U 85 U uppercase U V 86 V uppercase V W 87 W uppercase W X 88 X uppercase X Y 89 Y uppercase Y Z 90 Z uppercase Z [ 91 [ opening bracket \ 92 \ back slash ] 93 ] closing bracket ^ 94 ^ circumflex _ 95 _ underline (underscore) ‘ 96 ‘ grave accent a 97 a lowercase a b 98 b lowercase b c 99 c lowercase c d 100 d lowercase d e 101 e lowercase e f 102 f lowercase f E–4 DEC Multinational Character Set Graphic Decimal Value Abbreviation Description g 103 g lowercase g h 104 h lowercase h i 105 i lowercase i j 106 j lowercase j k 107 k lowercase k l 108 l lowercase l m 109 m lowercase m n 110 n lowercase n o 111 o lowercase o p 112 p lowercase p q 113 q lowercase q r 114 r lowercase r s 115 s lowercase s t 116 t lowercase t u 117 u lowercase u v 118 v lowercase v w 119 w lowercase w x 120 x lowercase x y 121 y lowercase y z 122 z lowercase z { 123 { opening brace | 124 | vertical line } 125 } closing brace ~ 126 ~ tilde DEL 127 DEL delete, rubout ? 128 — [reserved] ? 129 — [reserved] ? 130 — [reserved] ? 131 — [reserved] DEC Multinational Character Set E–5 Graphic Decimal Value Abbreviation Description ? 132 IND index ? 133 NEL next line ? 134 SSA start of selected area ? 135 ESA end of selected area ? 136 HTS horizontal tab set ? 137 HTJ horizontal tab set with justification ? 138 VTS vertical tab set ? 139 PLD partial line down ? 140 PLU partial line up ? 141 RI reverse index ? 142 SS2 single shift 2 ? 143 SS3 single shift 3 ? 144 DCS device control string ? 145 PU1 private use 1 ? 146 PU2 private use 2 ? 147 STS set transmit state ? 148 CCH cancel character ? 149 MW message waiting ? 150 SPA start of protected area ? 151 EPA end of protected area ? 152 — [reserved] ? 153 — [reserved] ? 154 — [reserved] ? 155 CSI control sequence introducer ? 156 ST string terminator ? 157 OSC operating system command ? 158 PM privacy message ? 159 APC application program command E–6 DEC Multinational Character Set Graphic Decimal Value Abbreviation Description ? 160 — [reserved] ¡ 161 ¡ inverted exclamation mark ¢ 162 ¢ cent sign £ 163 £ pound sign ? 164 — [reserved] ¥ 165 ¥ yen sign ? 166 — [reserved] § 167 § section sign ¤ 168 ¤ general currency sign © 169 © copyright sign ª 170 ª feminine ordinal indicator « 171 « angle quotation mark left ? 172 — [reserved] ? 173 — [reserved] ? 174 — [reserved] ? 175 — [reserved] ° 176 ° degree sign ± 177 ± plus/minus sign ² 178 ² superscript 2 ³ 179 ³ superscript 3 ? 180 — [reserved] µ 181 µ micro sign ¶ 182 ¶ paragraph sign, pilcrow · 183 · middle dot ? 184 — [reserved] ¹ 185 ¹ superscript 1 º 186 º masculine ordinal indicator » 187 » angle quotation mark right ¼ 188 ¼ fraction one quarter DEC Multinational Character Set E–7 Graphic Decimal Value Abbreviation Description ½ 189 ½ fraction one half ? 190 — [reserved] ¿ 191 ¿ inverted question mark À 192 À uppercase A with grave accent Á 193 Á uppercase A with acute accent  194  uppercase A with circumflex à 195 à uppercase A with tilde Ä 196 Ä uppercase A with umlaut, (diaeresis) Å 197 Å uppercase A with ring Æ 198 Æ uppercase AE diphthong Ç 199 Ç uppercase C with cedilla È 200 È uppercase E with grave accent É 201 É uppercase E with acute accent Ê 202 Ê uppercase E with circumflex Ë 203 Ë uppercase E with umlaut, (diaeresis) Ì 204 Ì uppercase I with grave accent Í 205 Í uppercase I with acute accent Î 206 Î uppercase I with circumflex Ï 207 Ï uppercase I with umlaut, (diaeresis) ? 208 — [reserved] Ñ 209 Ñ uppercase N with tilde Ò 210 Ò uppercase O with grave accent Ó 211 Ó uppercase O with acute accent Ô 212 Ô uppercase O with circumflex Õ 213 Õ uppercase O with tilde Ö 214 Ö uppercase O with umlaut, (diaeresis) E–8 DEC Multinational Character Set Graphic Decimal Value Abbreviation Description Œ 215 Œ uppercase OE ligature Ø 216 Ø uppercase O with slash Ù 217 Ù uppercase U with grave accent Ú 218 Ú uppercase U with acute accent Û 219 Û uppercase U with circumflex Ü 220 Ü uppercase U with umlaut, (diaeresis) Ÿ 221 Ÿ uppercase Y with umlaut, (diaeresis) ? 222 — [reserved] ß 223 ß German lowercase sharp s à 224 à lowercase a with grave accent á 225 á lowercase a with acute accent â 226 â lowercase a with circumflex ã 227 ã lowercase a with tilde ä 228 ä lowercase a with umlaut, (diaeresis) å 229 å lowercase a with ring æ 230 æ lowercase ae diphthong ç 231 ç lowercase c with cedilla è 232 è lowercase e with grave accent é 233 é lowercase e with acute accent ê 234 ê lowercase e with circumflex ë 235 ë lowercase e with umlaut, (diaeresis) ì 236 ì lowercase i with grave accent í 237 í lowercase i with acute accent î 238 î lowercase i with circumflex ï 239 ï lowercase i with umlaut, (diaeresis) DEC Multinational Character Set E–9 Graphic Decimal Value Abbreviation Description ? 240 — [reserved] ñ 241 ñ lowercase n with tilde ò 242 ò lowercase o with grave accent ó 243 ó lowercase o with acute accent ô 244 ô lowercase o with circumflex õ 245 õ lowercase o with tilde ö 246 ö lowercase o with umlaut, (diaeresis) œ 247 œ lowercase oe ligature ø 248 ø lowercase o with slash ù 249 ù lowercase u with grave accent ú 250 ú lowercase u with acute accent û 251 û lowercase u with circumflex ü 252 ü lowercase u with umlaut, (diaeresis) ÿ 253 ÿ lowercase y with umlaut, (diaeresis) ? 254 — [reserved] ? 255 — [reserved] E–10 DEC Multinational Character Set Appendix F Optional Programming Productivity Tools This appendix introduces an optional programming productivity tool: the VAX Language-Sensitive Editor (VAXLSE). This tool is not included with the VAX SCAN software; it is a separate software product and must be purchased separately. VAXLSE can significantly increase the productivity of the VAX SCAN programmer; this appendix shows how. The VAX Language-Sensitive Editor (VAXLSE) is a multilanguage, advanced text editor designed specifically for software development. You can use VAXLSE to control your editing environment and (with VAXLSE’s knowledge of specific languages) to quickly and accurately develop programs. This appendix introduces the concepts of tokens1 and placeholders and their use in editing source files. It also provides information on the following: • • • • Invoking VAXLSE Using language-specific examples Using aliases Compiling source code This appendix concludes with editor keypad information and command descriptions. It also provides further language-specific information and examples. 1 The VAX Language-Sensitive Editor concept of tokens is different from that of VAX SCAN. Optional Programming Productivity Tools F–1 For more detailed information about VAXLSE, see the VAX LanguageSensitive Editor User’s Guide. F.1 Getting Started with the VAX Language-Sensitive Editor VAXLSE provides you with predefined language elements called tokens and placeholders that you can use to create or edit source code for each of the supported languages. These elements can be expanded into templates for language constructs. A complete program can be constructed by successive expansions of these templates and constructs. Tokens Tokens are reserved words or function names that are typed into the editing buffer and expanded to provide templates for corresponding language constructs. Some examples of VAXLSE’s tokens for VAX SCAN are PROCEDURE, MACRO, IF, DECLARE, and MEMBER. Placeholders Placeholders are inserted into the editing buffer as parts of templates, and represent locations in the source code for you to provide additional program text. In some cases, however, a placeholder can be expanded to provide a template for additional text. Examples of VAX SCAN placeholders are {-type-}, {-macro_name-}, and [-module_statement]. Note that for VAX SCAN, braces and hyphens ({- -}) enclose required placeholders, while brackets and hyphens ([- -]) enclose optional placeholders. F.2 Commands for Tokens and Placeholders There are three commands that manipulate tokens and placeholders. These commands and their default key bindings are as follows: Command EXPAND F–2 Optional Programming Productivity Tools Key Binding CTRL/E Command Key Binding GOTO PLACEHOLDER/FORWARD CTRL/N ERASE PLACEHOLDER/FORWARD CTRL/K EXPAND (CTRL/E) The EXPAND command (CTRL/E) enables you to develop your program by choosing options available to you through VAXLSE’s knowledge of languages. When you press CTRL/E while the cursor is on a placeholder name, one of the following three events occurs: • • • Text appears to aid you in supplying a value. This type of placeholder is called a terminal placeholder. The placeholder is automatically replaced with a template consisting of more language elements. This type of placeholder is called a nonterminal placeholder. A menu appears providing you with options that can be expanded into templates. To select an option, you use the up and down arrow keys, then press CTRL/E, the RETURN key, or the ENTER key. This type of placeholder is called a menu placeholder. In any of these three cases, you can type the desired text over the placeholder. If you press CTRL/E after typing a token name (or a nonambiguous part of a token name), the token name expands in the same manner as a placeholder. GOTO PLACEHOLDER (CTRL/N) The GOTO PLACEHOLDER commands provide you with an efficient method of moving from placeholder to placeholder. The GOTO PLACEHOLDER/FORWARD command (CTRL/N) places the cursor on the first character of the placeholder name. Here you can use the EXPAND command or start typing the text to replace the placeholder. As you begin typing, the placeholder is automatically erased. The GOTO PLACEHOLDER/REVERSE command (CTRL/P) allows you to move back to the first character of the previous placeholder. Optional Programming Productivity Tools F–3 ERASE PLACEHOLDER/FORWARD (CTRL/K) The ERASE PLACEHOLDER/FORWARD command (CTRL/K) allows you to remove optional placeholders that correspond to the language constructs you choose not to use in your program. You cannot remove a required placeholder. F.3 Creating and Editing Code The best way to learn VAXLSE is by experimenting at the terminal. You can get online help during an editing session for both the keypad functions and the commands. F.3.1 Editing a New File The following procedure helps you experiment with the VAX SCAN templates using a new file. (For tutorial examples, refer to Section F.4.) 1. Invoke VAXLSE using the following command line format: " LSEDIT # /qualifier . . . file-spec For example: $ LSEDIT PROG.SCN RETURN 2. The initial string {-scan_module-} appears on the screen. Press the EXPAND key (CTRL/E). The template shown in Figure F–1 appears on your screen. F–4 Optional Programming Productivity Tools Figure F–1: Initial Screen Display ZK-4301-85 3. Press the GOTO PLACEHOLDER/FORWARD key (CTRL/N) to move from one placeholder to the next, expanding and typing in text as you go. For help on a placeholder or token, press the HELP/LANGUAGE key sequence (PF1-PF2) while the cursor is positioned on the placeholder. 4. For any optional placeholders that you do not want, press the ERASE PLACEHOLDER/FORWARD key (CTRL/K). 5. Some expansions display menus. Use the arrow keys to move through the menu and select your choice by pressing CTRL/E, the ENTER key, or the RETURN key. Optional Programming Productivity Tools F–5 6. Enter command mode by pressing CTRL/Z for the LSE> prompt, or the PF1-Keypad 7 key sequence for the LSE Command> prompt. Enter the CONTINUE command to return to editing. Enter the EXIT or QUIT command to leave VAXLSE; however, if you make modifications to the file, you must enter the EXIT command to save the changes you have made. The following procedures provide you with more general information about VAXLSE: 1. To see a diagram of the keypad, press the Help key (PF2). 2. To obtain a listing of the keys and their descriptions, enter the SHOW KEY command. 3. To see a list of VAXLSE commands and their explanations, press CTRL/Z (or use the PF1-Keypad 7 key sequence) to obtain one of VAXLSE’s prompts; then type HELP COMMANDS and press the RETURN key. 4. To examine a list of all the predefined tokens, press CTRL/Z to get the LSE> prompt; then type SHOW TOKEN and press the RETURN key. F.3.2 Editing an Existing File When editing an existing file (in one of the supported languages), you can still make use of VAXLSE’s language knowledge by using tokens. Because tokens exist for many keywords, you simply type the keyword and press the EXPAND key. For example, typing IF followed by pressing CTRL/E causes a template for an IF construct to appear on your screen. F.3.3 Defining Aliases The DEFINE ALIAS command allows you to define an abbreviation for a long identifier name entered in your source code. To define an alias for an identifier on which the cursor is currently located, press the PF1CTRL/A key sequence (which invokes the DEFINE ALIAS/INDICATED command) and type the abbreviation at the prompt as follows: _Alias name: name RETURN F–6 Optional Programming Productivity Tools The complete (long) identifier name appears whenever the abbreviation is typed and expanded by pressing CTRL/E. F.3.4 Using the Compiler Interface When writing your program, you can use the COMPILE command and subsequent REVIEW commands to check your code for syntax and semantic errors without exiting the editing session. F.3.4.1 The COMPILE Command The COMPILE command compiles the current buffer and writes diagnostic information to a file. VAXLSE supports each compiler’s command qualifiers and also supports user command procedures. VAXLSE runs the specified compiler in a subprocess by issuing a DCL command. For example, with TEST.SCN as the current buffer, type the COMPILE command as follows: LSE> COMPILE RETURN This results in the following DCL command: $ SCAN TEST.SCN /DIAGNOSTICS The effect of the /DIAGNOSTICS qualifier is described in Section F.3.4.2. If you want to specify additional DCL qualifiers, such as /DEBUG, you must use the COMPILE command and type in a dollar sign ( $ ) before the qualifier, as shown in the following example: LSE> COMPILE $/DEBUG RETURN VAXLSE substitutes the command verb for the dollar sign and the resulting DCL command is issued as follows: $ SCAN/DEBUG TEST.SCN /DIAGNOSTICS If you specify COMPILE/REVIEW, VAXLSE enters REVIEW mode and reviews compilation errors on the screen when the compilation is completed. For more information on the COMPILE command, see the VAX Language-Sensitive Editor User’s Guide. Optional Programming Productivity Tools F–7 F.3.4.2 The REVIEW Command The REVIEW command performs the same function as the /REVIEW qualifier on the COMPILE command. The REVIEW command selects and displays a set of diagnostic messages that resulted from a compilation. The program must have been compiled with the /DIAGNOSTICS qualifier. For example, after invoking the compiler with the /DIAGNOSTICS qualifier, or after using the COMPILE command as described in the previous section, type the following: LSE> REVIEW RETURN The screen is split into two windows. The top window contains buffer $REVIEW, which displays errors and highlights the line where the error occurred. The bottom window contains the source buffer. You then type the following command: LSE> RETURN NEXT ERROR The NEXT ERROR command moves the cursor to the next error in buffer $REVIEW. To move the cursor to the source buffer and the region containing the error, type the following: RETURN LSE> GOTO SOURCE Use the arrow keys to move within the source buffer. To return to reviewing errors, type either the NEXT ERROR or PREVIOUS ERROR command. The default key bindings for these commands are shown in the following table. Command Key Binding GOTO SOURCE CTRL/G NEXT ERROR CTRL/F PREVIOUS ERROR CTRL/B To return to one window containing the source buffer when you are in buffer $REVIEW, type the following command: LSE> END REVIEW RETURN F–8 Optional Programming Productivity Tools F.3.4.3 REVIEW Mode Upon entering REVIEW mode, the buffer $REVIEW window contains the following: • • • The source line on which the error was detected Any supplied text An error message The detected source line is identified by a listing line number that indicates the line on which the error occurred. The detected source line is also highlighted to indicate which error message you are currently viewing. You can highlight the next or previous error, using the NEXT ERROR and PREVIOUS ERROR commands, respectively. The supplied text (for example, macro-expanded text) provides supplementary information about the detected source line, but is not always supplied with every detected source line. When you enter REVIEW mode, the cursor is positioned on the first detected source line. If you want to look at this error in your source code, enter the GOTO SOURCE command and the cursor moves to the location of the error. VAXLSE highlights the area where the error is located. You can also move the cursor to the supplied text and then use the GOTO SOURCE command to move to the related text. In addition to highlighting an area in the source buffer, for certain messages VAXLSE can modify the source code according to the correction indicated by the message. For example, the following error message and line number message appear on your screen in the $REVIEW buffer, as shown in the following example. Line 10: IF (a > = 10) %SCAN-W-MERGE, Merged ">" and "=" to form ">=" The area in the source buffer where this error occurred is highlighted. When you use the GOTO SOURCE command to locate your position within the source code, the correction appears on the line where the error occurred in the source buffer, as shown in the following example: IF (a >= 10) Optional Programming Productivity Tools F–9 VAXLSE prompts you with the following message at the bottom of the screen: Keep the indicated correction [Y or N]? If you want to keep the supplied correction, type Y and press the RETURN key. If you want to keep the original code unaltered, type N and press the RETURN key. There is no default. You must type either Y or N. To move from the source code buffer to buffer $REVIEW or from buffer $REVIEW to the source code buffer without examining errors or moving to another error, use the NEXT WINDOW command. Use the END REVIEW command to return to a one-window display of the source buffer. F.3.5 VAXLSE Command Line The format for VAXLSE command line is as follows: " LSEDIT # /qualifier . . . file-spec /Qualifier Specifies any command qualifier. File-spec Specifies the file to be edited. The specification must be a VAX/VMS file specification. If no file specification is entered, VAXLSE defaults to the file it most recently edited. VAXLSE reads the file into a buffer. The buffer name is the name and type of the file specification in the command line. The file type determines the default language. For example, the file type for SCAN is SCN; the file types for C are C and H; the file type for FORTRAN is FOR; and the file types for COBOL are COB, LIB, and CBL. If the specified file exists, it is opened. If the file does not exist, it is created when you exit VAXLSE using the EXIT command. F–10 Optional Programming Productivity Tools F.3.6 Editor Command Line Qualifiers Table F–1 lists editor command line qualifiers that provide additional information to VAXLSE on how to handle your files. For more information, see the VAX Language-Sensitive Editor User’s Guide. Table F–1: Editor Command Line Qualifiers Qualifier Default /[NO]COMMAND=file-spec /NOCOMMAND /[NO]DISPLAY /DISPLAY /[NO]ENVIRONMENT=file-spec-list /NOENVIRONMENT /[NO]INITIALIZATION=file-spec /NOINITIALIZATION /[NO]JOURNAL[=file-spec] /JOURNAL /LANGUAGE=language /[NO]OUTPUT[=file-spec] /OUTPUT /[NO]READ_ONLY /NOREAD_ONLY /[NO]RECOVER /NORECOVER /[NO]SECTION=file-spec /SECTION=LSE$SECTION /START_POSITION=(line,character) /START_POSITION=(1,1) /[NO]SYSTEM_ENVIRONMENT=file-spec /SYSTEM_ENVIRONMENT=LSE$SYSTEM_ ENVIRONMENT F.3.7 Keypad Functions Figure F–2 and Figure F–3 show VAXLSE keypad functions for VT100 and VT200 terminals. Table F–2 shows the default editor keypad functions. For information on redefining these keys to suit your keypad preference, see the DEFINE KEY command in the VAX LanguageSensitive Editor User’s Guide. Optional Programming Productivity Tools F–11 Figure F–2: VAX Language-Sensitive Editor Keypad Layout for VT100 Series Terminals ZK-1767-84 F–12 Optional Programming Productivity Tools Figure F–3: VAX Language-Sensitive Editor Keypad Layout for VT200 Series Terminals ZK-3011-84 Table F–2: Default Editor Keypad Functions Key Function PF1 Change Indentation/Reverse PF1 Change Indentation/Forward ! PF1 " PF1 # Previous Window Next Window Optional Programming Productivity Tools F–13 Table F–2 (Cont.): Default Editor Keypad Functions Key Function PF1 = Change Window_Mode Backspace or F12 or CTRL/H Delete or < x Start of Line Rubout Char Linefeed or F13 Rubout Word Tab Tab PF1 Tab Untab CTRL/A Change Text Entry Mode PF1 CTRL/A Define Alias/Indicated CTRL/B Previous Error CTRL/E Expand Item PF1 CTRL/E Unexpand Item CTRL/F Next Error CTRL/G Goto Source CTRL/K Erase Placeholder/Forward PF1 CTRL/K Unerase Placeholder CTRL/N Goto Placeholder/Forward CTRL/P Goto Placeholder/Reverse CTRL/R Refresh Screen CTRL/U Erase to Beginning of Line CTRL/W Refresh Screen CTRL/Z Editor Command Mode PF1 CTRL/Z VAXTPU Command Mode VAXLSE line mode commands are shown in Table F–3: Table F–3: Editor Line Mode Commands Command Purpose ATTACH Allows you to attach the terminal to another process F–14 Optional Programming Productivity Tools Table F–3 (Cont.): Editor Line Mode Commands Command Purpose CALL Allows you to call a specified VAXTPU procedure CANCEL MARK Deletes a specified mark CANCEL SELECTMARK Cancels the effect of a SET SELECTMARK command CHANGE CASE Alters the case (upper/lower) of each letter in the select range CHANGE DIRECTION Alters the direction (forward/reverse) of the current buffer CHANGE INDENTATION Adds or deletes leading blanks and tabs in the select range CHANGE TEXTENTRYMODEAlters the text entry mode (insert/overstrike) of the current buffer CHANGE WINDOWMODE Alters the number of displayed windows COMPILE Writes and compiles a buffer CONTINUE Ends command line prompts and returns to keypad mode CUT Moves the select range to the indicated buffer DEFINE ALIAS For use with the EXPAND command; determines a reference name for text or an identifier DEFINE COMMAND Specifies a name for a user or an editor command DEFINE KEY Specifies the key for an editor command DEFINE LANGUAGE Specifies language characteristics DEFINE PLACEHOLDER Specifies placeholder characteristics DEFINE TOKEN Specifies token characteristics DELETE ALIAS Cancels the effect of a DEFINE ALIAS command DELETE BUFFER Eliminates the specified buffer DELETE COMMAND Cancels the effect of a DEFINE COMMAND command DELETE KEY Cancels the effect of a DEFINE KEY command Optional Programming Productivity Tools F–15 Table F–3 (Cont.): Editor Line Mode Commands Command Purpose DELETE LANGUAGE Cancels the effect of a DEFINE LANGUAGE command DELETE PLACEHOLDER Cancels the effect of a DEFINE PLACEHOLDER command DELETE TOKEN Cancels the effect of a DEFINE TOKEN command DO Executes editor commands or VAXTPU program statements END DEFINE Terminates a DEFINE PLACEHOLDER or TOKEN command END REVIEW Terminates the current review session ENTER LINE Inserts a line break (carriage return) at the current cursor position ENTER SPACE Inserts a blank character and performs a fill on the current line ENTER SPECIAL Inserts a specified ASCII character at the current cursor position ENTER TAB Inserts indentation, if at beginning of line; otherwise, inserts a tab at the current cursor position ENTER TEXT Inserts a specified string at the current cursor position ERASE CHARACTER Deletes a character at the current cursor position ERASE LINE Deletes a line of text from the current cursor position ERASE PLACEHOLDER Deletes the text of a selected placeholder ERASE WORD Deletes a word at the current cursor position EXIT Terminates an editing session and returns to the calling program or DCL EXPAND Replaces the placeholder, token, or alias with the body F–16 Optional Programming Productivity Tools Table F–3 (Cont.): Editor Line Mode Commands Command Purpose EXTRACT Selects the definition of a named item and formats it as a command FILL Fills the lines in the select range GOTO BOTTOM Moves the cursor to the bottom of the current buffer GOTO BUFFER Moves the cursor to the last position held in the specified buffer GOTO CHARACTER Moves the cursor to the specified character GOTO FILE Moves the cursor to a buffer containing the specified file GOTO LINE Moves the cursor to the next line GOTO MARK Moves the cursor to the mark created by the preceding SET MARK command GOTO PAGE Moves the cursor to the next page GOTO PLACEHOLDER Moves the cursor to the next placeholder GOTO SCREEN Moves the cursor in the current direction by the number of lines in the current window GOTO SOURCE Uses the current cursor position in buffer $REVIEW to select the diagnostic in the source buffer GOTO TOP Moves the cursor to the top of the current buffer GOTO WORD Moves the cursor to the next word in the current buffer HELP Displays information about a specified editor topic NEXT ERROR Selects the next diagnostic from the current set in buffer $REVIEW NEXT WINDOW Selects the alternate window PASTE Copies the contents of a specified buffer into the current buffer PREVIOUS ERROR Selects the previous diagnostic from the current set in buffer $REVIEW Optional Programming Productivity Tools F–17 Table F–3 (Cont.): Editor Line Mode Commands Command Purpose PREVIOUS WINDOW Selects the alternate window QUIT Terminates an editing session without saving any modified buffers READ Opens a specified file for input and places its contents in a specified buffer REFRESH Rewrites the screen display REPEAT Executes a command a specified number of times REVIEW Displays a set of diagnostic messages resulting from a compilation SAVE ENVIRONMENT Writes all user-defined languages, placeholders, and tokens to a specified file SEARCH Positions the cursor at a specified string in the current buffer SET FORWARD Sets the current direction of the buffer forward SET INDENTATION Changes the current indentation level for the buffer SET INSERT Sets the text entry mode of the buffer to insert mode SET LANGUAGE Changes the language associated with the buffer SET LEFTMARGIN Specifies the left margin for FILL and ENTER SPACE SET MARK Specifies a name at the current cursor position for a GOTO MARK command SET MODE Changes the setting of the AUTOERASE, BELL, FILL, FORTRAN, and EXPANDCASE modes SET OUTPUTFILE Changes the output file associated with the buffer SET OVERSTRIKE Sets the text entry mode of the buffer to overstrike mode SET READONLY Specifies that following a COMPILE command or an exit from VAXLSE, the buffer not be written to a file F–18 Optional Programming Productivity Tools Table F–3 (Cont.): Editor Line Mode Commands Command Purpose SET REVERSE Sets the current direction of the buffer to reverse SET RIGHTMARGIN Specifies the right margin for FILL and ENTER SPACE commands SET SCREEN Changes the characteristics of the terminal display screen SET SELECTMARK Specifies a position as one end of a select range SET TABINCREMENT Specifies the number of columns between tab stops for the buffer SET WRITE Specifies that following a COMPILE command or an exit from VAXLSE, the buffer will be written to a file SHIFT Scrolls a window horizontally (left or right) SHOW ALIAS Displays the characteristics of the specified alias SHOW BUFFER Displays the characteristics of the specified buffer SHOW COMMAND Displays the characteristics of the specified command SHOW KEY Displays the characteristics of the specified key SHOW LANGUAGE Displays the characteristics of the specified language SHOW MARK Displays the setting of the specified mark SHOW MODE Displays the current mode settings SHOW PLACEHOLDER Displays the characteristics of the specified placeholder SHOW TOKEN Displays the characteristics of the specified token SHOW VERSION Displays the version of VAXLSE SPAWN Suspends the editing session and runs the DCL interpreter in a subprocess SUBSTITUTE Searches for a specified text string and replaces it with another specified string Optional Programming Productivity Tools F–19 Table F–3 (Cont.): Editor Line Mode Commands Command Purpose TAB Inserts indentation, if at the beginning of line; otherwise, spaces to the next tab stop UNERASE Restores text previously deleted by an ERASE command UNEXPAND Reverses the effect of the last EXPAND command UNTAB Removes spaces to the previous tab stop WRITE Outputs the content of a specified buffer or select range to a specified file F.4 Using the VAX Language-Sensitive Editor with VAX SCAN This part of the appendix describes the special features of VAX SCAN that are available through VAXLSE and provides examples of using VAXLSE to write VAX SCAN code. Section F.6 provides information on how to obtain a list of VAXLSE tokens and placeholders defined for VAX SCAN. F.5 Sample Editing Session The following sample session shows expansions of the more frequently used VAX SCAN tokens and placeholders. Some of the examples are expanded to show the formats and guidelines that VAXLSE provides. (Not all of the examples are fully expanded.) The examples show expansions of the following VAX SCAN features: • • • • • Module and token declarations Macros Main procedure Function Variable declarations F–20 Optional Programming Productivity Tools • Control structures and built-in functions Instructions and explanations precede each example. Remember the following: • • • • • A placeholder is expanded by pressing CTRL/E. The cursor is moved forward to the next placeholder by pressing CTRL/N. The cursor is moved backward to the previous placeholder by pressing CTRL/P. A placeholder is erased by pressing CTRL/K. The arrow keys are used to move the indicator through a menu, and an option is selected by pressing the RETURN key, the ENTER key, or any key bound to EXPAND. To reproduce the examples, invoke VAXLSE and the VAX SCAN interface by typing the following command at the DCL prompt: " LSEDIT # filename.SCN /qualifier . . . F.5.1 Module and Token Declarations When entering a newly created buffer for VAX SCAN, the initial string {-scan_module-}, appears at the top of the screen. Expansion of the initial string produces the display shown in Figure F–4. Optional Programming Productivity Tools F–21 Figure F–4: Expansion of Initial String ZK-4302-85 The cursor is positioned at the first placeholder. Your first step is to type firstprogram over the placeholder. The {-module_name-} is automatically erased. The next placeholder can be used to add an ident for the module. You are not interested in this, so erase placeholder [-IDENT ’{-module_ident-}’-] by pressing CTRL/K. F–22 Optional Programming Productivity Tools Figure F–5: First Placeholder ZK-4303-85 The cursor is now at placeholder [-module_level_comments-]. This comment block is optional and you choose to erase it. This positions the cursor at the placeholder [-module_statement-]... which, when expanded, displays a menu of the module level statements in VAX SCAN. Expand placeholder [-module_statement-]... to display a menu and select the item {-declarative_statement-}. This displays another menu of the declarative statements in VAX SCAN. Select the menu item TOKEN. Optional Programming Productivity Tools F–23 Figure F–6: TOKEN Selected ZK-4304-85 You now fill in the token declaration much like the module template. To define a token that matches one or more blanks or tabs, type blanks over placeholder {-token_name-} to supply a name for the token. Then erase placeholder [-token_attr-]... because you do not need token attributes. Now provide the pattern for the token by typing { ’ ’ | s’ht’ }... over placeholder {-token_expression-}. F–24 Optional Programming Productivity Tools Figure F–7: Pattern Provided for Token ZK-4305-85 F.5.2 Macros The cursor is still positioned on the token statement. Move to the next placeholder, [-module_statement-] by pressing CTRL/N. Your previous command to expand this placeholder resulted in a menu of choices. This time, however, you know which construct you want (a macro), so type the keyword that begins that statement and expand the keyword. This is often faster than using the menus. Type macro over placeholder [-module_statement-]... and expand it. Optional Programming Productivity Tools F–25 Figure F–8: MACRO Expanded ZK-4306-85 Fill in the macro statement the same way you filled in the token declaration. Start by erasing the optional placeholder [-macro_title-]. Typing compressblanks over the placeholder {-macro_name-} gives the macro a name. Expanding placeholder {-req_attribute-} displays a menu which indicates the macro must have either the attribute TRIGGER or SYNTAX. You want a trigger macro for this exercise, so choose TRIGGER. Erase placeholder [-EXPOSE-] because you do not need this optional attribute. F–26 Optional Programming Productivity Tools If you expand the placeholder [-picture-], you get no further templates, just the message a picture specification. The same is true if you expand the placeholders [-token_expression-], [-set_expression-], or [-expression-]. The best way to get more information on these constructs is to use HELP/LANGUAGE, which is obtained by typing PF1 PF2 while positioned on the placeholder. The HELP describes the operators and valid operands. Your picture is the token blanks. Just type blanks over placeholder [-picture-]. ZK-4307-85 Again, erase the placeholder [-macro_level_comments-], which you do not need in this example. You are now positioned to build the body of the macro. This macro replaces a series of blanks with a single blank. Type the keyword that starts the statement and expand it to get Optional Programming Productivity Tools F–27 a template for the ANSWER statement. Type answer over placeholder [-macro_body_statement-]... and expand it. ZK-4308-85 You do not need the TRIGGER option on the ANSWER statement, so erase placeholder [-TRIGGER-]. This positions the cursor at the placeholder {-replacement_text-}, over which you type the replacement text ’ ’. No additional replacement text is needed, so erase [-replacement_text-]. In fact, there are no further statements to add to the macro body, so erase [-macro_body_statement-].... F–28 Optional Programming Productivity Tools ZK-4309-85 F.5.3 Creating a MAIN Procedure You now need to create a MAIN procedure for the program. This is created following the same steps you used when you created a macro. Type procedure (the keyword that starts the statement) over placeholder [-module_statement-] and expand it. Optional Programming Productivity Tools F–29 ZK-4310-85 Start by erasing the placeholder [-procedure_title-]. Next, give the procedure a name by typing mainproc over placeholder {-procedure_ name-}. You want this procedure to be the main procedure, so expand placeholder [-MAIN-]. A MAIN procedure has no parameters, so erase placeholder [-parameters-]. The final placeholder [-OF {-type-}-] is used to specify the result of the procedure. The main procedure is a subroutine rather than a function, so erase this placeholder. Finally, erase the placeholder [-procedure_level_comment-]. F–30 Optional Programming Productivity Tools ZK-4311-85 You now need to create the body to the main procedure with a START SCAN statement that initiates picture matching. You get a template for the START SCAN statement by typing start over placeholder [-procedure_body_statement-]... and expanding it. Optional Programming Productivity Tools F–31 ZK-4312-85 Expanding placeholder [-scan_option-] displays a menu of the clauses that are permitted in a START SCAN statement. Select item INPUT FILE, which is used to specify the input stream as a file. Typing ’input$file’ over placeholder {-vms_file_spec-} specifies the file to use for the input stream. F–32 Optional Programming Productivity Tools ZK-4313-85 Expand placeholder [-scan_option-]... to specify the output stream. Select menu item OUTPUT FILE. Type ’output$file’ over placeholder {-vms_file_spec-} to specify the file to use for the output stream. Optional Programming Productivity Tools F–33 ZK-4314-85 You are finished with the program. Erase the remaining placeholders [-scan_option-]..., [-procedure_body_statement-]..., and [-module_ statement-]. F.5.4 Creating a Function In this section, you create a function that counts the number of vowels in a string. Rather than start at the very beginning with a new file, start at the following point: F–34 Optional Programming Productivity Tools ZK-4315-85 First, get a template for a procedure by typing procedure over placeholder [-module_statement-], then expand it. Optional Programming Productivity Tools F–35 ZK-4316-85 Start by erasing the placeholder [-procedure_title-]. Next, give the procedure a name by typing countvowels over placeholder {procedure_name-}. This is not the main procedure, so erase placeholder [-MAIN-]. The procedure needs one parameter, so expand the placeholder [-parameters-], and then the placeholder. [-parameter-]. F–36 Optional Programming Productivity Tools ZK-4317-85 Provide a name for the parameter by typing buffer over placeholder {-parameter_name-}. You can use the default parameter passing mechanism, so erase placeholder [-mechanism-]. You can get a menu of the VAX SCAN data types by expanding placeholder {-type-}. Choose DYNAMICSTRINGTYPE. Optional Programming Productivity Tools F–37 ZK-4318-85 The procedure needs no other parameters, so erase the placeholder [-parameter-].... Now you are positioned at the placeholder [-OF {-type-}-], which is used to describe the result of a function. The function needs to return an integer, so expand placeholder [-OF {-type}-]. Next, expand placeholder {-type-}. Select the item INTEGERTYPE from the data type menu. Finally, erase the placeholder [-procedure_ levelcomment-]. F–38 Optional Programming Productivity Tools ZK-4319-85 F.5.5 Variable Declarations You are now ready to create the procedure body, which will begin with the declaration of two integers, i and count. To get a template for a DECLARE statement, type declare over the placeholder [-procedure_ body_statement-]... and expand it. Optional Programming Productivity Tools F–39 ZK-4320-85 Now type i over placeholder {-name_list-}, type count over placeholder [-name_list-]..., and erase placeholder [-name_list-]. Also, you should erase the placeholder [-storage_attribute-] because the default, AUTOMATIC, is what you want. Next expand placeholder {-type-} and choose menu item INTEGERTYPE. F–40 Optional Programming Productivity Tools ZK-4321-85 F.5.6 Control Structures The body of the function needs to be a FOR loop that looks at the characters in the string passed as a parameter. To get a template for a FOR loop, type for over the placeholder [-procedure_body_ statement-]... and expand it. Optional Programming Productivity Tools F–41 ZK-4322-85 Next, fill in the FOR statement template. Type i over placeholder {index_variable-} and 1 over placeholder {-initial_value-}. For the final value, you want to use the LENGTH built-in function. You can get a template for the LENGTH built-in function by typing builtin over {-final_value-} and expanding it. The expansion produces a menu from which you choose BUILTINFUNCTIONS. This produces another menu from which you choose [-string_functions-]. Another menu is displayed and you choose LENGTHBIF. F–42 Optional Programming Productivity Tools ZK-4323-85 The limit of the FOR loop needs to be the length of the parameter buffer, so type buffer over placeholder {-string_expression-}. The default step value of 1 is correct, so erase placeholder [-STEP {-step_ value-}-]. Optional Programming Productivity Tools F–43 ZK-4324-85 You need an IF statement for the body of the FOR loop that will verify whether a character is a vowel. To get an IF template, type if over placeholder [-executable_statement-].... The best way to test whether a character is a vowel is to use the MEMBER built-in function. Rather than going through the series of menus to get a template for MEMBER (as you did for LENGTH), instead type member over placeholder {-boolean_expression-} and expand it. F–44 Optional Programming Productivity Tools ZK-4325-85 The first argument of MEMBER is the string that will be searched. Type buffer[ i ] for the placeholder {-search_expression-}. The second argument is a string of characters to search for, in this case the set of vowels. Type ’aeiouyAEIOUY’ for placeholder {-member_ expression-}. You are not quite finished. MEMBER returns an integer (0 if not a vowel), and IF tests a Boolean value. Thus, you need to change the test to produce a Boolean result. Move to the end of the line (keypad 2) and type <> 0. Optional Programming Productivity Tools F–45 ZK-4326-85 The THEN section of the IF needs to increment the variable count. Enter the statement needed to do this by typing count = count + 1 over the placeholder [-executable_statement-].... Erase placeholders [-executable_statement-]... and [-else_part-], as you have completed the IF statement. Also erase placeholder [executable_statement-]... because you need no further statements in the FOR loop. F–46 Optional Programming Productivity Tools ZK-4327-85 Next, you need a RETURN statement to return the number of vowels counted. To get a template for a RETURN statement, type return over the placeholder [-procedure_body_statement-]... and expand it. Type count over placeholder [-return_value-]. This completes the procedure. As a final step, erase the [-procedure_body_statement]... and [-module_statement-]... remaining placeholders. Optional Programming Productivity Tools F–47 ZK-4328-85 F.6 VAX Language-Sensitive Editor Tokens and Placeholders for VAX SCAN To see a list of all the defined VAX Language-Sensitive Editor tokens provided by VAX SCAN, enter the following command: LSE> SHOW TOKEN RETURN You can see a list of all the defined placeholders provided by VAX SCAN by using the following command: LSE> SHOW PLACEHOLDER RETURN F–48 Optional Programming Productivity Tools To print a copy of either of these lists, you must first enter the appropriate SHOW command. This places the list into the $SHOW buffer. Then, enter the following commands: LSE> GOTO BUFFER $SHOW RETURN LSE> WRITE filename RETURN You can use the DCL command PRINT followed by the file name to obtain a hard copy of the list. You may also specify a token name or placeholder name after the SHOW command to obtain information about a particular token or placeholder. Optional Programming Productivity Tools F–49 Index A B ABS • 11–26 Access mechanism • 14–18 Addition operator ( + ) • 10–2 ALIAS • 5–8 ALLOCATE • 12–38 syntax diagram • 12–38 Alternation • 5–5, 5–13 PICTURE operator • 5–13 TOKEN operator • 5–4, 5–5 Analyzers See Extractors AND • 10–3 Boolean operator • 10–9 GROUP operator • 5–10 SET operator • 5–2 ANSWER • 4–3 syntax diagram • 12–29 TRIGGER attribute • 12–30 ANY • 11–2 Application development • 2–1 Arguments optional • 14–5, 14–12 Arithmetic operators • 10–5 Assignment • 4–3, 12–3 record • 12–7 statement requirements • 12–3t substring • 12–5 syntax diagram • 12–3 AUTOMATIC variable • 8–3 BOOLEAN initial value • 7–2 literal • 3–6 variables • 7–2 Built-in functions • 11–6t data type conversion INTEGER • 11–23 POINTER • 11–25 STRING • 11–24 ENDFILE • 11–29 EXISTS • 11–10 FIRST • 11–11 INDEX • 11–18 LAST • 11–12 LENGTH • 11–19 LOWER • 11–20 mathematical ABS • 11–26 MAX • 11–27 MIN • 11–27 MOD • 11–28 MEMBER • 11–21 NEXT • 11–13 PRIOR • 11–13 referencing • 10–16 STRING • 11–17 to 11–23 SUBSCRIPT • 11–16 TIME • 11–30 TREE • 1–26 TREEPTR • 11–9 tree traversing • 11–7 to 11–17 TRIM • 11–22 Index–1 Built-in functions (cont’d.) UPPER • 11–20 VALUE • 11–15 VALUEPTR • 11–15 Built-in tokens • 11–1t ANY • 11–2 COLUMN • 11–2 FIND • 11–3 INSTANCE • 11–3 SEQUENCE • 11–5 SKIP • 11–5 Built-In tokens NOTANY • 11–4 C CALL • 4–3, 12–9 syntax diagram • 12–9 CASE–END CASE • 4–3, 12–11 syntax diagram • 12–11 CASELESS • 5–8 Character set • 3–2, 3–2t CLOSE • 4–3, 12–35 COLUMN • 11–2 Comments in source program • 3–12 Complement operator (NOT) • 10–2 GROUP • 5–10 SET • 5–2 Concatenation PICTURE operator • 5–13 STRING operator • 5–5 TOKEN operator • 5–4 Concatenation operator ( & ) • 10–2, 10–6 Condition values returned • 14–15 signaled • 14–15 CONSTANT • 4–2, 8–7 syntax diagram • 8–7 Control characters • 3–7t Conversion built-in functions INTEGER • 11–23 POINTER • 11–25 STRING • 11–24 D DATA STACK • 12–27 2–Index DATA STACK (cont’d.) buffer overflow • 12–27 Data types • 7–1t BOOLEAN • 7–2 conversion functions • 11–23 to 11–25 FILL • 7–4 INTEGER • 7–2 OVERLAY • 7–17 POINTER • 7–5 RECORD • 7–14 STRING • 7–3 TREE • 7–5 TREEPTR • 7–9 DEBUG • 16–1 to 16–16 break on event • 16–5 breakpoints • 16–4 command qualifiers • 16–2t DEPOSIT • 16–6 elements available for debugging • 16–3 examine FILL • 16–7 OVERLAY • 16–11 POINTER • 16–7 RECORD • 16–11 STRING • 16–7 TREE • 16–8 EXAMINE • 16–6 examples BREAK • 16–4, 16–13 BREAK/EVENT= • 16–5 DEPOSIT • 16–6 STRING • 16–7 EXAMINE • 16–6 FILL • 16–7 POINTER • 16–7 STRING • 16–7 TREE • 16–8 TRACE • 16–4 TRACE/EVENT= • 16–5 WATCH • 16–6 sample debugging session • 16–11 trace on event • 16–5 tracepoints • 16–4 watchpoints • 16–6 Declarative statements syntax diagram • 4–2 DECLARE • 8–3 syntax diagram • 8–3 DECLARE (cont’d.) type specification • 8–4 DEC Multinational Character Set • 3–6, 3–7, 5–1, E–1 to E–10 Delimiters • 3–10 Depth of tree • 7–7 Directive statements • 13–1t INCLUDE • 13–3 LIST • 13–1 REDEFINE • 13–3 syntax diagram • 4–4 Division operator ( / ) • 10–2 E ENDFILE • 11–29, 12–37 Equal to operator ( = ) • 10–2 Error recovery • 5–27 Errors division by zero • 10–5 forbidden action • 15–1 overflow • 10–5 OVFTOKTEX • 12–27 SCN$PASENDSTM • 6–7 syntactic • 15–1 Exact equals operator ( = = ) • 10–7 Exact equal to operator ( = = ) • 10–2 Exclusive OR operator (XOR) • 10–2 Executable statements • 12–1t ALLOCATE • 12–38 ANSWER • 12–29 assignment • 12–3 record • 12–7 substring • 12–5 CALL • 12–9 CASE–END CASE • 12–11 CLOSE • 12–35 CONSTANT • 8–7 FAIL • 12–33 FOR–END FOR • 12–16 FREE • 12–40 GOTO • 12–10 IF–END IF • 12–13 labels • 12–2 OPEN • 12–33 PRUNE • 12–41 READ • 12–35 Executable statements (cont’d.) RETURN • 12–17 START SCAN • 12–18 STOP SCAN • 12–28 syntax diagram • 4–3 TYPE • 8–1 WHILE–END WHILE • 12–15 WRITE • 12–37 EXISTS • 11–10 EXPOSE • 5–18 Expression operators • 10–2 to 10–3 precedence of • 10–19t Expressions • 10–1, 10–19 EXTERNAL constant • 8–7 EXTERNAL PROCEDURE • 9–7 syntax diagram • 9–8 EXTERNAL variable • 8–4 Extraction substring • 10–4 Extractors • 1–28 F FAIL • 4–3, 12–33 syntax diagram • 12–33 File attribute • D–1 to D–2 Files as input or output stream • 6–2 as input stream • 12–20 as output stream • 12–23 closing • 12–35 opening • 12–33 reading • 12–35 writing • 12–37 FILE VARIABLE • 7–20 FILL variables • 7–4 initial value • 7–4 Filters • 1–27 FIND • 11–3 FIRST • 11–11 Flow of control • 1–14 FOR–END FOR • 4–3, 12–16 syntax diagram • 12–16 FORWARD PROCEDURE • 9–9 syntax diagram • 9–9 FREE • 12–40 syntax diagram • 12–40 Index–3 Function calls for system routines • 14–12 Functions • 9–2 built-in • 10–16 referencing • 10–15, 10–16 Functions>See also Built-in functions G GLOBAL constant • 8–7 GLOBAL procedure • 9–4 GLOBAL variable • 8–4 GOTO • 4–3, 12–10 syntax diagram • 12–10 Greater or equal operator ( >= ) • 10–2 Greater than operator ( > ) • 10–2 GROUP • 4–2, 5–10 expression • 5–10 operators complement (NOT) • 5–10 intersection (AND) • 5–10 precedence of • 5–11 union (OR) • 5–10 syntax diagram • 5–10 H HELP • 15–1 I IF–END IF • 4–3, 12–13 syntax diagram • 12–13 IGNORE • 5–8 INCLUDE • 4–4, 13–3 syntax diagram • 13–3 INDEX • 11–18 Initial value DYNAMIC STRING • 7–3 FILL • 7–4 FIXED STRING • 7–3 INTEGER • 7–2 POINTER • 7–5 RECORD • 7–16 TREEPTR • 7–9 VARYING STRING • 7–3 4–Index INPUT FILE • 12–20 INPUT PROCEDURE • 12–21 Input stream • 1–2 Input streams • 1–19, 12–19 files • 12–20 procedures • 12–21 special literals • 6–5 strings • 12–23 INPUT STRING • 12–23 INPUT WIDTH • 12–20, 12–22, 12–26 INSTANCE • 11–3 INTEGER conversion • 11–23 initial value • 7–2 literal • 3–5 variables • 7–2 Intersection operator (AND) • 10–2 BOOLEAN • 5–2 GROUP • 5–11 SET • 5–2 K Keywords • 3–3 reserved • 3–4t unreserved • 3–4t L Labels • 12–2 in executable statements • 12–10 LAST • 11–12 LENGTH • 11–19 Less than operator ( < ) • 10–2 Less than or equal to operator ( <= ) • 10–2 Level of tree • 7–7 LIST • 4–4, 13–1 options • 13–2 PICTURE operator • 5–13 syntax diagram • 13–1 Literals • 3–5 to 3–10 BOOLEAN • 3–6 control character • 3–7 hexadecimal character • 3–10 integer • 3–5 POINTER • 3–6 quoted string • 3–7 Literals (cont’d.) special character • 3–9t STRING • 3–6 TREEPTR • 3–6 LOCAL constant • 8–7 Logical operators • 10–9 to 10–10 Look-ahead TOKEN operator • 5–4 LOWER • 11–20 M MACRO–END MACRO • 5–12 to 5–32 attributes EXPOSE • 5–18 SYNTAX • 5–16 TRIGGER • 5–16 body • 5–32 example • 4–5, 4–8, 4–10, 5–12, 5–13, 5–14, 5–15, 5–19, 5–20, 5–21, 5–24, 12–18, 12–29, 12–30, 12–33 interaction activation • 5–23 completion • 5–23 failure to match • 5–26 invocation • 5–23 macro set • 4–5 name • 3–3 picture • 5–13 alternation • 5–13 concatenation • 5–14 list • 5–15 operator, precedence of • 5–16 optional brackets • 5–16 repetition • 5–15 picture variables • 5–20 text matched • 5–20 text position • 5–20 structure • 4–4 syntax diagram • 4–4, 5–12 Mathematical built-in functions • 11–26 to 11–29 MAX • 11–27 MEMBER • 11–21 MIN • 11–27 MOD • 11–28 Modular Programming Standard • 14–24 MODULE–END MODULE • 4–1 MODULE–END MODULE (cont’d.) example • 4–8, 4–10, 7–5, 8–4, 12–9 IDENT • 4–8 structure • 4–7 syntax diagram • 4–7 Multinational character set • E–1 to E–10 Multinational Character Set (DEC) • 3–6, 3–7, 5–1 Multiplication operator ( * ) • 10–2 N Names • 3–3 NEXT • 11–13 Node in tree • 7–7 NOT • 10–3 Boolean operator • 10–9 GROUP operator • 5–10 SET operator • 5–2 NOTANY • 11–4 Not equal to operator ( <> ) • 10–2 Null argument • 12–9 O OFF • 13–2 ON • 13–2 OPEN • 4–3, 12–33 syntax diagram • 12–34 Operators • 3–10, 10–2 addition • 10–5 arithmetic • 10–5 Boolean • 10–9 to 10–10 concatenation • 10–6 division • 10–5 expression • 10–2 GROUP • 5–10 logical • 10–9 multiplication • 10–5 PICTURE • 5–13 to 5–16 precedence of • 10–19t relational • 10–7 rules • 10–8t SET • 5–2 substring • 10–4 subtraction • 10–5 TOKEN • 5–4 union (OR) • 10–2 Index–5 Operators>See also specific operators Operators>unary minus ( – ) • 10–2 Operators>unary plus ( + ) • 10–2 OR • 10–3 Boolean operator • 10–9 GROUP operator • 5–10 SET operator • 5–2 OUTPUT FILE • 12–23 OUTPUT PROCEDURE • 12–24 Output stream • 1–2 Output streams • 1–19, 12–19 DATA STACK • 12–27 files • 12–23 OUTPUT WIDTH • 12–26 PROCEDURE • 12–24 special literals • 6–6 strings • 12–25 OUTPUT STRING • 12–25 OUTPUT WIDTH • 12–23, 12–24, 12–26 OVERLAY variable component • 7–17 component size • 7–17 OVFTOKTEX • 12–27 P PAGE • 13–2 Parameters • 9–4 Parameters>See also PROCEDURE–END PROCEDURE Passing mechanism • 9–6 Passing mechanisms • 14–13 Pattern creation • 1–5 Picture matching • 1–18 Picture variables • 5–20 POINTER • 11–25 initial value • 7–5 literals • 3–6 references • 10–17 variables • 7–5 Preprocessors • 1–29 Primitives of language • 3–1 PRIOR • 11–13 Procedure Calling and Condition Handling Standard • 14–24 Procedure calls • 14–15 PROCEDURE–END PROCEDURE • 4–2, 9–1 6–Index PROCEDURE–END PROCEDURE (cont’d.) example • 4–6, 4–8, 4–10, 7–5, 8–4, 8–6, 9–2, 9–4, 10–15, 10–18, 12–9, 12–18, 12–22, 12–25 EXTERNAL • 9–7 FORWARD • 9–9 name • 3–3 parameters • 9–1, 9–4 DESCRIPTOR attribute • 9–6 passing mechanisms • 9–6 REFERENCE attribute • 9–6 VALUE attribute • 9–6 structure • 4–6 syntax diagram • 4–6, 9–2 Program creation • 2–1 Program debugging • 16–1 to 16–16 Program form • 3–1 Program structure • 1–11, 4–1 MACRO–END MACRO • 4–4 macro set • 4–5 MODULE–END MODULE • 4–2 PROCEDURE–END PROCEDURE • 4–2 statements declarative statements • 4–2 directive statements • 4–4 executable statements • 4–3 macros • 4–4 MODULE–END MODULE • 4–7 PROCEDURE–END PROCEDURE • 4–6 PROMPT on READ statement • 12–35 PRUNE • 4–3, 12–41 example • 12–42 Q Quoted string literal • 3–7 R Range SET operator • 5–2 Range operator in substring • 12–5 READ • 4–3, 12–35 syntax diagram • 12–35 Record reference • 10–12 RECORD variable component • 7–14 component size • 7–14 initial value • 7–16 Recovery See Error recovery REDEFINE • 4–4, 13–3 syntax diagram • 13–4 REFERENCE built-in function • 10–16 function • 10–15 pointer • 10–17 record • 10–12 scalar • 10–12 TREE • 10–13 variable specification • 10–11 to 10–19 Relational operators • 10–7 rules • 10–8t Repetition PICTURE operator • 5–13 TOKEN operator • 5–4 Replacement text • 1–8 construction • 1–10 reporting • 1–11 Reserved keywords • 3–4t RETURN • 4–3, 12–17 syntax diagram • 12–17 Run-Time Library (RTL) • 14–1 routines • 14–2 example of calling • 14–19, 14–21 facilities • 14–2 how to call • 14–3 S S’EOL’ • 12–21 to 12–25, 13–3 in input stream • 6–5 in output stream • 6–6 redefining • 6–9 S’EOS’ • 12–21 to 12–25, 13–3 in input stream • 6–5 in output stream • 6–6 redefining • 6–9 S’SOS’ • 12–21 to 12–25, 13–3 in input stream • 6–5 in output stream • 6–6 redefining • 6–9 Scalar reference • 10–12 Scalar variable • 7–1 Scope • 4–9 to 4–11 example • 4–10 of trigger macro • 5–24 of variables • 1–20 rules • 4–9 SEQUENCE • 11–5 SET • 4–2, 5–1 examples • 5–2 name • 3–3 operators • 5–2 precedence of • 5–2 syntax diagram • 5–1 SKIP • 11–5 Spaces in source program • 3–12 Special characters • 3–9t Special literals in input stream • 6–5 in output stream • 6–6 redefining • 6–9 START SCAN • 4–3, 12–18 options • 12–19t DATA STACK • 12–27 INPUT FILE • 12–20 INPUT PROCEDURE • 12–21 INPUT STRING • 12–23 INPUT WIDTH • 12–26 OUTPUT FILE • 12–23 OUTPUT PROCEDURE • 12–24 OUTPUT STRING • 12–25 OUTPUT WIDTH • 12–26 syntax diagram • 12–19 Statements ALLOCATE • 12–38 ANSWER • 12–29 assignment • 12–3 CALL • 12–9 CASE–END CASE • 12–11 CLOSE • 12–35 CONSTANT • 8–7 FAIL • 12–33 FOR–END FOR • 12–16 FREE • 12–40 GOTO • 12–10 GROUP • 5–10 IF–END IF • 12–13 Index–7 Statements (cont’d.) MACRO–END MACRO • 5–12 OPEN • 12–33 PRUNE • 12–41 READ • 12–35 RETURN • 12–17 SET • 5–1 START SCAN • 12–18 STOP SCAN • 12–28 TOKEN • 5–3 TYPE • 8–1 WHILE–END WHILE • 12–15 WRITE • 12–37 Statement structure • 4–2 to 4–4 directive • 4–4 executable statements • 4–3 STOP SCAN • 4–3, 12–28 syntax diagram • 12–28 Storage class • 8–3 Stream input and output • 6–1 file • 6–2 form • 1–19, 6–1 procedure • 6–3 string • 6–2 width • 6–9 Streams, input and output • 12–19 STRING • 11–17, 11–24 as input or output stream • 6–2 built-in functions INDEX • 11–18 LENGTH • 11–19 LOWER • 11–20 MEMBER • 11–21 TRIM • 11–22 UPPER • 11–20 initial value • 7–3 literal • 3–6 substring extraction • 10–4 variables • 7–3 String literal quoted • 3–7 Structured variables • 7–1 SUBSCRIPT • 11–16 in tree variables • 7–7 Substring operator ( [ ] ) • 10–2, 10–4, 12–3 Subtraction operator ( – ) • 10–2 Syntax diagrams 8–Index Syntax diagrams (cont’d.) ALLOCATE • 12–38 ANSWER • 12–29 assignment • 12–3 CALL • 12–9 CASE–END CASE • 12–11 CONSTANT • 8–7 declarative statements • 4–2 DECLARE • 8–3 directive statements • 4–4 executable statements • 4–3 EXTERNAL PROCEDURE • 9–8 FAIL • 12–33 FOR–END FOR • 12–16 FORWARD PROCEDURE • 9–9 FREE • 12–40 GOTO • 12–10 GROUP • 5–10 IF–END IF • 12–13 INCLUDE • 13–3 LIST • 13–1 MACRO–END MACRO • 4–4, 5–12 MODULE–END MODULE • 4–7 OPEN • 12–34 PROCEDURE–END PROCEDURE • 4–6, 9–2 READ • 12–35 REDEFINE • 13–4 RETURN • 12–17 SET • 5–1 START SCAN • 12–19 STOP SCAN • 12–28 TOKEN • 5–4 TYPE • 8–1, 8–4 WHILE–END WHILE • 12–15 WRITE • 12–37 SYNTAX MACRO • 5–13, 5–14, 5–17 activation • 5–23 failure to match • 5–26 forward referencing • 4–11 System routines • 14–1 examples of calling • 14–18 function calls • 14–12 function results • 14–17 how to call • 14–3 passing mechanisms • 14–13 procedure results • 14–18 subroutine calls • 14–15 System services • 14–2 System services (cont’d.) groups • 14–2 how to call • 14–3 T Tabs in source program • 3–12 TIME • 11–30 TITLE • 13–2 TOKEN • 4–2, 5–3 attributes ALIAS • 5–8 CASELESS • 5–8 IGNORE • 5–8 built-in • 11–1t, 11–1 to 11–6 ANY • 11–2 COLUMN • 11–2 FIND • 11–3 INSTANCE • 11–3 NOTANY • 11–4 SEQUENCE • 11–5 SKIP • 11–5 expression • 5–4 interaction • 5–9 name • 3–3 operators • 5–4, 5–5 alternation • 5–5 concatenation • 5–5 look-ahead • 5–6 precedence of • 5–7 repetition • 5–5 overlap • 5–9 unbuildable • 5–10 universal • 1–17, 5–9 Token building • 1–17 Translators • 1–27 TREE • 7–5 to 7–14 built-in functions • 1–26 declaration • 1–25 depth • 1–24 nodes • 1–24 referencing • 10–13 treeptr variable • 11–9 subscripts • 1–26 variable referencing • 7–5 variables • 7–7 Tree concepts • 1–23 TREEPTR • 11–9 initial value • 7–9 literals • 3–6 variables • 7–9 TREE VARIABLE • 1–23 TRIGGER MACRO • 5–16 activation • 5–23 failure to match • 5–27 TRIM • 11–22 TYPE • 4–2 syntax diagram • 8–4 U Unary minus operator ( – ) • 10–2 Unary plus operator ( + ) • 10–2 Unbuildable tokens • 5–10 Union operator (OR) • 10–2 GROUP • 5–10 SET • 5–2 Universal group • 5–11 Universal token • 1–17, 5–9 UPPER • 11–20 Uses for VAX SCAN • 1–27 V VALUE • 11–15 VALUEPR • 11–15 VARIABLE • 1–20, 4–2 COMMON • 8–3 EXTERNAL • 8–4 file • 7–20 GLOBAL • 8–4 initial values • 12–39 name • 3–3 picture • 5–20 scalar BOOLEAN • 7–2 FILL • 7–4 INTEGER • 7–2 POINTER • 7–5 STRING • 7–3 TREEPTR • 7–9 scope • 1–20 specification of type • 8–1 STATIC • 8–3 Index–9 VARIABLE (cont’d.) storage class AUTOMATIC • 8–3 COMMON • 8–3 EXTERNAL • 8–3 GLOBAL • 8–3 STATIC • 8–3 structured OVERLAY • 7–17 RECORD • 7–14 TREE • 1–23, 7–5 VAX/VMS Common Language Environment • 1–1 VAX/VMS Modular Programming Standard • 14–24 VAX Language-Sensitive Editor Aliases • F–6 Commands COMPILE • F–7 /REVIEW • F–7 ERASE PLACEHOLDER • F–4 EXPAND • F–3 GOTO PLACEHOLDER • F–3 REVIEW • F–8 Compiler interface • F–7 Control structures • F–41 Creating a function • F–34 Creating a MAIN procedure • F–28 Editing a new file • F–4 Editing an existing file • F–6 editor command line • F–10 Editor command line qualifiers • F–11 Getting started • F–2 Keypad functions • F–11 Macros • F–25 Module and token declarations • F–21 Placeholders • F–2 Placeholders for VAX SCAN • F–48 Sample editing session • F–20 Tokens • F–2 Tokens for VAX SCAN • F–48 Using with VAX SCAN • F–20 Variable declarations • F–39 VAX Procedure Calling and Condition Handling Standard • 14–24 VAX SCAN character set • 3–2 file support • D–1 to D–2 10–Index VAX SCAN (cont’d.) on VAX/VMS • 2–3 program creation • 2–1 program debugging • 16–1 to 16–16 program editing • 2–1 programs flow of control • 1–14 structure • 1–11 special characters • 3–9t uses • 1–27 extractors • 1–28 filters • 1–27 preprocessors • 1–29 translators • 1–27 VMS Usages • 14–6 VAX SCAN equivalents • 14–6 W WHILE–END WHILE • 4–3, 12–15 syntax diagram • 12–15 WRITE • 4–3, 12–37 syntax diagram • 12–37 X XOR • 10–3 Boolean operator • 10–9 Z Zero division by (error) • 10–5 integer variable initial value • 7–2 record initial value • 7–16
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.4 Linearized : Yes XMP Toolkit : 3.1-701 Producer : Acrobat Distiller 7.0.5 (Windows) Create Date : 2009:03:13 01:43:43+01:00 Modify Date : 2009:03:13 01:43:43+01:00 Creator Tool : VAX DOCUMENT V1.1 Copyright (c) 1986,1987,1988 DIGITAL EQUIPMENT CORPORATION. All Rights Reserved. Format : application/pdf Title : untitled Document ID : uuid:2e0d32d7-6db8-4030-94ed-82e754a09167 Instance ID : uuid:71b525be-af16-4b06-9549-de48890c82f6 Page Count : 400 Creator : VAX DOCUMENT V1.1 Copyright (c) 1986,1987,1988 DIGITAL EQUIPMENT CORPORATION. All Rights Reserved.EXIF Metadata provided by EXIF.tools