Table of Contents

Introduction

The principal claim to fame of the HAL/S computer language is that the bulk of the flight software for the Space Shuttle was written in it, as supplemented by source code in the assembly language of the Shuttle's General Purpose Computers (GPC).  GPCs were IBM AP-101S computers or (for early missions) IBM AP-101B computers.  HAL/S also seems to have been used for the flight software of the Galileo probe, though in that case the onboard computers were based on RCA 1802 COSMAC microprocessors.

Aside:  The other claim to fame is that HAL/S has an optional pseudo-mathematical notation in which arithmetical expressions look more like mathematics than they generally do in other programming languages.

HAL/S was devised by the company Intermetrics, Inc., and touted as one of the "standard" languages in which NASA flight software should be written.  In spite of the two successes I mentioned above, I haven't found much evidence that it ever became a NASA standard.  Indeed, a 1983 report that investigated the language candidates HAL/S versus ADA versus Modula 2 concluded that only ADA met all of the desired criteria.  Today, I'd regard HAL/S as a dead language, though I'd be happy to be instructed otherwise.

One factor greatly in its favor, both as a language for flight software and for general-purpose computing, is a very fine book about the language, namely Michael Ryer's Programming in HAL/S.  That may sound like an odd advantage to mention, but "very fine books about them" are something that computer languages with a minimal user base tend to lack.  Authors have more incentive to spend their time writing about widely-successful languages with large numbers of users.

Nevertheless, the Space Shuttle's flight software was written in HAL/S, so anybody interested in working with that flight software also needs appropriate tools for working with HAL/S.  The Space Shuttle's flight software came in two very-different flavors, namely the primary flight software (PASS) and the backup flight software (BFS), with the BFS being basically a clean-room implementation of a subset of PASS functionality.  By emphasizing PASS and BFS I don't mean to disparage Galileo's software.  However, I have seen no Galileo flight software, and as far as I know right now have no prospect for ever getting my hands on it.  If you have Galileo flight software source code, or even related documentation, by all means contact me.  I'll expand the scope of HAL/S quicker than you can bat an eyelash.

