1 Introduction
2 Ground Rules

Building a File System
3 File Systems
4 File Content Data Structure
5 Allocation Cluster Manager
6 Exceptions and Emancipation
7 Base Classes, Testing, and More
8 File Meta Data
9 Native File Class
10 Our File System
11 Allocation Table
12 File System Support Code
13 Initializing the File System
14 Contiguous Files
15 Rebuilding the File System
16 Native File System Support Methods
17 Lookups, Wildcards, and Unicode, Oh My
18 Finishing the File System Class

The Init Program
19 Hardware Abstraction and UOS Architecture
20 Init Command Mode
21 Using Our File System
22 Hardware and Device Lists
23 Fun with Stores: Partitions
24 Fun with Stores: RAID
25 Fun with Stores: RAM Disks
26 Init wrap-up

The Executive
27 Overview of The Executive
28 Starting the Kernel
29 The Kernel
30 Making a Store Bootable
31 The MMC
32 The HMC
33 Loading the components
34 Using the File Processor
35 Symbols and the SSC
36 The File Processor and Device Management
37 The File Processor and File System Management
38 Finishing Executive Startup

Users and Security
39 Introduction to Users and Security
40 More Fun With Stores: File Heaps
41 File Heaps, part 2
42 SysUAF
43 TUser

Terminal I/O
45 Shells and UCL
46 UOS API, the Application Side
47 UOS API, the Executive Side
48 I/O Devices
49 Streams
50 Terminal Output Filters
51 The TTerminal Class
52 Handles
53 Putting it All Together
54 Getting Terminal Input
55 QIO
56 Cooking Terminal Input
57 Putting it all together, part 2
58 Quotas and I/O

59 UCL Basics
60 Symbol Substitution
61 Command execution
62 Command execution, part 2
63 Command Abbreviation
64 ASTs
65 Expressions, Part 1
66 Expressions, Part 2: Support code
67 Expressions, part 3: Parsing
69 Expressions, part 4: Evaluation

UCL Lexical Functions
72 TProcess updates
73 Unicode revisted
74 Lexical functions: F$CONTEXT
75 Lexical functions: F$PID
76 Lexical Functions: F$CUNITS
77 Lexical Functions: F$CVSI and F$CVUI
78 UOS Date and Time Formatting
79 Lexical Functions: F$CVTIME
81 Date/Time Contexts
83 Lexical Functions: F$DELTA_TIME
84 Lexical functions: F$DEVICE
86 Lexical functions: F$DIRECTORY
87 Lexical functions: F$EDIT and F$ELEMENT
88 Lexical functions: F$ENVIRONMENT
90 Lexical functions: F$EXTRACT and F$IDENTIFIER
92 LIB_FAO and LIB_FAOL, part 2
93 Lexical functions: F$FAO
94 File Processing Structures
95 Lexical functions: F$FILE_ATTRIBUTES
97 Lexical functions: F$GETDVI
98 Parse_GetDVI
99 GetDVI
100 GetDVI, part 2
101 GetDVI, part 3
102 Lexical functions: F$GETJPI


Download sources
Download binaries

UCL Basics

This article is the first in a series where we will look at the execution of scripts in UCL. Unless otherwise noted, UOS UCL and VMS DCL are compatible from the user's perspective.

First, let's look at an updated Run routine:

procedure Run ;

var S : string ;

    while( True ) do
        S := Parse( Get_Command ) ;
        if( Edit( S, 8 or 128  ) <> '' ) then
            Process( S ) ;
        end ;
    end ;