A 1981 article summarizes the HAL/S activity up to that point in time, describing a number of implementations of HAL/S compilers for various types of computers.  None of them are available for computers accessible to the general public, of course.  The IBM PC didn't even become available until 1981 anyway, and (as I can tell you from personal experience) the personal computers available prior to that were literally sneered at as toys by the mass of mainframe computer users who hadn't the vision to even consider the possibility that widely-available low-cost computers available to everybody might largely supplant the giant mainframes upon which their careers depended.  But time ticks on, obviously, and so today we need HAL/S tools that run on the computers actually available to us.  Which is to say, on Linux, Mac OS, or Windows computers.  (Or on hand-held devices, though I confess that it's hard to envisage working with HAL/S software on a cellphone!)

My initial iteration of a solution to this problem was to develop a Linux/Mac/Windows based HAL/S compiler which could translate HAL/S source code into a language I called PALMAT, for which I also had an emulator.  The compiler and emulator could optionally be combined into a HAL/S interpreter, into which the user could input HAL/S statements and immediately see the result of executing that statement.  I called this software yaHAL-S-FC.  The software functions pretty well, though it never reached the point of implementing 100% of HAL/S's features, nor of being extremely polished for user friendliness.  I halted work on it mainly because the effort of extending it to 100% functionality seemed to be expanding rather than contracting.  But it could be useful as an interactive learning aid for those who (for example) are working their way through Ryer's book.  The software remains available in the Virtual AGC software repository, and is the subject of two of our pages, one about the compiler itself and one about the interpreter alone.  I will not mention it again here.

The HAL/S development tools we focus on here are:

  1. A HAL/S compiler, implementing 100% of HAL/S features, producing IBM AP-101S object code.
  2. An IBM AP-101S assembler.
  3. An IBM AP-101S linker.
  4. An IBM AP-101S emulator.

The list above is in some ways a roadmap for future development, because at the present time we have only the compiler.  So the bulk of the discussion will concern just the compiler.

The HAL/S compiler, which I will refer to as HALSFC, is based on the source code for the original Intermetrics HAL/S compiler called HAL/S-FC.  Intermetrics actually had three separate HAL/S compilers that I know about:

Aside:  The surviving documentation is almost silent on the subject of having separate compilers for PASS vs BFS, but here's my understanding of what happened:

And if all of that wasn't enough for you, the structure of HAL/S-FC, in either the PASS or BFS version, is actually more complex than I may have implied.  In fact, HAL/S-FC was not just one program, but rather seven stand-alone "passes", some of them optional, that were run in succession to perform the full compilation:

Description
HAL/S-FC
HAL/S-BFC
Cross-compile HAL/S source code to HALMAT intermediate language
PASS1
PASS1B
Produce some optional reports about the HALMAT.  Sometimes called  "FLOWGEN"
FLO
Optimize the HALMAT representation
OPT
OPTB
Optimize it some more!
AUX
Cross-compile the HALMAT intermediate language to AP-101S object code PASS2
PASS2B
Produce optional Simulation Data Files (SDF)
PASS3
PASS3B
Print optional reports about the SDF
PASS4

Aside:  At present, modern implementations of PASS3/PASS3B/PASS4 have not yet been created, though as you can see from the table above, they're not needed merely for compilation of object code.

Aside:  Probably, you're beginning to see a truly explosive confusion of terminology around the word "pass":  There are 7 passes of the compiler, some of which are named PASSx and some of which are not, but meanwhile, "PASS" is also the name of the primary flight software!  Intermetrics also used the following alternate terminology, which is less confusing, and I may use it from time to time as well:
And to pile misery atop misery, Microsoft Windows reserves the name "AUX" in a way that makes it extremely difficult to use as the name of a file or a directory.  That includes variations like AUX.exe as well.  So to save ourselves a world of grief, even if not working on Windows, the AUX pass of the compiler is henceforth referred to as AUXP.

The original Intermetrics compilers, HAL/S-FC and HAL/S-360, were written in a high-level computer language I call XPL/I, with some "inline" IBM 360 machine code.  To get our modern HAL/S compiler, HALSFC, I first had to write an XPL/I compiler (which I call XCOM-I), and to compile Intermetrics's source code for HAL/S-FC.  There's a separate page dedicated to the XPL/I language and to XCOM-I.  Neither topic will be mentioned further here, except in passing.  Prior to that, the source code for PASS1/PASS1B of HAL/S-FC had been manually translated into the Python 3 language, creating a program I call HAL_S_FC.  This Python port is very useful for cross-checking HALSFC, but is (no longer) intended to be run directly by developers, and I've created no separate documentation for it beyond what's covered on the XCOM-I page.

As compiled by XCOM-I, the various passes of HAL/S-FC actually names like HALSFC-PASS1[.exe] or HALSFC-OPTB[.exe].

I know that all of this probably seems very complex.  It does to me!  However, HALSFC has been designed to hide all of that complexity from the developer.  I hope you'll find operation of HALSFC to be quite simple.

HALSFC

As I've mentioned, the many pieces of the modern HAL/S compiler are referred to by the blanket name HALSFC, and HALSFC is the only program you need to invoke to compile a HAL/S program into IBM AP-101S object code.

Let's just briefly examine how to use HALSFC.  Since we haven't yet covered how to install the program — that's covered in the next section! — you can't actually try out the commands I show you, but you can come back after installation and try them.  Installation, unfortunately, does have some complexity associated with it, and I'd prefer to encourage you with the simplicity first, before discouraging you with the complexity.  Besides, having a clear idea of what HALSFC can do and what it cannot do at present may help you to decide whether you want to install it at all.

Work with HALSFC is done from so-called "command line", because there's no graphical interface.  So let's suppose you're at a command line with the current working directory being an empty one.  Or rather, let's suppose that the directory is empty except for a simple-minded HAL/S file called HELLO.hal that looks like this:
DEBUG ¢D¢E¢F

HELLO: PROGRAM;
DECLARE I INTEGER;
DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY');
DECLARE INTEGER, J;
REPLACE PRINTER BY "6";
WRITE(PRINTER) 'THE BEGINNING';
DO FOR I = 1 TO 5;
WRITE(PRINTER) I, 'HELLO, WORLD!';
DO FOR J = 2 TO 8 BY 2;
WRITE(PRINTER) J, MY_NAME, 'SAYS ISN''T THIS FUN?';
END;
END;
WRITE(6) 'THE END';
CLOSE HELLO;

What this program does isn't important, though most of it is probably obvious at a glance, and other than the first line, the rest is easily understood by consulting Ryer's book.  The first line is an example of a compiler directive, which in this case is specific to the Intermetrics implementation and just affects that items appear on the compiler's printouts.

HALSFC is actually a shell script.  Or more accurately, two shell scripts:  HALSFC for Linux or Mac OS, and HALSFC.bat for Windows.  They are almost identical in operation, so there's not much reason to distinguish between them.

The HALSFC has up to five command-line arguments.  The latter four are optional, and default values are used if they're missing.  You can simply omit any arguments from the trailing end of the list, but if you want to omit any in the middle, you should use "" as a place-holder.  The full syntax of an invocation is this:
HALSFC SOURCEFILE.hal TEST "PARAMETERS" TARGET EXTENSION

Let's just try compiling HELLO.hal:

HALSFC HELLO.hal "" "LIST"

After a short period of time we're told:

Compilation successful. Results in "HALSFC Wed Aug 21 07:14:36 AM CDT 2024.results".

(or whatever your actual date and time is!) and our directory now contains both the HELLO.hal we started with, but also a subdirectory called "HALSFC Wed Aug 21 07:14:36 AM CDT 2024.results", which contains a lot of files.   Every time you run HALSFC, a new results-directory is created.  Since they're all named *.results, though, they're easy to find later and delete, and we don't have to have our working directory cluttered up with innumerable files, of which only a small subset are likely to be of interest.  I'll cover the files in this folder later, in probably-boring detail.

Note:  The results folder just mentioned is created only at the end of the compilation process, so if you manually abort HALSFC prior to completion, you will find the multitude of files that normally appear in the results folder now clutter up the working folder in which you're running HALSFC.  Compilation is normally pretty fast, since individual HAL/S source-code files tend to be short, so there's not usually a lot of reason for premature aborts, but it's still something to be aware of.  These files generally have names of the form *.bin, *.rpt, *.out, *.txt, or *.parms.

Of the files which are likely to be interesting, the one we usually look at first is the report (pass1.rpt) from the "phase 1" compiler pass, which is where our HAL/S source code is parsed, and in which most or all errors will have been detected.  Here's what that report looks like:
    HAL/S REL32V0                T I T A N  S Y S T E M S  C O R P .                 AUGUST 8, 2024    12:51:35.21     PAGE 1


HAL/S COMPILER PHASE 1 -- VERSION OF AUGUST 8, 2024. CLOCK TIME = 4:31:2.00.


TODAY IS AUGUST 8, 2024. CLOCK TIME = 12:51:35.21.

PARM FIELD: LIST


COMPLETE LIST OF COMPILE-TIME OPTIONS IN EFFECT


*** TYPE 1 OPTIONS ***

NOADDRS
NODECK
NODUMP
NOHALMAT
NOHIGHOPT
LFXI
LIST
NOLISTING2
MICROCODE
NOREGOPT
NOSDL
NOSREF
NOSRN
NOTABDMP
TABLES
NOTABLST
NOTEMPLATE
NOVARSYM
ZCON


*** TYPE 2 OPTIONS ***

BLOCKSUM = 400
CARDTYPE =
COMPUNIT = 0
DSR = 1
LABELSIZE = 1200
LINECT = 59
LITSTRINGS = 2000
MACROSIZE = 500
MFID =
PAGES = 2500
SYMBOLS = 200
TITLE =
XREFSIZE = 2000


*** NO LANGUAGE SUBSET IN EFFECT ***

------------------------------------------------------------------------------------------------------------------------------------------------------
HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 8, 2024 12:51:35.21 PAGE 2
STMT SOURCE REVISION



D| EBUG `D`E`F |

------------------------------------------------------------------------------------------------------------------------------------------------------
HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 8, 2024 12:51:35.21 PAGE 3
STMT SOURCE CURRENT SCOPE

1 M| HELLO: |HELLO
1 M| PROGRAM; |HELLO
2 M| DECLARE I INTEGER; |HELLO
3 M| DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); |HELLO
4 M| DECLARE INTEGER, J; |HELLO
5 M| REPLACE PRINTER BY "6"; |HELLO
6 M| WRITE(PRINTER) 'THE BEGINNING'; |HELLO
^^^^^^^
7 M| DO FOR I = 1 TO 5; |HELLO
8 M| 1 WRITE(PRINTER) I, 'HELLO, WORLD!'; |HELLO
^^^^^^^
9 M| 1 DO FOR J = 2 TO 8 BY 2; |HELLO

E| , |
10 M| 2 WRITE(PRINTER) J, MY_NAME, 'SAYS ISN''T THIS FUN?'; |HELLO
^^^^^^^
11 M| 1 END; |ST#9
12 M| END; |ST#7
13 M| WRITE(6) 'THE END'; |HELLO
14 M| CLOSE HELLO; |HELLO

------------------------------------------------------------------------------------------------------------------------------------------------------
HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 8, 2024 12:51:35.21 PAGE 4



**** C O M P I L A T I O N L A Y O U T ****

HELLO: PROGRAM;

------------------------------------------------------------------------------------------------------------------------------------------------------
HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 8, 2024 12:51:35.21 PAGE 5



S Y M B O L & C R O S S R E F E R E N C E T A B L E L I S T I N G :

(CROSS REFERENCE FLAG KEY: 4 = ASSIGNMENT, 2 = REFERENCE, 1 = SUBSCRIPT USE, 0 = DEFINITION)

DCL NAME TYPE ATTRIBUTES & CROSS REFERENCE

1 HELLO PROGRAM FLAGS=20040, NEST=0, SCOPE=1, PTR=2, LENGTH=0, LINK1=-1, LINK2=0, SYT_NO=1,
ARRAY=-8192, ADDR=0, CLASS=2, TYPE=73 XREF: 0 0001
2 I INTEGER SINGLE, ALIGNED, STATIC, FLAGS=808208, NEST=1, SCOPE=1, PTR=0, LENGTH=0,
LINK1=0, LINK2=0, SYT_NO=2, ARRAY=0, ADDR=0, CLASS=1, TYPE=6 XREF: 0 0002
4 0007 2 0008
3 MY_NAME CHARACTER(20) ALIGNED, STATIC, INITIAL, FLAGS=8A08, NEST=1, SCOPE=1, PTR=0, LENGTH=20,
LINK1=0, LINK2=0, SYT_NO=3, ARRAY=0, ADDR=0, CLASS=1, TYPE=2 XREF: 0 0003
2 0010
4 J INTEGER SINGLE, ALIGNED, STATIC, FLAGS=808208, NEST=1, SCOPE=1, PTR=0, LENGTH=0,
LINK1=0, LINK2=0, SYT_NO=4, ARRAY=0, ADDR=0, CLASS=1, TYPE=6 XREF: 0 0004
4 0009 2 0010
5 PRINTER REPLACE MACRO FLAGS=C000, NEST=1, SCOPE=1, PTR=0, LENGTH=0, LINK1=0, LINK2=0, SYT_NO=5,
ARRAY=0, ADDR=0, CLASS=6, TYPE=0, MACRO TEXT="6" XREF: 0 0005 2 0006 2 0008
2 0010



L I T E R A L T A B L E D U M P:

LOC TYPE LITERAL

1 ARITH 4214000000000000
2 CHAR RON BURKEY
3 ARITH 4160000000000000
4 CHAR THE BEGINNING
5 ARITH 4110000000000000
6 ARITH 4150000000000000
7 ARITH 4160000000000000
8 CHAR HELLO, WORLD!
9 ARITH 4120000000000000
10 ARITH 4180000000000000
11 ARITH 4120000000000000
12 ARITH 4160000000000000
13 CHAR SAYS ISN'T THIS FUN?
14 ARITH 4160000000000000
15 CHAR THE END



------------------------------------------------------------------------------------------------------------------------------------------------------
HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 8, 2024 12:51:35.21 PAGE 6


OPTIONAL TABLE SIZES

NAME REQUESTED USED
^^^^ ^^^^^^^^^ ^^^^

LITSTRINGS 2000 68
SYMBOLS 200 5
MACROSIZE 500 2
XREFSIZE 2000 13
BLOCKSUM 400 0


CALLS TO SCAN = 85
CALLS TO IDENTIFY = 14
NUMBER OF REDUCTIONS = 202
MAX STACK SIZE = 9
MAX IND. STACK SIZE = 5
END IND. STACK SIZE = 1
END ARRAY STACK SIZE = 0
MAX EXT_ARRAY INDEX = 1
STATEMENT COUNT = 14
MINOR COMPACTIFIES = 0
MAJOR COMPACTIFIES = 0
REALLOCATIONS = 0
MAX NESTING DEPTH = 1
FREE STRING AREA = 16620316


END OF HAL/S PHASE 1, AUGUST 8, 2024. CLOCK TIME = 12:51:35.22.

17 CARDS WERE PROCESSED.
NO ERRORS WERE DETECTED DURING PHASE 1 .


NUMBER OF FILE 6 LOCATES = 1
NUMBER OF FILE 6 READS = 0
NUMBER OF FILE 6 WRITES = 0


TOTAL CPU TIME FOR PHASE 1 0:0:0.02.
CPU TIME FOR PHASE 1 SET UP 0:0:0.01.
CPU TIME FOR PHASE 1 PROCESSING 0:0:0.00.
CPU TIME FOR PHASE 1 CLEAN UP 0:0:0.01.

There's lots of information here, though the most-significant thing is probably the message "NO ERRORS WERE DETECTED DURING PHASE 1".  What phase 1 (PASS1) has accomplished is mostly to output a processed form of our HAL/S program as expressed in an "intermediate language" called HALMAT.  Unfortunately, most of the documentation about HALMAT has not survived, but since the additional passes of the compiler do understand HALMAT, we don't necessarily need to understand it ourselves.  The HALMAT form of the program is the file halmat.bin.

The compiler then proceeded to further process halmat.bin, using the "phase 1.5" programs (FLO, OPT, and AUXP).  Those programs don't produce useful reports, at least not by default, so we don't need to look at their reports.  However, what they do is to "optimize" the HALMAT, producing new HALMAT related files called optmat.bin and auxmat.bin.

The "phase 2" program (PASS2) then pulls in all of those HALMAT and HALMAT-related files, and generates object code from them.  Let's look at PASS2's report, pass2.rpt:

PAGE 1


HAL/S COMPILER PHASE 2 -- VERSION OF AUGUST 8, 2024. CLOCK TIME = 4:32:17.00

HAL/S PHASE 2 ENTERED AUGUST 8, 2024. CLOCK TIME = 12:51:35.64


------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 2
SYMBOL TYPE ID ADDR LEN(HEX) LEN(DEC) BLOCK NAME


$0HELLO SD 0001 000000 000040 64 HELLO
#EHELLO SD 0002 000000 000006 6
#DHELLO SD 0003 000000 000033 51
@0HELLO ER 0004
#QIOINIT ER 0005
#QCOUT ER 0006
#QHOUT ER 0007

------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 3
LOC CODE EFFAD LABEL INSN OPERANDS SYMBOLIC OPERAND


0000000 ST#1 EQU *
00000 #EHELLO CSECT ESDID= 0002
00000 0000 DC X'0000'
00001 0000 DC X'0000'
00002 00000700 DC A'00000700' #DHELLO
00004 0000 DC X'0000'
00005 0000 DC X'0000'
00000 $0HELLO CSECT ESDID= 0001
0000000 HELLO EQU *
00000 E8F3 0000 LHI R0,0() @0HELLO
00002 E9F3 0000 LHI R1,0() #DHELLO
00004 B914 0005 STH R1,5(R0)
00005 E0FB 0014 IAL R0,20()
00007 EB11 0004 LA R3,4(R1)
00008 BB24 0009 STH R3,9(R0)
0000009 ST#2 EQU *
0000009 ST#3 EQU *
00009 #DHELLO CSECT ESDID= 0003
00009 000008 ORG *-1
00008 140A524F DC X'140A524F'
0000A 4E204255 DC X'4E204255'
0000C 524B4559 DC X'524B4559'
000000E ST#4 EQU *
000000E ST#5 EQU *
000000E ST#6 EQU *
00009 $0HELLO CSECT ESDID= 0001
00009 BEE8 LFXI R6,6
0000A BDE5 LFXI R5,3
0000B D0FF 3800 SCAL@# R0,0(R1,R3) #QIOINIT
0000D EAAD 002B LA R2,43(R1) C'THE BEGINNING'
0000E D0FF 3800 SCAL@# R0,0(R1,R3) #QCOUT
0000010 ST#7 EQU *
00010 BFE3 LFXI R7,1
00011 DF84 0033 BCF 7,*+34 B LBL#3 (WITHIN ST#12)
0000012 LBL#4 EQU *
0000012 ST#8 EQU *
00012 BEE8 LFXI R6,6
00013 BDE5 LFXI R5,3
00014 D0FF 3800 SCAL@# R0,0(R1,R3) #QIOINIT
00016 1DE7 LR R5,R7
00017 D0FF 3800 SCAL@# R0,0(R1,R3) #QHOUT
00019 EA8D 0023 LA R2,35(R1) C'HELLO, WORLD!'
0001A D0FF 3800 SCAL@# R0,0(R1,R3) #QCOUT
000001C ST#9 EQU *
0001C BCE4 LFXI R4,2
0001D DF3C 002D BCF 7,*+16 B LBL#5 (WITHIN ST#11)
000001E LBL#6 EQU *
000001E ST#10 EQU *
0001E BEE8 LFXI R6,6
0001F BDE5 LFXI R5,3
00020 D0FF 3800 SCAL@# R0,0(R1,R3) #QIOINIT
00022 1DE4 LR R5,R4
00023 D0FF 3800 SCAL@# R0,0(R1,R3) #QHOUT
00025 EA21 0008 LA R2,8(R1) MY_NAME
00026 D0FF 3800 SCAL@# R0,0(R1,R3) #QCOUT


------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 4
LOC CODE EFFAD LABEL INSN OPERANDS SYMBOLIC OPERAND

00028 EA61 0018 LA R2,24(R1) C'SAYS ISN'T THIS FUN?'
00029 D0FF 3800 SCAL@# R0,0(R1,R3) #QCOUT
000002B ST#11 EQU *
0002B BCE4 LFXI R4,2
0002C 840F 0007 AH R4,3(R3) J
000002D LBL#5 EQU *
0002D BC0F 0007 STH R4,3(R3) J
0002E B5E4 0008 CHI R4,8
00030 DE4E 001E BCB 6,*-18 BLE LBL#6 (WITHIN ST#9)
0000031 LBL#7 EQU *
0000031 ST#12 EQU *
00031 BFE3 LFXI R7,1
00032 870B 0006 AH R7,2(R3) I
0000033 LBL#3 EQU *
00033 BF0B 0006 STH R7,2(R3) I
00034 B5E7 0005 CHI R7,5
00036 DE96 0012 BCB 6,*-36 BLE LBL#4 (WITHIN ST#7)
0000037 LBL#8 EQU *
0000037 ST#13 EQU *
00037 BEE8 LFXI R6,6
00038 BDE5 LFXI R5,3
00039 D0FF 3800 SCAL@# R0,0(R1,R3) #QIOINIT
0003B EA4D 0013 LA R2,19(R1) C'THE END'
0003C D0FF 3800 SCAL@# R0,0(R1,R3) #QCOUT
000003E ST#14 EQU *
000003E LBL#2 EQU *
0003E C9F9 0000 0000 SVC 0(R1) H'21', X'0015'
0000E #DHELLO CSECT ESDID= 0003
0000E 000000 ORG *-14
00000 0015 DC X'0015'
00004 000013 ORG *+15
00013 00075448 DC X'00075448'
00015 4520454E DC X'4520454E'
00017 4400 DC X'4400'
00018 00145341 DC X'00145341'
0001A 59532049 DC X'59532049'
0001C 534E2754 DC X'534E2754'
0001E 20544849 DC X'20544849'
00020 53204655 DC X'53204655'
00022 4E3F DC X'4E3F'
00023 000D4845 DC X'000D4845'
00025 4C4C4F2C DC X'4C4C4F2C'
00027 20574F52 DC X'20574F52'
00029 4C442100 DC X'4C442100'
0002B 000D5448 DC X'000D5448'
0002D 45204245 DC X'45204245'
0002F 47494E4E DC X'47494E4E'
00031 494E4700 DC X'494E4700'
END

------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 5


RLD INFORMATION

POS.ID (P) IS THE ESDID OF SD FOR THE CONTROL SECTION THAT CONTAINS THE ADDRESS CONSTANT
REL.ID (R) IS THE ESDID OF ESD ENTRY FOR THE SYMBOL BEING REFERRED TO

FLAG TYPE ACTION PERFORMED

V00000ST YCON RELOCATION FACTOR IS ADDED TO ADDRESS CONSTANT. IF ADDRESS IS GREATER THAN 15 BITS, SET BIT "0" ON.
000001ST ACON RELOCATION FACTOR IS ADDED TO ADDRESS CONSTANT.
V00100ST ZCON ADD RELOCATION FACTOR TO FIRST HALFWORD. IF GREATER THAN 15 BITS, UPDATE BSR FIELD.
(BRANCH RELOCATION FOR 32-BIT BRANCH)
V10000ST ZCON UPDATE DSR FIELD WITH HIGH ORDER 4 BITS OF THE 19-BIT RELOCATION FACTOR.
(DATA RELOCATION FOR 32-BIT BRANCH)
V01000ST ZCON UPDATE BSR FIELD WITH HIGH ORDER 4 BITS OF THE 19-BIT RELOCATION FACTOR.
(BRANCH RELOCATION FOR 32-BIT DATA)
V10100ST ZCON ADD RELOCATION FACTOR TO FIRST HALFWORD. IF GREATER THAN 15-BITS, UPDATE DSR FIELD.
(DATA RELOCATION FOR 32-BIT DATA)

V = SIGN OF THE YCON IN THE TEXT RECORD
0 = THE YCON IS POSITIVE
1 = THE YCON IS THE ABSOLUTE VALUE OF A NEGATIVE NUMBER
S = DIRECTION OF RELOCATION
0 = POSITIVE
1 = NEGATIVE
T = TYPE OF NEXT RLD ITEM
0 = NEXT RLD ITEM HAS DIFFERENT R OR P POINTERS; THEY ARE IN THE NEXT ITEM
1 = NEXT RLD ITEM HAS SAME R AND P POINTERS; HENCE THEY ARE OMITTED

POS.ID CSECT(P) ADDRESS FLAGS REL.ID CSECT(R)

0001 $0HELLO 000001 00 0004 @0HELLO
0001 $0HELLO 000003 00 0003 #DHELLO
0001 $0HELLO 00000C 00 0005 #QIOINIT
0001 $0HELLO 00000F 00 0006 #QCOUT
0001 $0HELLO 000015 00 0005 #QIOINIT
0001 $0HELLO 000018 00 0007 #QHOUT
0001 $0HELLO 00001B 00 0006 #QCOUT
0001 $0HELLO 000021 00 0005 #QIOINIT
0001 $0HELLO 000024 00 0007 #QHOUT
0001 $0HELLO 000027 00 0006 #QCOUT
0001 $0HELLO 00002A 00 0006 #QCOUT
0001 $0HELLO 00003A 00 0005 #QIOINIT
0001 $0HELLO 00003D 00 0006 #QCOUT
0002 #EHELLO 000002 10 0001 $0HELLO
0002 #EHELLO 000002 40 0003 #DHELLO

------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 6



VARIABLE OFFSET TABLE
LOC IS THE CSECT-RELATIVE ADDRESS IN HEX OF THE DECLARED VARIABLE.
B IS THE BASE REGISTER USED FOR ADDRESSING THE DECLARED VARIABLE. IF B IS NEGATIVE, THIS IS A VIRTUAL REGISTER AND CODE
MUST BE GENERATED TO LOAD A REAL REGISTER.
DISP IS THE DISPLACEMENT USED FOR GENERATING BASE-DISPLACEMENT ADDRESSES FOR ACCESSING THE DATA ITEMS.
LENGTH IS THE SIZE IN DECIMAL HALFWORDS OF THE VARIABLE.
BIAS IS THE AMOUNT OF THE ZEROTH ELEMENT OFFSET.
NAME IS THE NAME OF THE VARIABLE.


LOC B DISP LENGTH BIAS NAME

UNDER HELLO STACK=20
000006 1 006 1 0 I
000008 1 008 11 0 MY_NAME
000007 1 007 1 0 J


------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 7



MEMORY MAP FOR DATA CSECT #DHELLO

NAME LEN(DEC) OFFSET(DEC) B DISP(HEX) SCOPE

**LOCAL BLOCK DATA** 2 4 HELLO
I 1 6 1 0006 HELLO
J 1 7 1 0007 HELLO
MY_NAME 11 8 1 0008 HELLO

TOTAL SIZE OF ALIGNMENT GAPS FOR CSECT: 0 HW



INSTRUCTION FREQUENCIES

INSN COUNT
LFXI 12
LR 2
STH 4
LA 6
AH 2
SCAL 11
IAL 1
BCB 2
BCF 2
SVC 1
LHI 2
CHI 2


OPTIONAL TABLE SIZES

NAME REQUESTED USED
^^^^ ^^^^^^^^^ ^^^^

LITSTRINGS 2000 68
LABELSIZE 1200 8


42 HALMAT OPERATORS CONVERTED

47 INSTRUCTIONS GENERATED

70 HALFWORDS OF PROGRAM, 51 HALFWORDS OF DATA.

MAX. OPERAND STACK SIZE =9
END OPERAND STACK SIZE =0
MAX. STORAGE DESCRIPTOR STACK SIZE =1
END STORAGE DESCRIPTOR STACK SIZE =0
NUMBER OF MINOR COMPACTIFIES =0
NUMBER OF MAJOR COMPACTIFIES =0
NUMBER OF REALLOCATIONS =5
FREE STRING AREA =16623408

END OF HAL/S PHASE 2 AUGUST 8, 2024. CLOCK TIME = 12:51:35.65


------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 8


TOTAL CPU TIME FOR PHASE 2 0:0:0.01
CPU TIME FOR PHASE 2 SET UP 0:0:0.00
CPU TIME FOR PHASE 2 GENERATION 0:0:0.00
CPU TIME FOR PHASE 2 CLEAN UP 0:0:0.01

The most-significant thing about PASS2's report is probably that it gives us a glimpse — well, actually a full listing — of the assembly-language into which the compiler has transformed our HAL/S sample program.  PASS2 doesn't actually put such a listing in its report, by the way, at least not by default.  It only did so in this case because we compiled it with the LIST option.  After all, software that's merely printed in a report has very little use from the computer's point of view.  In fact, I've only included it in the report as eye candy!

Rather, useful object code is emitted in the form of a file, called cards.bin.  The cards.bin file is what would be used by a linker or loader.  The object code is, of course, IBM AP-101S object code.  You can read all about it, in all its gory detail, in the document "Space Shuttle Model AP-101S Principles of Operation, with Shuttle Instruction Set".

As for the object file, it is in the OS/360 Object File Format — or at least, very close to it! —, which you can read about in its wikipedia article.  There are some slight differences, in that you'd expect text strings in the object file to be encoded in EBCDIC, whereas they are instead encoded using the Display Electronics Unit (DEU) character set.

Rather than compiling HELLO.hal using the command given earlier, I'd be more likely to compile it using the command

HALSFC HELLO.hal TEST "LIST,NOTABLES,LISTING2"

The difference, you'll recall, is that TEST additionally performs some verification of the compiler results, and that TEST requires NOTABLES. (NOTABLES simply means not to run the compiler's PASS3 and PASS4, which we weren't even looking at in this example anyway.  LISTING2 means to produce a secondary, "unformatted" source-code listing.)  In fact, here are the messages we get,

======================================================
PASS1 cross-comparison test:
Files pass1A.rpt and pass1pA.rpt are identical
Files FILE1.bin and halmat.bin are identical
Files LISTING2.txt and listing2.txt are identical
======================================================
Compilation successful. Results in "HALSFC Wed Aug 21 07:39:24 AM CDT 2024.results".

What we're told is that essentially the same compilation has been performed, but that additionally we gained some confidence that the various of the compiler outputs are correct.  By the way, the secondary listing looks like this:

1  H A L   C O M P I L A T I O N   --   P H A S E   1   --   U N F O R M A T T E D   S O U R C E   L I S T I N G             PAGE 1
- D| EBUG `D`E`F | 1
0 1 M| | 2
0 1 M| HELLO: PROGRAM; | 3 HELLO
0 1 M| DECLARE I INTEGER; | 4 HELLO
0 2 M| DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); | 5 HELLO
0 3 M| DECLARE INTEGER, J; | 6 HELLO
0 4 M| REPLACE PRINTER BY "6"; | 7 HELLO
0 5 M| WRITE(PRINTER) 'THE BEGINNING'; | 8 HELLO
0 6 M| DO FOR I = 1 TO 5; | 9 HELLO
0 7 M| WRITE(PRINTER) I, 'HELLO, WORLD!'; | 10 HELLO
0 8 M| DO FOR J = 2 TO 8 BY 2; | 11 HELLO
0 9 M| WRITE(PRINTER) J, MY_NAME, 'SAYS ISN''T THIS FUN?'; | 12 HELLO
0 10 M| END; | 13 HELLO
0 11 M| END; | 14 HELLO
0 12 M| WRITE(6) 'THE END'; | 15 HELLO
0 13 M| CLOSE HELLO; | 16 HELLO

The characters in column 1 are so-called ANSI control characters, as described later.

Installation of HALSFC

For Linux, Mac OS, or Windows.

  1. Install XCOM-I, per the instructions on the XPL/I page.
  2. Perhaps you can download pre-built HALSFC executables.  I give you no guarantee that they'll work, and you run the risk of not necessarily getting the most up-to-date version of the compiler.  If those things bother you (they should!) then go on to step 3 instead.  But if you do download them, and if the stuff described in the preceding section works for you after doing so, then you're all done with the installation.
  1. (Optional but recommended.)  Verify that XCOM-I works, by following the instructions appropriate to your computer type, as given in the following sections of the XPL/I page:
  1. Build HALS/S-FC executable files, using the instructions on the XPL/I page.

Where the Wild HAL/S Files Are

Naturally, the most-important HAL/S source-code files for us will be the PASS and BFS source-code files of the Space Shuttle. 

In lieu of those, however, it would be nice to have some HAL/S source-code files other than HELLO.hal or files we have to write for ourselves!  Fortunately, Ryer's book Programming in HAL/S is a rich source of source.  A hundred or so short source-code files have been extracted from Ryer, and can be found in the directory "virtualagc/yaShuttle/Source Code/Programming in HAL-S".

The HAL-S-360 Users Manual is a much-more feeble source of source, though if you look in the directory "virtualagc/yaShuttle/Source Code/HAL-S-360 Users Manual" you'll find a file called DEMO.hal that I've taken from the Users Manual.  It is interesting because it also shows us what the compiler listing was supposed to look like.  That listing is not quite the same as ours today.  But given that it was a version of the HAL/S compiler 30 years younger than ours, and that the compiler used was HAL/S-360 rather than HAL/S-FC, it's hardly surprising that there are some differences.

There may be other HAL/S source among our collected documentation, that I've overlooked.  If you notice any — or for that matter, have any! — let me know.

Some Differences Between the Old and the New

EBCDIC vs ASCII

The original HAL/S compiler, running on an IBM System/360 computer as it did, expected that the underlying encoding of textual characters such as letters and numbers was EBCDIC.  EBCDIC, to put it mildly, is no longer a common encoding for character sets.  The current common practice, which I'll stick my neck out and assume will continue into the future, is for character sets to be encoded in what's known as UTF-8, a scheme in which a variable number of bytes (from 1 to 6) is used for each unique glyph, but that the vast majority of all software source code is encoded in the 7-bit subset of UTF-8 known as ASCII.

In the case of HAL/S source code, as originally specified in the early 1970's, it so happens that the legal character set contained basically:

I say "basically", because technically there are some quibbles about some of the characters (^, \, and end-of-file) with which I will not bore you.  But I will mention that in spite of the technical illegality of it, legacy HAL/S and XPL source code often already uses either '~' or '^' in place of '¬'.

Given these facts and the obvious technical advantages of using a 7-bit character set for everything, the modern tool-set:

These restrictions apply only to HAL/S source code.  And, any human-readable reports generated by the compiler are pure 7-bit ASCII with the substitutions mentioned.  This should not be taken to imply that character data is maintained internally by the compiler in ASCII encoding, nor that all files output by the compiler have text encoded in ASCII.  In fact, that's not true:  Internally, the compiler uses mostly EBCDIC, and other than files which are human-readable, characters are encoded in the same manner as the original compiler encoded them.  For example, textual data in AP-101S object-code files uses Display Electronics Unit (DEU) encoding (seen in the figure to the right), which is neither EBCDIC nor ASCII, though in some ways being ASCII-like.

COMMON Memory

Much of the data transferred from one compiler pass to the next resided in so-called COMMON memory.  I refer here not to the HAL/S compilation unit known as a COMPOOL, but rather to sections of IBM 360 memory which were expected to be left intact when one pass of the compiler (say, PASS2) terminated and the next pass of the compiler (say, PASS3) was loaded and began executing.  Given that the modern HAL/S compiler implements each pass of the compiler as a stand-alone program, no such continuity of physical memory is possible.  So some other means must be used to preserve this data.

The modern compiler handles this by storing COMMON data in files.  Upon termination, a compiler pass writes an output-file describing the state of COMMON memory.  And similarly, upon startup, a compiler pass reads and input-file describing the state of COMMON memory.  The compiler maintains a model of the IBM 360 24-bit memory space, and the addresses of all COMMON data remain the same in this 24-bit model throughout any compilation run.

Overstruck Lines in Reports

Since the original compiler physically printed reports and could control whether or not the printer advanced the paper, it was capable of overstriking those printed lines with decorations such as underlines.  The corresponding reports output by the modern compiler are plain ASCII text, and overstriking is not possible.  For example, in a source-code listing, expansion of a macro was originally indicated by underlining the macro.

The modern compiler mimics the original underlining with a line of text, such as

THIS IS MY UNDERLINED TEXT

with two lines of text, thusly:

THIS IS MY UNDERLINED TEXT
^^^^^^^^^^

While this nicely conveys the underlining effect, I think, the fact that some single printed lines are replaced by dual printed lines does affect the vertical alignment and the pagination.

Compiler Options, Part One