end ;
This is a loop where we get a command, parse it, and then (assuming it isn't null) process the command.

Symbol Substitution
In a previous article, we discussed UOS symbols. UOS symbols serve as UCL variables. Most shell implementations incorporate variables within the shell. Although a UOS shell could do the same, UCL uses UOS symbols so that the symbols are available to any other (different) shells running under UOS. Because of the universal nature of UOS, many different shells may be available, thus using UOS symbols allows better interoperation between the shells. UCL allows for two types of symbols/variables: local and global. Local symbols are stored in the LNM_PROCESS table, while global symbols are stored in the LNM_JOB table. In this respect, UCL and DCL differ. DCL uses internal symbols rather than system-wide symbol tables (which VMS doesn't offer). Unless otherwise specified, if there are symbols in both the local and global tables with the same name, the local symbol is used.

The Parse procedure performs symbol substitution. This is a process that allows customization of commands, including program execution. Most shell scripts have some similar ability. Essentially, symbol substitution means that the actual values of symbols are substituted for the symbol names in the command line prior to the line being executed. The apostrophe (') is used to indicate a symbol substitution. For instance:

dir A

would return a directory listing of any files named "A". But
dir 'A'

would return a directory listing of any files with the name of the value of symbol A. For instance, if symbol A contained the value "XYZ", then the above command would look like this after substitution:
dir XYZ

A couple of things to note: first, the apostrophes must enclose the symbol. Second, the apostrophes are removed when the symbol value is substituted. Because the symbol name is delimited by apostrophes, we can embed the symbol name anywhere in the line. For instance:
dir X'A'1

would do a directory listing of any filename starting with "X", ending with "1" and with symbol A's value in-between. In the case of A containing "XYZ", after substitution the command would be:
dir XXYZ1

In the case of string literals (those delimited by double quotes), two apostrophes must be used to specify the start of a symbol name for substitution. Thus, single apostrophes can be freely used within literals without having to worry about inadvertant symbol substitution. Example:

A = "Hello, ''NAME'"

Note that the symbol is still terminated by only a single apostrophe.

Symbol substitution is iterative. That is, if the substituted value contains apostrophe-delimited symbol name, then that is also substituted. For example, assume we have two symbols with the following values:

A = "'B'"
B = "UOS"

Now, if UCL does a substitution of the following:
dir 'A'

The first iteration of substitution results in:
dir 'B'

The next iteration results in:
dir UOS

Note that iterative substitution does not occur inside string literals. Thus, a full iterative substitution of:
dir "''A'"

will result in a final result of:
dir "'B'"

Phase Two Symbol Substitution
The apostrophe-driven symbol substitution is only the first of two phases of symbol substitution. After symbols have been substituted as described above, UCL next checks for any symbol name preceeded by an ampersand (&). Unlike phase one substitution, the ampersand substitution cannot be used in the middle of other text. In other words, the ampersand must be preceeded by white space or a special character (not A-Z, 0-9, $, or _), and likewise for the character following the symbol name. In general, ampersand subsitution should be avoided - use it only when it is the only way to accomplish what you need to do. To understand how both phases of symbol substitution work together, consider the following - assume P is empty (equals "") and B is "5":

dir 'P''B'

the substitution would result in:
dir 5

This is because both P and B are substituted, as expected. But consider:
dir &P'B'

In this case, after phase 1 substitution, the command would look like this:
dir &P5

Then phase two of symbol substition occurs. In this case, symbol P5 is substituted. Assuming P5 contains "ABC", the new command will be:
dir ABC

which is quite different from
dir 5

Symbol values are also used in expressions, which we'll cover in a future article. In such a case, as we will see, the symbol's value is used without apostrophes or ampersands because of context. However symbol substitution may, in most cases, accomplish the same end result in expressions. But since it is unnecessary, it is best not to do so in command files, both for performance sake and clarity of script code.

Other UCL script elements
Generally, lines in UCL command files must begin with a dollar-sign ($) to indicate that the line is a UCL command and not data intended for a program to consume. This is not always absolutely required, but it is a good practice.

Labels are a means of control flow of execution through command files. A label is a token consisting of characters that are valid for a symbol name, followed by a colon (:). Any symbol name followed by a colon is treated as a label even if there is a symbol of the same name. Labels are ignored when encountered, but can be used as destinations for such commands as GOTO. Example label:

$ Retry:

Comments help to document scripts. They begin with an exclamation point (!) and extend to the end of the line. They can be on a line by themselves or after some other script code. An example comment from a command file:

$ ! This is a comment

Sometimes it is useful to continue a very long command onto multiple lines. When being typed at a terminal, a command is usually considered complete at the end of the line. To allow continuing a command onto the next input line from the terminal, a dash (-) can be included at the end of the line. The dash must be immediately preceeded by a space or tab. Although not required in command files, the line continuation may be used there as well. Note, however, that any line with a comment on it cannot be continued since the dash is considered to be part of the comment itself. Multiple lines can be continued. An example of line continuation:

dir \users\george\c\*.* -
/date/size -

The above lines would be interpreted as a single line that looked like this:
dir \users\george\c\*.*/date/size/page

Finally, let's consider the difference between running a command file and typing commands manually from a terminal (called "interactive mode"). In the latter case, some operations make no sense and will result in an error. For instance, a GOTO command is pointless in interactive mode, because there is no target label to which to move execution. Likewise, using a label in interactive mode makes no sense because once the line has been entered, it is done and gone. Any future (or prior) reference to that label can not go to it. We will discuss these situations as they come up.

UOS Errors and UCL Error Handling
It is possible that syntactically or contextually incorrect commands may be encountered in UCL - people are only human. Sometimes, situations beyond the script writer's control may cause errors to happen. Thus, UCL has error handling capabilities. We will address this in greater detail in a future article, but we will take a moment to describe errors in a general way.

UOS errors can be warnings, errors, or fatal errors. Error handling can deal with each of these separately, if desired. When an error is displayed to the user, it consists of a string following this format:
%xxx-y-zzzzzz, error text
where "xxx" is the source of the error (usually a three-letter code, such as "UCL"), "y" is the level of error (W=warning, E=error, F=fatal), and "zzzzzz" is an error abbreviation code (usually six characters) which is unique for each error from a given source. Sometimes there are additional lines of information provided by UCL which indicate the items in the command line that caused the error. Example of an error:

%UCL-W-NOLBLS, label ignored - use only within command procedures

Now that we've described the basic behavior of UCL we can look at the code to implement it. In the next article, we will implement symbol substitution, as described above.


Copyright © 2019 by Alan Conroy. This article may be copied in whole or in part as long as this copyright is included.