There are a number of options that are specific to the modern HAL/S compiler, versus the original HAL/S compiler (which naturally didn't have these "modern" options).  I'll resist the temptation of going through those in detail.  If you're interested, I'd suggest using the command

HALSFC-PASS1 --help

to get descriptions of them.  Most of them relate to debugging the HAL/S compiler itself, and hence are of little value to anybody wishing merely to use the compiler.  All of the other compiler passes (HALSFC-FLO, HALSFC-OPT, and so on) will list all of the same options, so you needn't look past HALSFC-PASS1.

However, there are quite a few options, too, that are command-line replacements for what were specified to the original HAL/S compiler by its Job Control Language (JCL), and specifically for attaching various input files or output files to the various compiler passes.  I'll cover those options here, briefly.  There's a later section that describes the uses of these file-attachment options in detail, ad nauseum.

More on the Compiler Options

In the preceding section, we talked about options specific to the modern compiler, principally as they involved attaching input- or output-files to the compiler.  Now let's talk about the compiler options inherited from the original HAL/S compiler.  There are many such options that can be presented to the HAL/S compiler to affect its behavior.

These options were presented to the original compiler via a so-called "PARM field" in its Job Control Language (JCL).  In the modern implementation, there's no such thing as JCL, so such options are instead provided to the compiler via the command line.  For example,
HALSFC-PASS1 --parm="..." etc.
where the "..." represents a list of options, delimited by commas, without additional blank spaces.  For example, --parm="LIST,SRN,TITLE=MY COMPILER".  (Yes, I said "without spaces", but I meant without spaces between the options.  The space in this example is within the TITLE option, which has a value that's a string.)

As it happens, many of the passes of the HAL/S compiler don't directly accept such options, but instead expect them to have been provided to an earlier compiler pass (such as PASS1 or PASS1B), and to persist throughout the remaining compiler passes via COMMON memory.  If you'll recall the compiler from PASS1 for the program HELLO.hal that I used earlier, you may also recall that it began with a list of the options in effect for that particular program run:
 PARM FIELD: LIST


COMPLETE LIST OF COMPILE-TIME OPTIONS IN EFFECT


*** TYPE 1 OPTIONS ***

NOADDRS
NODECK
NODUMP
NOHALMAT
NOHIGHOPT
LFXI
LIST
NOLISTING2
MICROCODE
NOREGOPT
NOSDL
NOSREF
NOSRN
NOTABDMP
TABLES
NOTABLST
NOTEMPLATE
NOVARSYM
ZCON


*** TYPE 2 OPTIONS ***

BLOCKSUM = 400
CARDTYPE =
COMPUNIT = 0
DSR = 1
LABELSIZE = 1200
LINECT = 59
LITSTRINGS = 2000
MACROSIZE = 500
MFID =
PAGES = 2500
SYMBOLS = 200
TITLE =
XREFSIZE = 2000
In contrast, the sample compiler report from PASS2 lists no such parameters, and yet it partakes of some of them (such as LIST) selected by invoking PASS1.

Many but not all of the allowed behavioral options are described in the HAL/S-FC User's Manual (section 5), but I'll give you my own take on them here.  Overall, the options can be categorized in several ways.  For one thing, they can be of "type 1" (meaning that they are mere on/off) or else of "type 2" (meaning that they have numerical or textual values).  For another, they can be "printable" or "unprintable".  All of the options you see in the compiler report above are printable; there are other options in effect, namely the unprintable ones, but the unprintable ones weren't printed in the report.  Moreover, each of the options has a default value it assumes if it's not specified directly.  Each of the type-1 options (i.e., the toggles) can be provided either in the positive form (meaning that the option is enabled) or the negative form (meaning that it is disabled).  For example, the LIST option is enabled by putting LIST in the parm field, and is disabled by putting NOLIST in the parm field, though it is actually disabled by default anyway.  Most options have both a long and a short form by which they can be specified.  LIST is a long form.  Its corresponding short form is simply L, whereas the short form of NOLIST is NL.  Or at least, that's the case for PASS1 and PASS1B; for PASS4, LIST has instead become a type-2 option, and takes a numerical value, thus having no corresponding NOLIST or NL.  But LIST appears to be the only parameter which changes its form in this chameleon-like way.

The table below shows the various compiler options accepted by different compiler passes.  Remember that the pass at which the option is accepted is not necessarily the pass at which it has any effect, and is not even any indication that the option is used for anything at all.  Some of the descriptions given in the table below are pasted or adapted from the HAL/S-FC User's Manual.

PARM-Field Options and Defaults, by Compiler Pass
Accepted in PASS1
Accepted in PASS1B
Accepted in PASS4 Description
Type 1, Printable
DUMP (off, DP)
DUMP (off, DP)
Requests the compiler to produce a memory dump if internal compiler failures occur; useful only for compiler generation and debugging.
LISTING2 (off, L2)
LISTING2 (off, L2)

Causes PASS1 to generate an "unformatted" source listing, which is an output-file (listing2.txt by default) separate from the normal compiler report generated by PASS1.  The nature of such a secondary listing is perhaps best illustrated by simply showing you one from our sample HELLO.hal program:
1  H A L   C O M P I L A T I O N   --   P H A S E   1   --   U N F O R M A T T E D   S O U R C E   L I S T I N G             PAGE 1
- D| EBUG `D`E`F | 1
0 1 M| | 2
0 1 M| HELLO: PROGRAM; | 3 HELLO
0 1 M| DECLARE I INTEGER; | 4 HELLO
0 2 M| DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); | 5 HELLO
0 3 M| DECLARE INTEGER, J; | 6 HELLO
0 4 M| REPLACE PRINTER BY "6"; | 7 HELLO
0 5 M| WRITE(PRINTER) 'THE BEGINNING'; | 8 HELLO
0 6 M| DO FOR I = 1 TO 5; | 9 HELLO
0 7 M| WRITE(PRINTER) I, 'HELLO, WORLD!'; | 10 HELLO
0 8 M| DO FOR J = 2 TO 8 BY 2; | 11 HELLO
0 9 M| WRITE(PRINTER) J, MY_NAME, 'SAYS ISN''T THIS FUN?'; | 12 HELLO
0 10 M| END; | 13 HELLO
0 11 M| END; | 14 HELLO
0 12 M| WRITE(6) 'THE END'; | 15 HELLO
0 13 M| CLOSE HELLO; | 16 HELLO
0 14 M| | 17 HELLO

Perhaps the only thing not immediately clear to you would be the markings in the first column ('1', '-', '0').  These are so-called ANSI control characters (plus some IBM extensions to them) that would have informed a line printer as to disposition of the line.  Here's what I think are all their possible values, although not all of them are ultimately used in secondary listings:
  • ' ':  Single-space and print.
  • '0':  Double-space and print.
  • '-':  Triple-space and print.
  • '+:  Overstrike the preceding line.
  • '1':  Advance to the next page and print.
  • 'H':  Don't print, but use the line as the heading for subsequent pages.
  • '2':  Don't print, but use the line as the subheading for subsequent pages.
LIST (off, L)
LIST (off, L)

Causes PASS2 to include AP-101S assembly-language for the compiled HAL/S program in the report it prints.  (As you've seen above in the PASS2 report generated from our sample HELLO.hal program.)
TRACE (on, TR)
TRACE (on, TR)

(I'm not sure what TRACE does, but the comments in HAL/S-FC source code indicate that it is for the IBM 360 target only, and thus is irrelevant to AP-101S.)
VARSYM (off, VS)
VARSYM (off, VS)

If specified, symbol-table information about the variables declared in the HAL/S program will be included in the AP-101S object-code file(s) generated by PASS2.   Our sample HELLO.hal program, for example, has declarations for the integer variables I and J, and the string variable MY_NAME.  Without VARSYM, while the object code would could correctly manipulate the data for these I, J, and MY_NAME by referencing their memory addresses, it would not include the symbolic names of I, J, and MY_NAME, nor their types (integer vs string), nor other interesting info about them.  Such additional information would be useful, for example, in performing symbolic debugging of the AP-101S code.  See the section on SYM records in the Wikipedia article about the IBM 360 Object File Format.
DECK (off, D)
DECK (off, D)

If specified, an additional copy (by default, deck.bin) of the object file produced by Phase 2 (by default, cards.bin or cards/) is produced.  For the PASS version of the compiler, deck.bin is identical to cards.bin.  For the BFS version of the compiler, the deck.bin differs from cards/.  See the section about the files produced by the compiler.
TABLES (on, TBL)
TABLES (on, TBL)

This option was originally intended to inhibit execution of PASS3 and PASS4 by specifying NOTABLES, when simulation and/or debugging of the object code wasn't needed.  For the modern compiler, this option doesn't have that effect, since the various compiler passes do not directly chain themselves together, but are rather chained together by the HALSFC.sh/.bat script.  In other words, today you'd control whether or not PASS3 and/or PASS4 were run by means of command-line parameters when invoking HALSFC.sh/.bat.  See the "test drive" section.
TABLST (off, TL)
TABLST (off, TL)
TABLST (off, TL) Causes PASS4 of the compiler to produce a formatted dump of the Simulation Data File.
ADDRS (off, A)
ADDRS (off, A)

Causes the Simulation Data Files (SDF) produced to include statement address information.
SRN (off)
SRN (off)

This should be specified if the source program is line numbered.  It causes the compiler to scan columns 1-72 only, allowing columns 73-78 to be used for line
numbers.  Note:  The Shuttle's PASS and BFS source code does have line numbers in columns 73-78, confing source code to columns 1-72, so the SRN option should always be used when compiling PASS/BFS source code.
SDL (off)
SDL (off)

Used to indicate to the compiler that this compilation is for SDL (Software Development Lab) use.  The HAL/S-FC User's Manual goes on to describe a lot of additional implications of this that I won't bother to describe here.

In brief, the Software Development Lab and its successor the Software Production Facility (SPF) were where the flight software was tested by running it in a simulated environment.  Thus, option NOSDL meant the software would be built for Shuttle onboard usage, whereas option SDL meant the software would be built for ground-testing purposes.  Additional reading:  "Spacecraft Avionics Software Development Then and Now: Different But the Same" and "HAL/S-FC SDL Interface Control Document".
TABDMP (off, TBD)
TABDMP (off, TBD)
TABDMP (off, TBD) Causes PASS4 to produce a hexadecimal dump of the Simulation Data File.
ZCON (on, Z)
ZCON (on, Z)

Causes calls to out-of-line routines (external references) to be performed via long indirect address constants. 

This is connected to the concept of DECLARE'ing data with the REMOTE attribute, which has caused me quite a lot of confusion personally, so I'll say a few words about it here.  Given that the General Purpose Computers (GPC's) in a Shuttle intercommunicate among themselves, you might suppose that REMOTE data is data residing on a different GPC than the one running the HAL/S program.  That's not what it is.  Rather, REMOTE pertains to data which while residing on the local GPC is nevertheless not near enough in the address space of the GPC to the instruction using that data to be addressable in an efficient fashion.  In particular, data which is farther away in the address space than 16-bits (in terms of 16-bit "halfwords") is not directly accessible in any simple fashion by AP-101S instructions.  Data accessible via short address displacements (YCONs) can therefore be accessed more efficiently, whereas data accessible only via long addresses (ZCONs) is accessed much less efficiently and is DECLARE'd using the REMOTE attribute.

What the ZCON compiler option does, I think, is the equivalent of implicitly causing all external symbols to be considered REMOTE.
HALMAT (off, HM)
HALMAT (off, HM)

If specified, HALMAT and literal tables are included in the SDF generated by PASS3.  NOHALMAT will reduce the size of the SDF considerably.
REGOPT (off, R)
REGOPT (off, R)
Used to indicate to the compiler that register optimization is desired. Allows borrowing of register 3 for addressing COMPOOL data.  The HAL/S User's Manual describes additional subtleties vis-à-vis the SDL option (see above).

SCAL (on, SC)
NOSCAL inhibits the use of the AP-101S instructions SCAL and SRET for subroutine linkage, even if the MICROCODE option (see below) was also chosen.  MICROCODE and NOSCAL together thus cause HAL/S linkage to be used instead of the SCAL/SRET instructions. If NOMICROCODE was specified, neither SCAL or NOSCAL has any effect.
MICROCODE (on, MC)
MICROCODE (on, MC)

Allows use of instructions which only exist on late versions of the Space Shuttle GPC. This includes SCAL, SRET, MVS, MVH, and BIX.

I've found no definitive explanation of how or when these late-model GPC instructions appeared.   However, it may be worth remembering that originally the Shuttle's GPCs were IBM AP-101B computers.  The upgraded AP-101S computers only began to be flown (with modifications to the flight software from OI-8F onward) in 1991.  So far, the only descriptions I've found of the changes in the AP-101S vs the AP-101B have made no mention at all of new instruction types, and in particular, alas, we do not have a list of the AP-101B instruction set.  My guess is that the newer instructions were present in the AP-101S but absent in the AP-101B.
SREF (off, SR)
SREF (off, SR)

Causes only those variables from an included EXTERNAL COMPOOL which are actually referenced by the unit being compiled to be printed in the cross reference listing. 
QUASI (off, Q)
QUASI (off, Q)

(I'm not sure what QUASI does, but the comments in HAL/S-FC source code indicate that it is for the IBM 360 target only, and thus is irrelvant for AP-101S.)
TEMPLATE (off, TP)
TEMPLATE (off, TP)
Causes the generation of a template for the compilation unit.  For example, if a HAL/S source-code file contains (say) a FUNCTION, then the TEMPLATE option causes a prototype for that function to be placed in the shared template library.  By using a compiler directive (D INCLUDE TEMPLATE ...), independently-compiled HAL/S units can reuse that previously-defined function without having to know how to explicitly declare it themselves. 

(Or using an analogy, if C compilers had a TEMPLATE option, they could automatically generate a C header file from a C source-code file.)
HIGHOPT (off, HO)
HIGHOPT (off, HO)
The high optimization option (HIGHOPT) allows the compiler to perform optimizations that may not be valid under certain circumstances which the HAL/S-FC User's Manual lists.  In other words, optimization is better when the HIGHOPT option is used, but certain programming practices have to be avoided.  Basically, HIGHOPT turns off certain kinds of datatype-checking, so that certain kinds of macros or manipulations of NAME variables which bypass the type-checking system should not be used.  Thus HIGHOPT is probably safe to use except with code written by Very Clever People™ or by people who want to be Very Clever.


ALL (off) The comments in PASS4 source code indicate that ALL means to "process all SDFs", though it's not quite clear to me what the implications of that are.


BRIEF (off) If BRIEF is in effect, PASS4 does not print a formatted dump of the SDF in its output report.  BRIEF automatically applies the TABLST and NOTABDMP compiler options.
Type 1, Unprintable
PARSE (off, P)
PARSE (off, P)

Debug. Gives parsing location information if an error is encountered.
LSTALL (off, LA)
LSTALL (off, LA)

Debug.  Causes both assembly language (like LIST) and HALMAT to appear in PASS2's output report.
Aside: As I've complained about, the surviving documentation for the HALMAT intermediate language is incomplete, and in particular is inadequate for implementing a new object-code generator for the HAL/S compiler.  I mean, perhaps we don't like having AP-101S object code, and for some reason prefer object code we might be able to execute more easily.  Now, if (hint! hint!) somebody were to use the LSTALL option judiciously, they could possibly make a complete map of the expected runtime behavior of each HALMAT instruction.  Which could in turn allow somebody to replace PASS2 by (for example) a C generator that we might call PASS2C.  Just a thought!
LFXI (on)
LFXI (on)

Causes the AP-101S instruction LFXI to be used in preference to LHI, LE, or SER instructions under certain circumstances. 
X1 (off)
X1 (off)
Documentation (and here) claims that option X1 disables optimization.  I have so far been unable to verify this.


X3 (off) Documentation (and here) claims that option X3 causes the phase 1.5 (optimization) to list HALMAT changes.  This must be false for HAL/S-FC, which does not even accept the X3 option in its PARM field.  It's likely the documentation is referring to HAL/S-360 — alas, unavailable to us — instead, since HAL/S-360 does accept the X3 option.
X4 (off) X4 (off) X4 (off) (Apparently unused.)
X5 (off) X5 (off) X5 (off) The X5 option enables a TRACE functionality (not to be confused with the IBM 360 TRACE option described above) during the OPT pass.  Documentation describes it as printing program flow and data bases.  Here's a an excerpt from OPT's output report from HELLO.hal that shows the effect:

PAGE 1


SYMBOL_SHRINKER(2): 2 I
SYMBOL_SHRINKER(3): 3 MY_NAME
SYMBOL_SHRINKER(4): 4 J
SYMBOL_SHRINKER(5): 5 PRINTER

------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 2


HAL/S OPTIMIZER -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:38:48.00

HAL/S OPTIMIZER ENTERED AUGUST 11, 2024. CLOCK TIME = 8:28:19.16

FINAL_PASS: 0
ASSIGNMENT: 27
ASSIGNMENT: 45

NO REL
2 2 I
3 3 MY_NAME
4 4 J
5 5 PRINTER
STACK_DUMP: LEVEL=1, BLOCK#=2, INL#=0, OLD_LEVEL=0, OLD_BLOCK#=0, VAL_SIZE=1

LEVEL STACKED_BLOCK# STACK_TAGS PULL_LOOP_HEAD
0 1 00000000 -1
1 2 00000000 -1

RECORD_TOP(CATALOG_ARRAY)= 1
RECORD_TOP(VALIDITY_ARRAY)= 1
RECORD_TOP(ZAPS)= 1
ZAP_BASE=1, PULL_LOOP_HEAD(LEVEL)=-1
SYT_SIZE=5, SYT_WORDS=0, SYT_USED=0

VALIDITY ZAPS LOOP_ZAPS
00000000 00000014 00000014
ASSIGNMENT: 45

X6 (off) X6 (off) X6 (off) The X6 option causes timing and other statistics to be collected and printed about the optimization process during execution of the OPT and AUXP passes.  In the sample below, generated from the HELLO.hal program, the green parts represent the contribution of X6 to OPT's report.  As for what it means, I couldn't tell you, other than that very little optimization seems to be have been needed for HELLO.hal.
PAGE 1


HAL/S OPTIMIZER -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:38:48.00

HAL/S OPTIMIZER ENTERED AUGUST 10, 2024. CLOCK TIME = 18:36:29.10


CSE'S FOUND = 0


COMPARE CALLS = 0
SCANS = 0
MAX_NODE_LIST = 0
MAX_CSE_TAB = 1
MINOR COMPACTIFIES = 0
MAJOR COMPACTIFIES = 0
FREE STRING AREA = 16637938


END OF HAL/S OPTIMIZER AUGUST 10, 2024. CLOCK TIME = 18:36:29.10


TOTAL CPU TIME FOR OPTIMIZER 0:0:0.00
CPU TIME FOR OPTIMIZER SETUP 0:0:0.00
CPU TIME FOR OPTIMIZER CRUNCHING 0:0:0.00
CPU TIME FOR OPTIMIZER CLEAN UP 0:0:0.00


END OF HAL/S OPTIMIZER AUGUST 10, 2024. CLOCK TIME = 18:36:29.10
In the case of AUXP, the report would normally be completely empty, so the entire report is contributed by X6:
PAGE 1


HAL/S AUXILIARY HALMAT GENERATOR -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:39:10.00

HAL/S AUXILIARY HALMAT GENERATOR ENTERED AUGUST 10, 2024. CLOCK TIME = 18:55:22.04



END OF HAL/S AUXILIARY HALMAT GENERATOR AUGUST 10, 2024. CLOCK TIME = 18:55:22.04

TOTAL CPU TIME FOR AUXILIARY HALMAT GENERATOR : 0:0:0.01
CPU TIME FOR AUXILIARY HALMAT GENERATOR SETUP : 0:0:0.01
CPU TIME FOR AUXILIARY HALMAT GENERATOR CRUNCHING : 0:0:0.00

TOTAL NUMBER OF GARBAGE COLLECTIONS = 2
MAXIMUM NUMBER OF USED CELLS = 499
TOTAL TIME SPENT IN GARBAGE COLLECTION = 0:0:0.00

TOTAL TIME SPENT IN PRETTY PRINTING AUXMAT = 0:0:0.00

MAXIMUM STACK LEVEL = 1

NUMBER OF MINOR COMPACTIFIES = 0
NUMBER OF MAJOR COMPACTIFIES = 0
FREE STRING AREA = 16582621




X7 (off) (Apparently unused.)


X8 (off) (Apparently unused.  Comments in PASS2 erroneously indicate that it is used there, but are in actuality referring to the MICROCODE option.)


X9 (off) (Apparently unused.)
XA (off) XA (off) XA (off) (Apparently unused.)
XB (off) XB (off)
The XB option adds information to PASS3's output report about deleted symbols.
XC (off) XC (off)
The XC option adds a symbol-table dump to PASS3's output report.


XD (off) (Apparently unused.)
XE (off)
XE (off)
XF (off) XF (off)
XF (off)


XG (off)


XH (off)


XI (off)


XJ (off)


XK (off)


XL (off)


XM (off)


XN (off)


XO (off)


XP (off)
Type 2, Printable
TITLE ("", T)
TITLE ("", T) TITLE ("", T)
Specifies a (1 to 60 character) title to be printed by PASS1 as a header at the top of each page of its output report. The header should be specified precisely as it is to appear.  It may contain spaces, but should not contain any commas, since commas are delimiters between options appearing in the PARM field.

The default is "T I T A N  S Y S T E M S  C O R P .", presumably because Intermetrics merged with the Titan Corporation in March of 2000.  The default title had previously been "I N T E R M E T R I C S", but was changed to this a couple of years after the merger.  Titan was later acquired by L-3 Communications, but I have no information as to whether the default was changed again.
LINECT (59, LC)
LINECT (59, LC) LINECT (59, LC)
Sets the maximum number of lines to be printed on any one page of the primary or unformatted secondary (see the LISTING2 option above) source listing.

This concept is trickier than it sounds, and if you actually count the number of lines on a page you may be confused into thinking the option doesn't work.  I think it probably does work, if keep in mind the various complications:
  • Double- or triple-spacing of lines via ANSI control characters (see LISTING2).
  • Overstruck lines.
  • Page headings and subheadings.
  • Expansions of macros or templates.
  • PASS1's desire to advance to a new page for each PROGRAM, PROCEDURE, FUNCTION, or COMPOOL.
PAGES (2500, P)
PAGES (2500, P) PAGES (10000, P)
Sets the maximum number of pages to be used for the primary compilation listing output by PASS1.
SYMBOLS (200, SYM)
SYMBOLS (200, SYM)
Specifies the initial size of the symbol table to be used by the compiler. As the value is exceeded, the system will automatically allocate more space for it within the available memory. Each symbol requires 53 bytes of storage plus 1 byte of storage for each character in the symbol name.

The default value is exceedingly optimistic, insofar as Space Shuttle flight software is concerned.
MACROSIZE (500, MS)
MACROSIZE (500, MS)
Specifies the initial number of characters allowed in the combined text of all REPLACE macro definitions. As the value is exceeded, the system will automatically allocate more space for it within the available memory.
LITSTRINGS (2000, LITS)
LITSTRINGS (2000, LITS)
Specifies the maximum total number of characters permitted in all character literals in the program to be compiled. (Note that the amount used for each character string in the program is 1 more than the number of characters in the string).
COMPUNIT (0, CU)
COMPUNIT (0, CU)
Specifies a compilation unit number, which is made available in the SDF and in the Block Data Areas, and which allows an analysis of active blocks in a core dump.
XREFSIZE (2000, XS)
XREFSIZE (2000, XS)
Specifies the initial number of cross reference table entries available to the compiler. As the value is exceeded, the system will automatically allocate more space for it within the available memory. Each entry requires four bytes of storage.
CARDTYPE ("", CT)
CARDTYPE ("", CT)
Allows statements with non-standard characters in the first column to be treated in the standard HAL/S fashion. A mapping of non-standard characters into standard types (E, M, S, C, D and blank) is specified by coding pairs of characters. E.g., if “CT=XCYM” were coded, any lines with X in the first column would be read as comments (C), while lines with Y in the first column would be read as regular main source code lines (M).
Aside:  If you experience difficulty using a literal blank as a replacement character, it may be worth trying to use M instead.
You may be puzzled why such a thing would be needed, or how it might be used.  Generally speaking, it is used only exceedingly rarely.  The best way to think of it may be as a way of implementing conditional compilation.  For code which you may or may not want to include in your program, and want a convenient way of enabling it or disabling it at compile time, you might put a special character in column 1, say "N".  At compile time, you could specify the option CT=NM if you wanted to include the code, or CT=NC if you wanted to comment it out.  This could be used for debugging, for compiling different configurations, as hints for software other than the compiler itself, etc.

Regarding the use of this option in compiling actual surviving Space Shuttle flight software, the answer as to how to do so (to the extent that it's known) is quite tricky.  The short answer is that we don't know for sure, but can provide a little bit of guidance on a version-by-version basis.
  • PASS OI-30.17:  We have no original HAL/S source code for this release, but merely reprinted compiler reports.  Consequently, we don't know what characters originally appeared in column 1 of the source-code punch-cards, and instead only know how the compiler replaced those characters according to whatever CARDTYPE options were in effect at compile-time.  In other words, as far as we can determine at this remove, only standard HAL/S characters (blank, 'C', and 'D') appeared in column 1.
  • PASS OI-34.06:  In addition to standard HAL/S characters (blank, 'C', 'D', and 'M'), the following characters are found in column 1:
    • 'F' — These appear in many source-code files.  The only sensible interpretation, upon analysis of possible replacement chracters as well as comparison to the corresponding files in PASS OI-30.17, is that 'F' is always replaced by 'C'.  I.e., the compiler option CARDTYPE=FC is always appropriate.  It has been suggested to me that 'F' is likely present as a marker for the purposes of some independent analysis by yet some other software not known to us.
    • 'R' — These appear in the module STRPDT, where comparison to the corresponding PASS OI-30.17 code tentatively suggests that 'R' should be replaced by a blank.  But see below.
  • BFS OI-34:  See the comments for PASS OI-30.17.

In addition to the relatively comprehensible column-1 characters mentioned above, there's the much-more-elaborate use of column 1 in module GKPMNV in flight software PASS OI-34.06, for which simple replacement of the character in column 1 does not suffice.  Here's a short excerpt from the source code of that module:

	.
.
.
 DECLARE GKP_ERR_MSG_REQ BOOLEAN AUTOMATIC INITIAL(OFF); 009900AA
DECLARE GKP_ITEM BIT(16) AUTOMATIC INITIAL (HEX'0000'); 010000AI
DECLARE GKP_ITEM_NO BIT(16) AUTOMATIC INITIAL (HEX'0000'); 010100AI
DECLARE GKP_CASE_ARRAY_NO INTEGER AUTOMATIC INITIAL (0); 010200AI
DECLARE GKP_ITEM_DATA_SC SCALAR DOUBLE AUTOMATIC INITIAL (0.0); 010300AI
DECLARE GKP_ITEM_DATA_INT INTEGER DOUBLE AUTOMATIC INITIAL (0.0);010400AI
RG13 DECLARE GKP_TGT_CASE ARRAY(19) INTEGER 010500AA
RG13 CONSTANT(3,1,1,1,1,6,6,6,4,4,7,8,9,10,11,5,2,2,2); 010600AA
OG2 DECLARE GKP_TGT_CASE ARRAY(20) INTEGER 010700AA
OG2 CONSTANT(3,1,1,1,1,6,6,6,4,4,7,0,0,0,0,5,2,2,2,8); 010800AA
AG1 DECLARE GKP_NON_TGT_CASE 010900AA
AG1 ARRAY(14) INTEGER CONSTANT(0,0,0,2,3,1,5,0,4,4,4,4,4,4); 011000AA
OG2 DECLARE GKP_NON_TGT_CASE 011100AA
OG2 ARRAY(14) INTEGER CONSTANT(0,0,0,2,3,1,0,0,4,4,4,4,4,4); 011200AA
NG3 DECLARE GKP_NON_TGT_CASE 011300AA
NG3 ARRAY(19) 011400AA
NG3 INTEGER CONSTANT(5,5,5,2,3,1,0,8,4,4,4,4,4,4,9,10,6,11,7); 011500AA
DECLARE GKP_GMBL_L_R_Y_COORD ARRAY(3) INTEGER CONSTANT(-67,-94,-121); 011600AA
.
.
.

But we're fortunate in this case, because the comments at the top of the source-code file do explain what's going on.  I quote the entire explanation:

C*******************************************************************    000100AA
C* THE SAME SOURCE MODULE, GKPMNV, IS USED FOR MANEUVER KIPS 000200AA
C* IN OPS 1,2 AND 3. 000300AA
C* 000400AA
C* IN GKPMNV: 000500AA
C* EXECUTABLE CODE UNIQUE TO OPS 1 HAS AN 'A' IN COL 1. 000600AA
C* INCLUDE CARDS UNIQUE TO OPS 1 HAVE AN 'F' IN COL 1. 000700AA
C* EXECUTABLE CODE UNIQUE TO OPS 2 HAS AN 'O' IN COL 1. 000800AA
C* INCLUDE CARDS UNIQUE TO OPS 2 HAVE A 'G' IN COL 1. 000900AA
C* EXECUTABLE CODE UNIQUE TO OPS 3 HAS AN 'N' IN COL 1. 001000AA
C* INCLUDE CARDS UNIQUE TO OPS 3 HAVE AN 'H' IN COL 1. 001100AA
C* EXECUTABLE CODE COMMON TO OPS 1&3 HAS AN 'R' IN COL 1.001200AA
C* INCLUDE CARDS COMMON TO ALL OPS HAVE A 'D' IN COL 1. 001250AG
C* 001300AA
C* FOR OPS 1, GKPMNV IS COMPILED WITH PARAMETER 001400AA
C* 'CARDTYPE=AMOCNCRMFDGCHC' IN THE HAL COMPILE CARD. 001500AA
C* THIS CREATES PROCEDURE GKD_ASC_MNVR_KIP BY TREATING 001600AA
C* AS COMMENTS SOURCE STATEMENTS HAVING 'R' OR 'O' IN COL 1. 001700AA
C* 001800AA
C* FOR OPS 2, 'CARDTYPE=ACOMNCRCFCGDHC' TO CREATE GKR_ORB_MNVR_KIP001900AA
C* 002000AA
C* FOR OPS 3, 'CARDTYPE=ACOCNMRMFCGCHD' TO CREATE GKG_MNVR_KIP. 002100AA
C* 002200AA
C* IN ADDITION, LINES UNIQUE TO A GIVEN OPS HAVE THE 002300AA
C* FOLLOWING SPECIFIC CODES AS THE FIRST 2 OR 3 CHARACTERS: 002400AA
C* 'G1' FOR OPS 1 UNIQUE LINES 002500AA
C* 'G2' FOR OPS 2 UNIQUE LINES 002600AA
C* 'G3' FOR OPS 3 UNIQUE LINES 002700AA
C* 'G13' FOR OPS 1&3 COMMON LINES 002800AA
C* ' ' FOR OPS 1,2&3 COMMON LINES (I.E. CODE COMMON TO ALL OPS002900AA
C* HAS NO SPECIAL CHARACTERS). 003000AA
C* 003100AA
C* THE VARIOUS CODES ARE REPLACE NAMES FOR BLANKS AND AT 003200AA
C* COMPILE TIME THEY HAVE NO EFFECT IN THE COMPILATION OTHER THAN 003300AA
C* IDENTIFYING THE OPS TO WHICH A STATEMENT BELONGS. 003400AA
C* 003500AA
C******************************************************************** 003600AA
REPLACE G1 BY " "; 003700AA
REPLACE G2 BY " "; 003800AA
REPLACE G3 BY " "; 003900AA
REPLACE G13 BY " "; 004000AA
C********************************************************************** 004100AA
Aside: Notice the implication that column 1 replacements via CARDTYPE are performed by the compiler prior to any macro expansions via REPLACE.
Important Note: One perhaps-unobvious lesson to take away from the above is that we cannot assume that it's okay to use the identical CARDTYPE option for all modules comprising any given release of the flight software.  Consider the 'F' character in column 1.  I mentioned earlier the inference that where 'F' appears in column in modules other than GKPMNV, it must always be replaced by 'C'.  And yet from the explanation specific to module GKPMNV, we see that depending on the overall runtime configuration, in GKPMNV it must sometimes be replaced 'C' and sometimes instead by 'D'.  Similarly, in module STRPDT we found that 'R' should be replaced by a blank (or 'M'), whereas in GKPMNV we find that it is instead replaced by 'C' in some configurations; although admittedly, in the case of STRPDT it's difficult to have as much confidence in my inferences, so possibly the replacement could vary by configuration there as well, even though undocumented.

Regarding these extra column-1 characters like 'F', 'A', and 'B', it's perhaps worth noting also that several flight-software modules have comments similar to this one we find in the module CPUSLS,
C********************************************************************** 000005AG
C************************ ******************* 000010AG
C THIS MODULE IS SET UP FOR THE SM PREPROCEESOR TO 000015AG
C GENERATE THIS COMPOOL FOR S2 ONLY OR S4 ONLY OR 000020AG
C BOTH OPS. 000025AG
C THIS MODULE MAY CONTAIN F,A AND B CARDS TO BE 000030AG
C USED BY THE PREPROCESSOR TO GENERATE THIS TABLE. 000035AG
C THE PROCEDURE ON HOW TO UPDATE THIS MODULE WILL BE 000040AI
C CONTAINED IN THE SAMS. 000045AG
C************************ ******************* 000050AG
C********************************************************************** 000055AG
which tells us that HAL/S source code was at least sometimes coded with the expectation of being preprocessed in some manner no longer possible for us now.
Aside:  Regarding the "SM PREPROCEESOR" mentioned in the program comments quoted above, there are several documents in our library pertaining to HAL/SM, which is described as being a dialect of the HAL/S language appropriate for something called the Concept Verification Test (CVT) environment rather than the Space Shuttle itself.  The SM preprocessor is said to "convert HAL/SM source language modules into HAL/S source language modules, perform minimal syntax verification, and provide various support features which cannot be conveniently or adequately performed by the HAL/S-360 Compiler."  See also:
LABELSIZE (1200, LBLS)
LABELSIZE (1200, LBLS)
Specifies the initial number of labels which can be recognized by the compiler. As the value is exceeded, the system will automatically allocate more space for it within the available memory.  "Labels" in HAL/S, recall, are things like
MY_LABEL: ...
that can be used as the targets of GOTO statements.  A name of a PROGRAM, PROCEDURE, FUNCTION, or COMPOOL may also technically be a "label", but it's TBD as to whether they're included in this count or not.
DSR (1)
DSR (1)
Specifies the value to be used for the data sector register in the right hand halfword of the R2 operand of the MVH instruction. The compiler will use this value explicitly when it is not possible to use a standard z-type address constant in which the DSR field is filled in by the link editor.

That's a direct quote from the HAL/S-FC User's Manual, but I personally haven't much of a clue as to what it may mean, other than that it relates to AP-101S assembly language, and I guess, to the linking process for it.
BLOCKSUM (400, BS)
BLOCKSUM (400, BS)
Specifies the initial size of the PASS1 internal compiler table used for collecting information for printing block summaries. As this value is exceeded, the system will automatically allocate more space for it within the available memory.
MFID ("")


Allows specification of the Major Function ID.  Implemented in the PASS version of the compiler only (versus the BFS version).

OLDTPL ("", 0)
(No longer a valid option, even though accepted by the compiler.  It involves the record length used in template files, which is now fixed at 80.)


LIST (1, L) (Do not confuse with the LIST option for PASS1.  Although PASS4 does accept the type-2 LIST option, it does not appear to me that it uses the value of the option in any way.)

Debugging-Aid Options

In addition to compiler options originally supplied by JCL, but now supplied by command-line switches as described in the preceding section, there are also compiler options which can be supplied within the HAL/S source code itself.  These typically (but not always) differ from the command-line options in that they tend to take effect at the position in the HAL/S source code at which the compiler encounters them.  As the title of this section implies, such options are often (but not always) for the purpose of debugging the compiler itself. 

Such options are inserted into the code via DEBUG compiler directives aligned with column 1 of the source code, and you can see examples of them (highlighted in green) in our little sample HELLO.hal program:

DEBUG ¢D¢E¢F

HELLO: PROGRAM;
DECLARE I INTEGER;
DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY');
DECLARE INTEGER, J;
REPLACE PRINTER BY "6";
WRITE(PRINTER) 'THE BEGINNING';
DO FOR I = 1 TO 5;
WRITE(PRINTER) I, 'HELLO, WORLD!';
DO FOR J = 2 TO 8 BY 2;
WRITE(PRINTER) J, MY_NAME, 'SAYS ISN''T THIS FUN?';
END;
END;
WRITE(6) 'THE END';
CLOSE HELLO;

This example turns on debugging-aid options D, E, and F.

Section 2.2.7 ("Debugging Aids") of the HAL/S-FC & HAL/S-360 Compiler System Program Description describes many such options, although as you've probably come to expect, by no means all of them.

Debugging-aid options are of two general types:

  1. Options of the form ¢T, where T is a letter (A-F), are used mainly (but not entirely) for PASS1.  They can:
  2. Options of the form H(N), where N is a decimal number (0-255), are used in later compiler passes.  I haven't put any of them in our HELLO.hal example above, but they too are specified within DEBUG compiler-directives.  Only one H(N) option is in effect at any given time.  Number N=0 has no effect at all, whereas numbers N=1-127 affect FLO, OPT, and/or AUX, while N=128-255 affects PASS2.  PASS1 simply inserts N into a tag field in the next HALMAT intermediate-language SMRK instruction generated — which is at the beginning of the next HAL/S statement —, and then resets the N=0 internally.  Yes, I know it's not obvious what that means, but the point is that if multiple H(N) switches were encountered, then only the final one could take effect (at the beginning of the next statement).

Here's a table of the debugging-aid options that I'm aware of, usually with samples of how the options affect the reports output by the various compiler passes.  You won't have to look too long to realize that any of these options, if they remain enabled, can increase the size of output reports dramatically.  And if options are combined, the increase can be astounding.  So rather than just enabling options at the beginning of the HAL/S program and leaving them enabled as I do in many of these examples for illustrative purposes, a more-normal usage would be to enable an option just prior to some place in the source code just prior to where a problem has been observed, and to disable them after the problematic section of code.

Aid
PASS1
OPT
AUX
PASS2
Description
¢0 Yes
No
No No Interlists HALMAT intermediate language with HAL/S source code in PASS1's output report.  Here's an excerpt for HELLO.hal, with changes highlighted in green, showing the effect of this option:

  1 M| HELLO: |HELLO
1 M| PROGRAM; |HELLO
HALMAT LINE 4: 4( 1),N, 0
: 1( 0) 0,1
2 M| DECLARE I INTEGER; |HELLO
HALMAT LINE 6: 4( 1),N, 0
: 2( 0) 0,0
HALMAT LINE 8: 841( 2),0, 2
: 3(SYT) 0,0
: 2(LIT) 0,0
3 M| DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); |HELLO
HALMAT LINE 11: 4( 1),N, 0
: 3( 0) 0,0
4 M| DECLARE INTEGER, J; |HELLO
HALMAT LINE 13: 4( 1),N, 0
: 4( 0) 0,0
5 M| REPLACE PRINTER BY "6"; |HELLO
HALMAT LINE 15: 4( 1),N, 0
: 5( 0) 0,0
HALMAT LINE 17: 31( 0),N, 1
HALMAT LINE 18: 25( 1),N, 0
: 2(IMD) 0,0
HALMAT LINE 20: 27( 1),N, 0
: 4(LIT) 0,0
HALMAT LINE 22: 21( 1),0, 0
: 6(IMD) 0,0
HALMAT LINE 24: 26( 0),0, 0
6 M| WRITE(PRINTER) 'THE BEGINNING'; |HELLO
^^^^^^^

¢1 Yes No No No Stop processing at the end of Phase 1.  Originally this meant that processing would stop after PASS1 had completed, but for the modern compiler the passes don't directly chain together, so this option no longer really halts processing.  However, it does affect the messages printed when PASS1 terminates.
¢2 No No No Yes Stop processing at the end of Phase 2.  Like ¢1 (see above), except for PASS2 rather than PASS1.
¢3 Yes No No No Turns on the Phase 1 identifier trace.  This trace info shows up in PASS1's output report.  Here's a short excerpt of changes (highlighted in green) to the output listing, if I add ¢3 to the DEBUG compiler directive at the top of HELLO.hal:

 HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 10, 2024 20:5:9.54 PAGE 3
STMT SOURCE CURRENT SCOPE

1 M| HELLO: |HELLO
1 M| PROGRAM; |HELLO
I : TOKEN = <IDENTIFIER>, IMPLIED_TYPE = 0, SYT_INDEX = 2, CONTEXT = 5
2 M| DECLARE I INTEGER; |HELLO
MY_NAME : TOKEN = <IDENTIFIER>, IMPLIED_TYPE = 0, SYT_INDEX = 3, CONTEXT = 5
3 M| DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); |HELLO
J : TOKEN = <IDENTIFIER>, IMPLIED_TYPE = 0, SYT_INDEX = 4, CONTEXT = 5
4 M| DECLARE INTEGER, J; |HELLO
PRINTER : TOKEN = <IDENTIFIER>, IMPLIED_TYPE = 0, SYT_INDEX = 5, CONTEXT = 10
5 M| REPLACE PRINTER BY "6"; |HELLO
PRINTER : TOKEN = -1, IMPLIED_TYPE = 0, SYT_INDEX = 5, CONTEXT = 0
AT 3 NEXT_CHAR=246 MACRO_EXPAN_LEVEL=1 MACRO_TEXT(1)=239 PARM_REPLACE_PTR(0)=0
AT 4 NEXT_CHAR=64 MACRO_EXPAN_LEVEL=1 MACRO_TEXT(1)=239 PARM_REPLACE_PTR(0)=0
AT 5 NEXT_CHAR=93 MACRO_EXPAN_LEVEL=0 MACRO_TEXT(-1)=0 PARM_REPLACE_PTR(0)=0
6 M| WRITE(PRINTER) 'THE BEGINNING'; |HELLO
^^^^^^^
I : TOKEN = <ARITH ID>, IMPLIED_TYPE = 0, SYT_INDEX = 2, CONTEXT = 0

¢4 Yes No No No Turns on the Phase 1 token trace.  This is a bit tricky to explain in a meaningful way, so I'll just say that the first operation of any compiler or interpreter tends to be to "scan" the input source code and convert it into a series of "tokens"; subsequent action by the compiler merely analyzes the sequence of tokens rather than the raw source code itself.  The token trace gives a running account of the tokens the scanner identifies.  Here's an excerpt from PASS1's output report showing the effect of the option.  It's helpful to know that BCD is the token just identified (shown as a string) and that NEXT_CHAR is the EBCDIC code (in decimal) of the not-yet-analyzed, non-blank character following the current token.

 1 M| HELLO: |HELLO
1 M| PROGRAM; |HELLO
SCANNER: 103, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: DECLARE, NEXT_CHAR: 201
SCANNER: 131, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: I, NEXT_CHAR: 201
SCANNER: 105, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: INTEGER, NEXT_CHAR: 94
SCANNER: 10, NUMBER_VALUE: 00, VALUE: 0, NEXT_CHAR: 196
2 M| DECLARE I INTEGER; |HELLO
SCANNER: 103, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: DECLARE, NEXT_CHAR: 212
SCANNER: 131, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: MY_NAME, NEXT_CHAR: 195
SCANNER: 118, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: CHARACTER, NEXT_CHAR: 77
SCANNER: 3, NUMBER_VALUE: 00, VALUE: 0, NEXT_CHAR: 242
SCANNER: 136, NUMBER_VALUE: 421400000, VALUE: 20, CURRENT BCD: 20, NEXT_CHAR: 93
SCANNER: 9, NUMBER_VALUE: 00, VALUE: 0, NEXT_CHAR: 201
SCANNER: 104, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: INITIAL, NEXT_CHAR: 77
SCANNER: 3, NUMBER_VALUE: 00, VALUE: 0, NEXT_CHAR: 125
SCANNER: 132, NUMBER_VALUE: 00, VALUE: 10, CURRENT BCD: RON BURKEY, NEXT_CHAR: 93
SCANNER: 9, NUMBER_VALUE: 00, VALUE: 0, NEXT_CHAR: 94
SCANNER: 10, NUMBER_VALUE: 00, VALUE: 0, NEXT_CHAR: 196
3 M| DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); |HELLO
SCANNER: 103, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: DECLARE, NEXT_CHAR: 201
SCANNER: 105, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: INTEGER, NEXT_CHAR: 107
SCANNER: 14, NUMBER_VALUE: 00, VALUE: 0, NEXT_CHAR: 209
SCANNER: 131, NUMBER_VALUE: 00, VALUE: 0, CURRENT BCD: J, NEXT_CHAR: 94
SCANNER: 10, NUMBER_VALUE: 00, VALUE: 0, NEXT_CHAR: 217
4 M| DECLARE INTEGER, J; |HELLO

¢5 No No No Yes This option adds HALMAT intermediate-language to PASS2's output report.  Recall that optimization (FLO, OPT, and AUX) may have altered the HALMAT so that it's no longer quite the same as what was output by PASS1 (see ¢0 above).
PAGE 1


HAL/S COMPILER PHASE 2 -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:39:23.00

HAL/S PHASE 2 ENTERED AUGUST 11, 2024. CLOCK TIME = 5:39:17.69

HALMAT: 005( 1), 0,0:0.0
HALMAT: 02B( 1), 0,0:0.2
1( 1), 0,0 :0.3
HALMAT: 004( 1), 0,0:0.4
1( 0), 0,1 :0.5
HALMAT: 004( 1), 0,0:0.6
2( 0), 0,0 :0.7
HALMAT: 841( 2), 2,0:0.8
3( 1), 0,0 :0.9
2( 5), 0,0 :0.10
HALMAT: 004( 1), 0,0:0.11
3( 0), 0,0 :0.12
HALMAT: 004( 1), 0,0:0.13
4( 0), 0,0 :0.14
HALMAT: 004( 1), 0,0:0.15
5( 0), 0,0 :0.16
HALMAT: 031( 0), 1,0:0.17
HALMAT: 025( 1), 0,0:0.18
2( 6), 0,0 :0.19
6( 6), 0,0 :0.23
HALMAT: 027( 1), 0,0:0.20
4( 5), 2,0 :0.21
HALMAT: 021( 1), 0,0:0.22
HALMAT: 026( 0), 0,0:0.24
HALMAT: 004( 1), 0,0:0.25
6( 0), 0,1 :0.26
HALMAT: 010( 4), 1,0:0.27
2( 1), 0,0 :0.29
AUX: 29 1 2(1) 0,0
1( 2), 0,1 :0.28
6( 5), 0,0 :0.31
5( 5), 0,0 :0.30

¢6 No No No Yes Adds assembly language to PASS2's output report:
PAGE 1


HAL/S COMPILER PHASE 2 -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:39:23.00

HAL/S PHASE 2 ENTERED AUGUST 11, 2024. CLOCK TIME = 5:47:27.31

I (1) 000002 002(1) 0
J (1) 000003 003(1) 0
MY_NAME (11) 000004 004(1) 0
*** HAL/S STATEMENT 1
000000:HELLO EQU *
000000: LHI 0,@0HELLO
000002: LHI 1,
000004: STH 1,5(0,0)
000005: IAL 0,0+DELTA.HELLO
000007: LA 3,0(0,9)
000009: STH 3,9(0,0)
*** HAL/S STATEMENT 2
*** HAL/S STATEMENT 3
*** HAL/S STATEMENT 4
*** HAL/S STATEMENT 5
*** HAL/S STATEMENT 6
00000A: LFXI 6,8
00000B: LFXI 5,5
00000C: SCAL 0,#QIOINIT
00000E: LA 2,=C'THE BEGINNING'
000010: SCAL 0,#QCOUT

¢7 Yes No No No Immediately prints a symbol table and then disables the option.  In the following excerpt from PASS1's output report, I've inserted this option just prior to HAL/S statement 7.  (Recall that the characters '`' and '¢' are equivalent to the compiler, but that the compiler internally always uses '`'.)
⋮
   5 M|   REPLACE PRINTER BY "6";                                                                           |HELLO
6 M| WRITE(PRINTER) 'THE BEGINNING'; |HELLO
^^^^^^^

D| EBUG `7 |HELLO

S Y M B O L & C R O S S R E F E R E N C E T A B L E L I S T I N G :

(CROSS REFERENCE FLAG KEY: 4 = ASSIGNMENT, 2 = REFERENCE, 1 = SUBSCRIPT USE, 0 = DEFINITION)

DCL NAME TYPE ATTRIBUTES & CROSS REFERENCE

1 HELLO PROGRAM FLAGS=20040, NEST=0, SCOPE=1, PTR=2, LENGTH=0, LINK1=-1, LINK2=0, SYT_NO=1,
ARRAY=-300, ADDR=0, CLASS=2, TYPE=73
2 I INTEGER SINGLE, ALIGNED, STATIC, FLAGS=800208, NEST=1, SCOPE=1, PTR=0, LENGTH=0,
LINK1=0, LINK2=0, SYT_NO=2, ARRAY=0, ADDR=0, CLASS=1, TYPE=6
3 MY_NAME CHARACTER(20) ALIGNED, STATIC, INITIAL, FLAGS=A08, NEST=1, SCOPE=1, PTR=0, LENGTH=20, LINK1=0,
LINK2=0, SYT_NO=3, ARRAY=0, ADDR=0, CLASS=1, TYPE=2
4 J INTEGER SINGLE, ALIGNED, STATIC, FLAGS=800208, NEST=1, SCOPE=1, PTR=0, LENGTH=0,
LINK1=0, LINK2=0, SYT_NO=4, ARRAY=0, ADDR=0, CLASS=1, TYPE=6
5 PRINTER REPLACE MACRO FLAGS=0, NEST=1, SCOPE=1, PTR=0, LENGTH=0, LINK1=0, LINK2=0, SYT_NO=5, ARRAY=0,
ADDR=0, CLASS=6, TYPE=0, MACRO TEXT="6"


7 M| DO FOR I = 1 TO 5; |HELLO
8 M| 1 WRITE(PRINTER) I, 'HELLO, WORLD!'; |HELLO
^^^^^^^
¢8 Yes No No No Print a Phase 1 production trace.  Here, a "production" is a rule in the Backus-Naur Form (BNF) of the grammar of the HAL/S language.  For identification purposes, each such rule is given a unique number, and all of the production numbers are related to the BNF rules in comments in the compiler's source code.  For example, production number 1 is the <COMPILATION> rule, number 2 is the <COMPILE LIST> rule, and so on:
⋮
 /*      1   <COMPILATION> ::= <COMPILE LIST> _|_                     */        00000750
00000800
/* 2 <COMPILE LIST> ::= <BLOCK DEFINITION> */ 00000850
/* 3 | <COMPILE LIST> <BLOCK DEFINITION> */ 00000900
00000950
/* 4 <ARITH EXP> ::= <TERM> */ 00001000
/* 5 | + <TERM> */ 00001050
/* 6 | - <TERM> */ 00001100
/* 7 | <ARITH EXP> + <TERM> */ 00001150
/* 8 | <ARITH EXP> - <TERM> */ 00001200
What the ¢8 option does is to provide an inline trace to the PASS1 output file of each BNF rule processed:

D| EBUG `8`D`E`F |
->->->->->->PRODUCTION NUMBER 308
->->->->->->PRODUCTION NUMBER 309
->->->->->->PRODUCTION NUMBER 311
->->->->->->PRODUCTION NUMBER 305
->->->->->->PRODUCTION NUMBER 302

------------------------------------------------------------------------------------------------------------------------------------------------------
HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 11, 2024 6:17:20.50 PAGE 3
STMT SOURCE CURRENT SCOPE

1 M| HELLO: |HELLO
1 M| PROGRAM; |HELLO
->->->->->->PRODUCTION NUMBER 362
->->->->->->PRODUCTION NUMBER 389
->->->->->->PRODUCTION NUMBER 386
->->->->->->PRODUCTION NUMBER 380
->->->->->->PRODUCTION NUMBER 374
->->->->->->PRODUCTION NUMBER 366
->->->->->->PRODUCTION NUMBER 361
->->->->->->PRODUCTION NUMBER 346
->->->->->->PRODUCTION NUMBER 344
->->->->->->PRODUCTION NUMBER 343
2 M| DECLARE I INTEGER; |HELLO
->->->->->->PRODUCTION NUMBER 333
->->->->->->PRODUCTION NUMBER 349
->->->->->->PRODUCTION NUMBER 362

¢9 No No No Yes
Includes a stack trace in PASS2's output report.  And misspells "stack", which seems like a real accomplishment.
PAGE 1


HAL/S COMPILER PHASE 2 -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:39:23.00

HAL/S PHASE 2 ENTERED AUGUST 11, 2024. CLOCK TIME = 6:21:39.17

GOT STAK 1
RET STACK 1
GOT STAK 1
GOT STAK 2
RET STACK 2

RET STACK 2
RET STACK 1
GOT STAK 1
GOT STAK 2
RET STACK 2
RET STACK 1


STACK NAME


------------------------------------------------------------------------------------------------------------------------------------------------------
PAGE 3

20 HELLO


OPTIONAL TABLE SIZES

NAME REQUESTED USED
^^^^ ^^^^^^^^^ ^^^^

LITSTRINGS 2000 68
LABELSIZE 1200 8
¢A Yes No No No Immediately terminates PASS1.
¢B Yes No No No In the PASS1 output report, print HALMAT intermediate language after each "block".  I'm not sure what a "block" is, but I'm sure that a HAL/S PROGRAM, PROCEDURE, or FUNCTION must certainly be one.  Note that the HALMAT statements may be reordered versus those inlined with the HAL/S source code by the ¢0 option (see above).

1 M| HELLO: |HELLO
1 M| PROGRAM; |HELLO
2 M| DECLARE I INTEGER; |HELLO
3 M| DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); |HELLO
4 M| DECLARE INTEGER, J; |HELLO
5 M| REPLACE PRINTER BY "6"; |HELLO
6 M| WRITE(PRINTER) 'THE BEGINNING'; |HELLO
^^^^^^^
7 M| DO FOR I = 1 TO 5; |HELLO
8 M| 1 WRITE(PRINTER) I, 'HELLO, WORLD!'; |HELLO
^^^^^^^
9 M| 1 DO FOR J = 2 TO 8 BY 2; |HELLO

E| , |
10 M| 2 WRITE(PRINTER) J, MY_NAME, 'SAYS ISN''T THIS FUN?'; |HELLO
^^^^^^^
11 M| 1 END; |ST#9
12 M| END; |ST#7
13 M| WRITE(6) 'THE END'; |HELLO
14 M| CLOSE HELLO; |HELLO

------------------------------------------------------------------------------------------------------------------------------------------------------
HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 11, 2024 6:29:48.84 PAGE 4
STMT SOURCE CURRENT SCOPE


*** HALMAT BLOCK 0 ***


HALMAT LINE 0: 5( 1),0, 0
: 87( 0) 0,0
HALMAT LINE 2: 2B( 1),0, 0
: 1(SYT) 0,0
HALMAT LINE 4: 4( 1),N, 0
: 1( 0) 0,1
HALMAT LINE 6: 4( 1),N, 0
: 2( 0) 0,0
HALMAT LINE 8: 841( 2),0, 2
: 3(SYT) 0,0
: 2(LIT) 0,0
HALMAT LINE 11: 4( 1),N, 0
: 3( 0) 0,0

¢C Yes No No No Print Phase 1 state trace.  The compiler is a kind of state machine, with each state having a unique identifying number.  However, the state transitions are table-driven, with both the state numbering and the state-tables having been computer generated by an automated system based on the book A Compiler Generator by McKeeman et al.  The point of that techno-babble explanation is that the compiler's "states" are extremely human-unfriendly, and indeed almost uninterpretable without computer assistance, so it's unclear how to make use of any knowledge about them.  (Perhaps that's my own ignorance getting the better of me, so I'd be interested to hear any explanation of how the state trace might be helpful.)
⋮
     D| EBUG `C                                                                                             |
COMP: STATE=1 I=0 J=0
COMP: STATE=138 I=2 J=0
COMP: STATE=1118 I=251 J=0
COMP: STATE=655 I=688 J=1
COMP: STATE=1119 I=859 J=1
COMP: STATE=394 I=701 J=1
COMP: STATE=1121 I=1079 J=1
COMP: STATE=647 I=702 J=1
COMP: STATE=1115 I=825 J=1
COMP: STATE=391 I=687 J=1
COMP: STATE=1112 I=1073 J=1

------------------------------------------------------------------------------------------------------------------------------------------------------
HAL/S REL32V0 T I T A N S Y S T E M S C O R P . AUGUST 11, 2024 6:35:35.36 PAGE 3
STMT SOURCE CURRENT SCOPE

1 M| HELLO: |HELLO
1 M| PROGRAM; |HELLO
COMP: STATE=618 I=686 J=1
COMP: STATE=345 I=706 J=1
COMP: STATE=144 I=901 J=1
COMP: STATE=538 I=283 J=1
COMP: STATE=1172 I=375 J=1
¢D Yes No No No Documentation describes this option as "Turn on standard Phase 1 listing".  The "standard source listing" is the inclusion of the HAL/S source code in PASS1's output report that has been ubiquitous in all of the PASS1 reports we've seen so far.  However, in practice ¢D operates in an unexpected way.  Inclusion of the standard source listing is by default initially enabled, but in the table of ¢T options is (like all ¢T options) initially marked as disabled.  Therefore, the first time ¢D is encountered, inclusion of the standard output listing simply remains enabled.  Subsequent occurrences of ¢D will then properly toggle it.  To avoid confusion, it's best to always use ¢D+ or ¢D-, rather than simply expecting ¢D to produce the desired result.  I'd regard this as a bug in the original compiler.
¢E Yes No No No This adds a table of numeric and string literals to PASS1's output report.  Numbers, even if integers rather than floating-point, are printed as hexadecimal representations of double-precision IBM hexadecimal floating-point format.  For example, the integer literal 20 will be printed as 4214000000000000.  As obtuse as that seems at first glance, it's actually useful information:  The compiler communicates the values of literals from one compiler pass to the next in a file (the "literal file"), and the literal file does use the IBM hex format for all numbers.  Thus knowing the IBM hex values is exactly what's needed for interpreting the literal file.  (See the next section for more info about files produced by the compiler.)
⋮
S Y M B O L  &  C R O S S   R E F E R E N C E   T A B L E   L I S T I N G :

(CROSS REFERENCE FLAG KEY: 4 = ASSIGNMENT, 2 = REFERENCE, 1 = SUBSCRIPT USE, 0 = DEFINITION)

DCL NAME TYPE ATTRIBUTES & CROSS REFERENCE

1 HELLO PROGRAM XREF: 0 0001
2 I INTEGER SINGLE, ALIGNED, STATIC XREF: 0 0002 4 0007 2 0008
4 J INTEGER SINGLE, ALIGNED, STATIC XREF: 0 0004 4 0009 2 0010
3 MY_NAME CHARACTER(20) ALIGNED, STATIC, INITIAL XREF: 0 0003 2 0010
5 PRINTER REPLACE MACRO MACRO TEXT="6" XREF: 0 0005 2 0006 2 0008 2 0010



L I T E R A L T A B L E D U M P:

LOC TYPE LITERAL

1 ARITH 4214000000000000
2 CHAR RON BURKEY
3 ARITH 4160000000000000
4 CHAR THE BEGINNING
5 ARITH 4110000000000000
6 ARITH 4150000000000000
7 ARITH 4160000000000000
8 CHAR HELLO, WORLD!
9 ARITH 4120000000000000
10 ARITH 4180000000000000
11 ARITH 4120000000000000
12 ARITH 4160000000000000
13 CHAR SAYS ISN'T THIS FUN?
14 ARITH 4160000000000000
15 CHAR THE END
¢F Yes No No No This adds some extra info to the symbol-table listing provided in PASS1's output report.
⋮
S Y M B O L  &  C R O S S   R E F E R E N C E   T A B L E   L I S T I N G :

(CROSS REFERENCE FLAG KEY: 4 = ASSIGNMENT, 2 = REFERENCE, 1 = SUBSCRIPT USE, 0 = DEFINITION)

DCL NAME TYPE ATTRIBUTES & CROSS REFERENCE

1 HELLO PROGRAM FLAGS=20040, NEST=0, SCOPE=1, PTR=2, LENGTH=0, LINK1=-1, LINK2=0, SYT_NO=1,
ARRAY=-8192, ADDR=0, CLASS=2, TYPE=73
XREF: 0 0001
2 I INTEGER SINGLE, ALIGNED, STATIC, FLAGS=808208, NEST=1, SCOPE=1, PTR=0, LENGTH=0,
LINK1=0, LINK2=0, SYT_NO=2, ARRAY=0, ADDR=0, CLASS=1, TYPE=6
XREF: 0 0002
4 0007 2 0008
3 MY_NAME CHARACTER(20) ALIGNED, STATIC, INITIAL, FLAGS=8A08, NEST=1, SCOPE=1, PTR=0, LENGTH=20,
LINK1=0, LINK2=0, SYT_NO=3, ARRAY=0, ADDR=0, CLASS=1, TYPE=2
XREF: 0 0003
2 0010
4 J INTEGER SINGLE, ALIGNED, STATIC, FLAGS=808208, NEST=1, SCOPE=1, PTR=0, LENGTH=0,
LINK1=0, LINK2=0, SYT_NO=4, ARRAY=0, ADDR=0, CLASS=1, TYPE=6
XREF: 0 0004
4 0009 2 0010
5 PRINTER REPLACE MACRO FLAGS=C000, NEST=1, SCOPE=1, PTR=0, LENGTH=0, LINK1=0, LINK2=0, SYT_NO=5,
ARRAY=0, ADDR=0, CLASS=6, TYPE=0,
MACRO TEXT="6" XREF: 0 0005 2 0006 2 0008
2 0010
¢G No
No
No
No
(The compiler accepts option ¢G, but it is apparently not used for anything.)
H(1)
No
TBD
TBD
No
Documentation describes this as "Optimizer off until next such statement encountered. No CSE's recognized across the pair of DEBUG's".  A more-understandable explanation is TBD.
H(2)
No
TBD
TBD
No
Documentation describes this as "Same as above, but CSE's may be recognized across the pair".  A more-understandable explanation is TBD.
H(3)
No
TBD
TBD
No
Documentation describes this as "WATCH status changed", which appears to mean that printing of HALMAT changes is toggled on or off.  Whether this option is available in HAL/S-FC versus whether it is confined to HAL/S-360 is TBD.  A more-understandable explanation is TBD.
H(5)
No
Yes
No
No
Toggles tracing that's similar (but apparently not identical) to that of the X5 compiler option.  See X5 in the preceding section for a sample.
H(6)
No
Yes No
No
The H(6) option embeds HALMAT into OPT's output report.  Put another way, it does for OPT what ¢5 does for PASS2.  (See ¢5 above.)
H(7)
No
TBD
TBD
No
Documentation describes this as "HALMAT_BLAB status changed".  A more-understandable explanation is TBD.  I do not observe any effect on the output reports.
H(64)
No
TBD
TBD
No
Documentation describes this as "Set VALIDITY TRACE status changed".  A more-understandable explanation is TBD.  I do not observe any effect on the output reports.
H(200)
No No No Yes In PASS2's output report, disables HALMAT (¢5-), assembler code (¢6-), and stack trace (¢9-)
H(201)
No No No Yes In PASS2's output report, enables HALMAT (¢5+), assembler code (¢6+), and stack trace (¢9+)
H(202)
No No No Yes In PASS2's output report, disables HALMAT (¢5-) and assembler code (¢6-)
H(203)
No No No Yes In PASS2's output report, enables HALMAT (¢5+) and assembler code (¢6+)
H(204)
No No No Yes In PASS2's output report, toggles the register trace.  There's an excerpt below of PASS2's output report from HELLO.hal showing the effect.  Presumably it would be more-meaningful intermixed with HALMAT or assembly code, but in the interest of space I haven't done that.  While I cannot give you a full explanation of how to read the trace, I'd venture the following guesses:
  • R indicates a particular AP-101S CPU register.
  • NAME tells you the identifier of the variable stored in it.
  • VAR gives you the "DCL" number of the variable in the symbol table in PASS1's output report
  • TYP indicates the datatype of the variable stored in the register.  2 is CHARACTER, 5 is SCALAR, 6 is INTEGER.  (The complete list of numeric codes for datatypes can be found beginning at punchcard 00150900 in HAL/S-FC source-code file PASS1.PROCS/##DRIVER.xpl, though since most of the datatypes won't fit in a single CPU register, not all of the codes are applicable to the register trace.)
PAGE 1


HAL/S COMPILER PHASE 2 -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:39:23.00

HAL/S PHASE 2 ENTERED AUGUST 11, 2024. CLOCK TIME = 9:34:6.06

R USE LIN CTN TYP VAR XR XS XC CONST XCON MULT VR2 NAME
5 1 0 5 6 0 0 0 0 3 0 0 0
6 1 0 5 6 0 0 0 0 6 0 0 0
R USE LIN CTN TYP VAR XR XS XC CONST XCON MULT VR2 NAME
7 1 0 1 6 2 0 0 0 0 0 0 0 I
R USE LIN CTN TYP VAR XR XS XC CONST XCON MULT VR2 NAME
5 1 0 1 6 2 0 0 0 0 0 0 0 I
6 1 0 5 6 0 0 0 0 6 0 0 0
7 1 0 1 6 2 0 0 0 0 0 0 0 I
R USE LIN CTN TYP VAR XR XS XC CONST XCON MULT VR2 NAME
4 1 0 1 6 4 0 0 0 0 0 0 0 J
R USE LIN CTN TYP VAR XR XS XC CONST XCON MULT VR2 NAME
4 1 0 1 6 4 0 0 0 0 0 0 0 J
5 1 0 1 6 4 0 0 0 0 0 0 0 J
6 1 0 5 6 0 0 0 0 6 0 0 0
R USE LIN CTN TYP VAR XR XS XC CONST XCON MULT VR2 NAME
5 1 0 5 6 4 0 0 0 3 0 0 0
6 1 0 5 6 0 0 0 0 6 0 0 0
R USE LIN CTN TYP VAR XR XS XC CONST XCON MULT VR2 NAME
4 1 -1 10 6 4 0 0 0 0 0 0 0


STACK NAME
20 HELLO
H(205)
No No No Yes In PASS2's output report, toggles HALMAT (¢5).
H(206)
No No No Yes In PASS2's output report, toggles assembler code (¢6).
H(207)
No No No Yes In PASS2's output report, toggles binary code. This is just what it sounds like:
PAGE 1


HAL/S COMPILER PHASE 2 -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:39:23.00

HAL/S PHASE 2 ENTERED AUGUST 11, 2024. CLOCK TIME = 9:53:49.38

000000: 49, 0001
000000: 38, 0002
000000: 80000000
000000: 0, 0000
000001: 0, 0000
000002: 43, 1001
000002: 43, 4003
000002: 55, 0001
000002: 00000700
000004: 0, 0000
000005: 0, 0000
000000: 38, 0003
H(208)
No No No Yes In PASS2's output report, toggles subscript trace. Our simple HELLO.hal test program doesn't actually have any array variables in it, so a subscript trace shows nothing at all.  Let's instead use the EXAMPLE_2 program from p. 6-6 of Ryer's "Programming in HAL/S", which looks like so:
  EXAMPLE_2:
PROGRAM;
DECLARE GYRO_INPUT ARRAY(4, 3) INTEGER
INITIAL(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
DECLARE ATT_RATE ARRAY(4, 3) SCALAR;
DECLARE SCALE ARRAY(3) CONSTANT(.013, .026, .013);
DECLARE BIAS SCALAR INITIAL(57.296);
DO FOR TEMPORARY I = 1 TO 4;
DO FOR TEMPORARY J = 1 TO 3;
M ATT_RATE = GYRO_INPUT SCALE + BIAS;
S I,J I,J J

END;
END;
WRITE(6) ATT_RATE;
CLOSE EXAMPLE_2;

Compiling this with the H(208) option enabled gives the following PASS2 output report:
PAGE 1


HAL/S COMPILER PHASE 2 -- VERSION OF AUGUST 9, 2024. CLOCK TIME = 12:39:23.00

HAL/S PHASE 2 ENTERED AUGUST 11, 2024. CLOCK TIME = 10:7:31.25

INX_CON=0, SUB#=1
INX_CON=0, SUB#=2
INX_CON=0, SUB#=2
INX_CON=0, SIZE/ROW=1, COLUMN=0
INX_CON=0, SUB#=1
INX_CON=0, SUB#=2
INX_CON=0, SUB#=2
INX_CON=0, SIZE/ROW=1, COLUMN=0
INX_CON=0, SUB#=1
INX_CON=0, SUB#=1
INX_CON=0, SIZE/ROW=1, COLUMN=0


STACK NAME
20 EXAMPLE_2


OPTIONAL TABLE SIZES

NAME REQUESTED USED
^^^^ ^^^^^^^^^ ^^^^

LITSTRINGS 2000 0
LABELSIZE 1200 10


46 HALMAT OPERATORS CONVERTED

45 INSTRUCTIONS GENERATED

68 HALFWORDS OF PROGRAM, 54 HALFWORDS OF DATA.

MAX. OPERAND STACK SIZE =10
END OPERAND STACK SIZE =0
MAX. STORAGE DESCRIPTOR STACK SIZE =3
END STORAGE DESCRIPTOR STACK SIZE =0
NUMBER OF MINOR COMPACTIFIES =0
NUMBER OF MAJOR COMPACTIFIES =0
NUMBER OF REALLOCATIONS =5
FREE STRING AREA =16623296

END OF HAL/S PHASE 2 AUGUST 11, 2024. CLOCK TIME = 10:7:31.25
TOTAL CPU TIME FOR PHASE 2 0:0:0.01
CPU TIME FOR PHASE 2 SET UP 0:0:0.01
CPU TIME FOR PHASE 2 GENERATION 0:0:0.00
CPU TIME FOR PHASE 2 CLEAN UP 0:0:0.00
H(209)
No No No Yes In PASS2's output report, toggles stack trace (¢9).

Files Used or Created by the HAL/S Compiler

Among themselves, the seven passes of HAL/S-FC use a somewhat-consistent scheme for associating filenames to file numbers, though not all of the passes necessarily use all of the files.  I say "somewhat", because files output by one pass are occasionally input to another pass using a different file number.  Here's a handy table that summarizes the file usage of each pass.  When you see something italicized, such as halmat.bin in --raf=B,7200,1,halmat.bin, I mean to imply that while these are the names that the shell script HALSFC uses, you may or may not want to choose a different name if you were to bypass HALSFC and concoct your own program flow.  On the other hand, the names must be consistent between the passes outputting them and the passes using them as input.  The cells that have been highlighted in color emphasize those places in which the same file must be used on successive passes; in the case of the virtual-memory file, I don't know if the same file is used on successive passes or not, so I haven't highlighted it, but I've been using the same file without any apparent difficulty.

HAL/S-FC Usage
PASS1 or PASS1B
FLO
OPT or OPTB
AUXP
PASS2 or PASS2B
PASS3 or PASS3B
PASS4
Notes
Input HAL source code
--ddi=0,SOURCEFILE.hal or stdin
n/a
n/a n/a n/a n/a n/a
Output report
--ddo=0,pass1.rpt or stdout
--ddo=0,flo.rpt or stdout --ddo=0,opt.rpt or stdout --ddo=0,auxp.rpt or stdout --ddo=0,pass2.rpt or stdout --ddo=0,pass3.rpt or stdout --ddo=0,pass4.rpt or stdout
Output error messages
stderr
stderr stderr stderr stderr stderr stderr
Extra listing file, plus SPACELIB error messages
--ddo=2,listing2.txt
n/a n/a n/a n/a TBD TBD This file is produced by PASS1 if "LISTING2" is among the compiler options.  (The memory-management system may also direct certain error messages to this device, but that's presently TBD.)
AP-101S object code
n/a
n/a n/a n/a --ddo=3,cards.bin,E (PASS) or
--pdso=3,cards,E (BFS)
TBD
TBD
Generated object code, in a format similar to the IBM 360 object-code format.  The PASS and BFS versions of the compiler differ, in that the PASS version outputs a single object file per HAL/S input file, whereas the BFS version output a number of output files as members of a partitioned data set in a manner that's TBD.
Object code "deck"
n/a n/a n/a n/a --ddo=4,deck.bin,E TBD
TBD
An optional copy of the object code.  For the PASS version of the compiler, it's identical to cards.bin (see above).  For the BFS version, it's a single-file format, unlike the PDS format of cards.
Input error-message library
--pdsi=5,ERRORLIB n/a n/a n/a --pdsi=5,ERRORLIB
TBD
TBD
ERRORLIB is a library of standardized error messages supplied with the HAL/S compiler source code.
Input access-rights library
--pdsi=6,ACCESS n/a n/a n/a n/a TBD TBD ACCESS is a library of access-code rights, by which different sections of HAL/S code can be restricted in terms of what other code they can access.  The supplied version of ACCESS is empty.
Extra listing
n/a n/a n/a n/a --ddo=7,extra.txt TBD
TBD
TBD
Output or input HALMAT
--raf=B,7200,1,halmat.bin --raf=B,7200,1,halmat.bin --raf=B,7200,1,halmat.bin --raf=B,7200,1,auxmat.bin --raf=B,7200,1,auxmat.bin TBD TBD HALMAT is the "intermediate" language into which HAL/S code is converted prior to generation of machine code.  Various versions are created by the several compiler passes; see also optmat.bin, below.
Literal file
--raf=B,1560,2,litfile.bin --raf=B,1560,2,litfile.bin --raf=B,1560,2,litfile.bin --raf=B,1560,2,litfile.bin --raf=B,1560,2,litfile.bin TBD TBD This is a "random-access file" that the compiler uses to store the values of string, floating-point, and bit-string literals.
Workfiles
--raf=B,1560,3,icfile.bin n/a
n/a
n/a --raf=B,1600,3,objcode.bin
TBD TBD TBD, but I think that icfile.bin holds values of INITIAL and CONSTANT clauses for DECLARE statements, which may be swapped out of memory if there are too many of them.  Presumably it is just a workfile not used by other compiler passes.

I think that objcode.bin is a workfile into which data used for object-generation is swapped to preserve memory.  In spite of the name I used for it, I don't think it is object code as such.
Second HALMAT file
n/a
n/a
--raf=B,7200,4,optmat.bin --raf=B,7200,4,optmat.bin --raf=B,7200,4,optmat.bin TBD TBD See the comments for halmat.bin and auxmat.bin above.
SDF
n/a n/a n/a n/a n/a --raf=B,1680,5,sdf.bin TBD Simulation Data File (SDF), for "phase 3" compilation only.
Virtual-memory
file
--raf=B,3360,6,vmem.bin --raf=B,3360,6,vmem.bin --raf=B,3360,6,vmem.bin --raf=B,3360,6,vmem.bin --raf=B,3360,6,vmem.bin --raf=B,3360,6,vmem.bin TBD This is a "random-access file" that the compiler uses to store blocks of virtual memory which have been temporarily unloaded from memory.
Input COMMON file
n/a
--commono=COMMON0.out
--commoni=COMMON1.out --commoni=COMMON2.out --commoni=COMMON3.out --commoni=COMMON4.out --commoni=COMMON5.out The state of COMMON memory upon program start.
Output COMMON file
--commono=COMMON0.out
--commono=COMMON1.out --commono=COMMON2.out --commono=COMMON3.out --commono=COMMON4.out --commono=COMMON5.out TBD
The state of COMMON memory upon program end.  Warning:  The input and output files cannot have the same name.


Validating the Compiler

My Mind-Reading Trick

I will now perform a mind-reading act:  I predict that you trust software you download from the online sources.  I'm referring not to the security aspects of such downloaded software, but to the functionality of it.  You may well be worried that the software is a scam somehow.  But barring that, you assume that it works correctly as advertised  You trust the developers.  You have no interest in whatever means were used to develop the software you've downloaded or to validate that it operates correctly. 

Was I right about you?  If was, then Congratulations!  Give yourself a gold star.  You don't need to read this section.  You're all done absorbing information about the HAL/S compiler.  That's why I've stuck this section at almost the very end.  It's easier to skip it that way.

However, that's not a very productive way of thinking if you're the one actually trying to resuscitate ancient software that was originally used by very few people, in a protected, secretive environment, and trying to do so in the absence of the environment and the tools (and often, the documentation) that those original developers relied on.  That's just not the digital archaeology way of thinking!  No, in situations like that, we have to make an enormous effort to check and cross-check everything we can think of, to insure the highest degree of authenticity we can. 

So that's what this optional section is about. 

Validating PASS1

As I mentioned earlier, we actually have two separately-developed modern versions of the HAL/S compiler's phase 1:  namely, the ubiquitous PASS1 (AKA HALSFC-PASS1) that has been discussed so much above, and a Python 3 port of phase 1 that I call HAL_S_FC.  In an ideal world, I'd like to say that these two programs were developed completely independently, in clean-room fashion.  Unfortunately, I can't say that, because I developed both of them myself, albeit at different times, though using entirely-different development methods and relying on my sieve-like memory to have forgotten everything in the meantime.  Hopefully, that's good enough to let us pretend that they were independently developed.  Because PASS1 and HAL_S_FC were developed separately, using different methods, it is likely that although they could individually be buggy, it is extremely unlikely that they are buggy in the same ways at the same places in their code.  Thus by closely comparing the results of the two, we can debug (or alternatively, validate) both of them at once.

Now unfortunately, to support my claim that these two implementations of phase 1 can each be used to validate the other, we do have to talk a little bit about how the modern HAL/S-FC compiler was developed, and I doubt that that's something of too much interest to you.  But if we have to, we have to.  Here's a side-by-side comparison of the development methods:

Stage of Development
HAL_S_FC
PASS1
First stage: separate development
  1. HAL/S-FC source code for PASS1 manually translated from from XPL/I language and IBM 360 assembly language to Python 3, calling it HAL_S_FC.
  2. Manually debugged until compilation of a HAL/S program could proceed to its conclusion without aborting.
  3. Manually debugged until the compiler report and output files (literals, HALMAT) seemed plausible.
  1. Developed XCOM-I, a general-purpose XPL/I-to-C cross compiler.
  2. Extensively tested XCOM-I with legacy XPL code (such as source code of 1970's XPL compilers).
  3. Manually developed C-language "patches" for the small amount of IBM 360 assembly-language source code in HAL/S-FC.
  4. Created C-language version of HAL/S-FC, using XCOM-I and C-language patches.
  5. Compiled the C code, calling the resulting executable HALSFC-PASS1.
Second stage: joint debugging
  1. Compiled all existing HAL/S source-code files using both HAL_S_FC and HALSFC-PASS1, with the same compiler options for each.
  2. Used automated comparisons (such as diff) of:  compiler reports and HALMAT files.  (For technical reasons, literal files aren't immediately comparable.)
  3. Where discrepancies were found, corrected either HAL_S_FC or XCOM-I or IBM 360 "patches" of HAL/S-FC.
  4. Went back to step 1 until no more discrepancies were found!
  5. Went back to step A until no more HAL/S source-code files are available.

The end result of that process, obviously, is that all available HAL/S source-code files (not including Space Shuttle flight software) were compiled to give matching results in the two implementations of phase 1.

We already know, of course, that the comparision of HALSFC-PASS1's results to those of HAL_S_FC can be performed with any/every compilation, simply by using the TEST feature of HALSFC.  My claim is that in doing so, we've validated our modern version of PASS1.

Validating Phase 1.5 and Phase 2

Unfortunately, we have no independent implementations of FLO, OPT, AUX, or PASS2 against which to compare HALSFC-FLO, HALSFC-OPT, HALSFC-AUX, and HALSFC-PASS2.

However, there is a potential method of performing an adequate validation test.  Suppose one were to have (say) all of the following items:

If so, it would be possible to perform an automated end-to-end check that the compiled source code produced an executable that was byte-for-byte correct, and that it had presumably exercised every feature of the HAL/S language.

At present, I can report merely that no such check has been performed, so for now this is just something that's on my wish-list.

A Glossary and Some References




This page is available under the Creative Commons No Rights Reserved License
Last modified by Ronald Burkey on 2024-08-21

Virtual AGC is
              hosted by ibiblio.org