.var qz 1 2
.var total 3 4
.var comment c t
.if comment
.nf;To generate the file libsim.hlp, run this file (SLH30!)
with /variant:help/nopaging
To generate the file SIMLH3.man, run this file with /variant:notready
QZ version with /var:qz
/variant:qz will include local routines at the Stockholm installation
/variant:total will give an extra big and comprehensive handbook
.pg.f
.endif comment
.lm 5.f.nj
.variable notready n r
.variable help h m
.lm 5.f.nj
.if help
.ps 5000,72
.endif help
.ifnot help
.ps 65,65
.pg
.nj.title DECsystem-10 SIMULA Language Handbook, part III
.sp 1.lm 5.ps 65,65
.pg
.number 1
.sk;.nj.lm 0
Swedish National Defense Research Institute#######FOA Report
Department of Planning and Operations Research####C10045-M3(E5)
S-10450 Stockholm#################################July 1978
.sk;DECsystem-10 SIMULA Language Handbook Part III
.br;==============================================
.sk;.lm 3;(The DECsystem-10 SIMULA Utility Program Library)
.sk;.lm 3;.fill
.i -3
BY#Stefan Arnborg, Lars Enderin, 
Mats Ohlin, Stephan Oldgren and Jacob Palme.
.lm 3;.nf;.s 2;.i -3;ABSTRACT
.fill
.s;The DECsystem-10 SIMULA Language Handbook contains the
information necessary for an applications programmer who intends to use
SIMULA on a DECsystem-10 computer.
.s;Part I describes the SIMULA programming language.
.br;Part II contains special information for DECsystem-10.
.br;Part III describes the utility program library, which includes:
.s;.i -2;>#The SAFEIO package for safe
conversational terminal interface.
.s;.i -2;>#Utility routines for inserting a help facility into 
the conversational terminal communication, where the appropriate
help message at each point in the program can be selected from
a file containing several messages.
.s;.i -2;>#Routines for accessing date, time etc.
.s;.i -2;>#Routines to allow writing real-time programs in SIMULA
(e.g_. programs which can communicate simultaneously
with more than one user terminal.)
These routines do not work with DECsystem-20.
.s;.i -2
>#Routines for binary (un-formatted) I/O.
.s;.i -2
>#Routines for record-oriented I/O.
.s;.i -2
>#Routines for file handling.
.s;.i -2
>#A utility package of routines for character string (TEXT) handling,
with routines for searching, splitting, concatenating, hashing etc.
.s;.i -2;>#Routines for in-core sorting and summation.
.index ^^Release version
.s;This document reflects the software as of version 4
of the DECsystem-10 SIMULA system.
.s;Last update 1978-05-23.
.lm 5;.ps 55,65
.p;.i -5;SEARCH KEY
.s;Computer, Programming, Programming Language, SIMULA, DECsystem-10,
Digital Equipment, Algol 60, Fortran, Program library, file handling,
input/output, conversational programming, real time, error handling,
string handling, character handling, text handling, sorting.
.s;.i -5;CONDITIONS OF RELEASE
.index ^^Conditions of release
.index ^^Responsibility for errors
.index ^^Copyright of the SIMULA system
.s;The information in this document is subject to change without notice.
The  Swedish National Defence Research Institute assumes no
responsibility for any errors that may appear in this document,
in the programs described therein or in the SIMULA system itself.
.ifnot help
.if notready
No promise is made to implement any of these programs,
especially not those marked "NOT READY".
.ei help
.ei notready
.in help
.s;This document and the software described in it is furnished
to the user for use on a DECsystem-10
computer system and may be copied only for use on such systems, except as
may otherwise be provided in writing by
the Swedish National Defence Research Institute.
.s;.i -5;ACKNOWLEDGEMENT
.s;Part of section 4.1 has been adapted from the similar text
for the IBM 360/370 SIMULA System, written by Karel Babcicky
at the Norwegian Computing Center.
.s;Copyright 1976, 1977 by The Swedish National Defense Research Institute and
(partly) The Norwegian Computing Center.
.if notready
.p -5,1,5;SOME OF THE PROCEDURES ARE NOT YET WRITTEN
.s;This preliminary version of part III of the handbook includes some
procedures which have not yet been implemented. Their descriptions
are only proposals. Some of these procedures may eventually be implemented in a
different fashion, if at all.
.s;These procedures are marked [NOT READY] in section 0.2 but
they are not always marked [NOT READY] in the following chapters.
Always refer to section 0.2 to check if a procedure is available.
.endif notready
.ifnot help
.ps 55,65;.pg;.lm 5;.f;.nj;TABLE OF CONTENTS
.lm 10;.P -5,2,3;0.## INTRODUCTION
.lm 15;.P -5,1,3;0.1# HOW TO GET ACCESS TO  THE LIBRARY
.lm 15;.P -5,1,3;0.2# SUMMARY LIST OF ROUTINES
.lm 10;.P -5,2,3;1.## UTILITY PACKAGES
.lm 15;.p -5,1,3;1.1# APPLICATION PACKAGES
.lm 15;.p -5,1,3;1.2# DEMONSTRATION PROGRAMS
.lm 10;.P -5,1,3;2.## SIMULA SOURCE PROGRAM CONVERSION PROGRAMS
.lm 10;.P -5,1,3;3.## DIRECTFILE HANDLING PROGRAMS
.lm 10;.P -5,1,3;4.## PROCEDURES NOT WRITEABLE IN SIMULA
.lm 15;.p -5,1,3;4.1# TIME AND DATE
.lm 15;.p -5,1,3;4.2# BASIC ASSEMBLY PROCEDURES FOR REAL TIME
.lm 15;.p -5,1,3;4.3# INPUT/OUTPUT
.lm 21;.p -6,1,3;4.3.1 ASCII-FORMATTED I/O
.lm 21;.p -6,1,3;4.3.2 UNFORMATTED (BINARY) I/O
.lm 21;.p -6,1,3;4.3.3 FILE HANDLING
.lm 15;.p -5,1,3;4.4# CONTROLLED ERROR HANDLING
.p -5,1,3;4.5# SCHEDULING AND JOB CONTROL
.lm 15;.p -5,1,3;4.6# MEMORY HANDLING
.ei help
.ifnot notready
.in help
.br;[These facilities are not yet ready.]
.ei help
.ei notready
.if notready
.ifnot help
.lm 21;.p -6,1,3;4.6.1 PRIMARY MEMORY HANDLING
.lm 21;.p -6,1,3;4.6.2 VIRTUAL MEMORY HANDLING (OR OVERLAY FACILITY)
.endif notready
.lm 15;.p -5,1,3;4.7# ENVIRONMENT ENQUIRY
.lm 15;.p -5,1,3;4.8# PACKING INTO PARTS OF WORDS
.lm 21;.p -6,1,3;4.8.1 PACK AND UNPACK, PARAMETERS
.lm 21;.p -6,1,3;4.8.2 PACK AND UNPACK, ERROR HANDLING
.lm 21;.p -6,1,3;4.8.3 PACK AND UNPACK, METHODS OF PACKING
.lm 21;.p -6,1,3;4.8.4 PACK AND UNPACK, METHODS OF UNPACKING
.lm 21;.p -6,1,3;4.8.5 PACK AND UNPACK, EXAMPLES
.lm 15;.p -5,1,3;4.9 MIN AND MAX
.ifnot help
.lm 10;.P -5,2,3;5.## ROUTINES WRITEABLE IN SIMULA.
.lm 15;.p -5,1,3;5.1# PARTITIONING OF TEXTS
.lm 15;.p -5,1,3;5.2# SEARCHING AND TESTING OF TEXTS
.lm 15;.p -5,1,3;5.3# OPERATIONS ON TEXTS
.lm 15;.p -5,1,3;5.4# INPUT/OUTPUT
.lm 15;.p -5,1,3;5.5# SORTING AND SUMMATION ETC.
.lm 15;.p -5,1,3;5.6# RANDOM NUMBER GENERATION ETC.
.lm 15;.p -5,1,3;5.7# SIMULA VERSIONS OF SYSTEM CLASSES
.lm 10;.P -5,2,3;6.## SWEDISH LANGUAGE TEXT HANDLING AND INPUT/OUTPUT
.lm 10;.P -5,1,3;7.## UTILITIES SPECIFIC TO DECSYSTEM-10
.lm 10;.P -5,1,3;APPENDIX A - REALTIME - A SCHEDULER FOR TERMINAL PROCESSES
.lm 10;.P -5,1,3;APPENDIX B - CONTROLLED ERROR HANDLING
.lm 10;.P -5,1,3;APPENDIX C - INDEX
.lm 5;.pg
.lm 5;.f;.nj
.i -5;0.##INTRODUCTION
.i -1;------------
.s;The intention is to include in this document descriptions of
utility programs, classes and procedures
of general interest to users of SIMULA on the
DECsystem-10.
.s;Examples:
.i -2;>#Programs for editing and generating SIMULA source programs.
.i -2;>#Useful program packages written in SIMULA such as
data base packages, graphic packages, conversational
I/O packages.
.i -2;>#Useful MACRO 10 programs to be called from SIMULA, e.g.#for
object and binary I/O, access to monitor facilities like
the clock.
.s;The programs described here will be distributed to DECsystem-10 users through
the DECUS library, either as separate programs or on
the SIMULA distribution tape.
.s;Anyone who has submitted a program to the DECUS library,
such that the program is also suitable for inclusion
in the SIMULA program library, is invited to send us
a copy of the program and its documentation. If we accept the
program, we will include its description in future editions of this handbook.
Contributions in the form of procedures and classes of general
interest are also welcome, preferably in machine-readable form with full
documentation. We may modify the code to better fit the rest of the system,
if you allow us to do so.
We cannot promise to include your contributions, however.
.p -5,2,15;0.1 HOW TO GET ACCESS TO THE LIBRARY
.s;Most of the procedures and classes
described in this document are available in the
library files LIBSIM.ATR and LIBSIM.REL. These files should
normally be available on the SYS_: area on your computer, but you can also
keep them on your own disk area.
Main programs to be executed directly are available as separate
_.SAV (.EXE) files, not in the LIBSIM files.
.endif help
.if help
.lm 0;.s;LIBSIM
.br;======
.s;The files LIBSIM.REL and LIBSIM.ATR contain a large
number of useful external procedures and classes for the
SIMULA programmer.
.endif help
.s;Library procedures will be available to your program if you declare them
as external at the beginning of your program, e.g:
.s;EXTERNAL CLASS safeio;
.br;EXTERNAL INTEGER PROCEDURE hash;
.s;You need not mention any explicit filename if you are using
LIBSIM on the SYS area or on your own area.
An external declaration in a separately compiled segment (module)
must be repeated in all dependent modules including the main program.
Please note that when you use modules in LIBSIM that are coded in SIMULA
you will sometimes have to explicitly declare other LIBSIM routines.
The compiler will duly tell the user which declarations are missing.
.s;If you want to use other libraries, see the DECsystem-10
SIMULA Language Handbook part II chapter 7.1.1.
.s;Normally, when you load your programs with the LOAD, EXECUTE or
DEBUG commands of DECsystem-10, you need not mention
the names of any separately compiled classes or procedures.
Just write:
.s;_.EXECUTE myprog
.s;if your program has the name myprog. Any external classes
or procedures declared as such inside myprog will automatically
be loaded.
.if help
.s;At installations using the MIC system for command language
macros, there may be
a macro LIBSIM.MIC available for maintenance
of LIBSIM libraries. Type "DO LIBSIM" without
parameters for information about this.
.ei help
.nj
.s;If you cannot find the necessary .SIM, .REL, .ATR, .HLP, .MAN or .DOC
files on the SYS_:, HLP_: or DOC_: areas on your computer,
.if qz
contact the computer center or the SIMULA development group.
.endif qz
.ifnot qz
 they may still be found on the SIMULA distribution tape. REL and ATR files
for separately compiled procedures or classes can be found in
the library LIBSIM (.ATR and .REL) on the SYS_: area.
.endif qz
.ifnot help
.s;For procedures written in MACRO-10, there is usually no
separate .SIM specification file. Instead, the .MAC file
is written such that when you compile it with the SIMULA
compiler, the necessary .ATR file is produced.
.endif help
.s;In addition to the utilities listed below, a SIMULA programmer
has access to a number of built-in standard procedures.
These are described in appendix B to the DECsystem-10
SIMULA Language Handbook part I.
.s;The procedures, classes and main programs listed below are described in
.if help
DECsystem-10 SIMULA Language Handbook part III.
.else help
this document.
.ei help
.ifnot help
.subtitle 0.2 SUMMARY LIST OF ROUTINES
.page
.index ^^SUMMARY LIST OF ROUTINES
.i -5;0.2 SUMMARY LIST OF ROUTINES
.endif help
.lm 0
.s;The first column for each program indicates type of result
for function procedures, K for separately compiled
.ifnot help
classes, M for main programs (not in LIBSIM).
.endif help
.if help
classes.
.endif help
The following letters indicate parameter types.
.s;Letter codes in this list:
.s;_..=repetition#of#parameter, R=REAL, L=LONG#REAL, I=INTEGER,
C=CHARACTER, T=TEXT,
X=REF, B=BOOLEAN, G=LABEL, a=ARRAY, P=PROCEDURE,
.ifnot help
K=CLASS, M=MAIN PROGRAM.
.endif help
.if help
K=CLASS.
.endif help
.s
An asterisk (*) indicates efficient, MACRO-10 coded procedure.
.lm 28.ts 2,10,28;.nj
.ifnot help
.p 0,1,8
.else help
.p 0,1,3
.endif help
.i -28;1.#UTILITY PACKAGES
.skip;.i -28;1.1#APPLICATION PACKAGES
.s;.i -28;K	T,T	SAFEIO	Safe conversational terminal I/O. See SAFEIO.HLP
and SAFEIO.MAN
.i -28;K	T	SAFEI	SAFEIO without file handling facilities
.i -28;K		SAFMIN	Small, simplified version of SAFEI
.i -28;K	T,T	SIMEIO	Same as SAFEIO but prefixed with SIMULATION
.i -28;K	T	SIMEI	Same as SAFEI but prefixed with SIMULATION
.i -28;K		SIMMIN	Same as SAFMIN but prefixed with SIMULATION
.i -28;K		SIMDBM	CODASYL DBTG type DBMS system. Consists of
the external classes  SIMDBM (DBMMIN), DBMSET and the main
programs DBDUMP, DBLOAD, DBSORT, FETCH,
HMAKE, TRANSF, LOAD, DIRED, SPEC, PREP and PREP2
.i -28;K	I,I	STORE	Simple text-oriented DBMS
.i -28;K		SELECT	Boolean condition searching TEXT or FILE
.i -28;K	I,I,I	GPSSS	GPSS-like queue simulation package
.i -28;K	I,I,I,C,I#GPSSST	GPSSS with more automatic trace facilities
.i -28;K		FIGURE	Plot package for Tektronix plotter.
GRAPHI, COSYS, COSYSF and RUBOUT are also part of this package.
.index ^^GRAPHI, part of FIGURE
.index ^^COSYS, part of FIGURE
.index ^^COSYSF, part of FIGURE
.index ^^RUBOUT, part of FIGURE
See FIGURE.HLP
.if qz
.i -28;K		CALSIM	Curve plotting on Calcomp 835 plotter.
See CALSIM.HLP
.endif qz
.i -28;K	I,I,X,B,I#VISTA	Full control of alphanumeric 
display screen, e.g. to produce moving pictures
.i -28;K	I,I,X,B,I#FORM	Form fill in data entry, subclass of VISTA
.i -28;P	I,I,I,T	GETVIS	Terminal type input for VISTA
.i -28;K	T	DAHELP	Gives user help message when running SIMULA program.
Uses direct-access file to store help messages. See DAHELP.HLP
.i -28;B	T,T,I,I	SQHELP	Gives user help message when running SIMULA program.
Uses sequential file to store help messages
.endif help
.ifnot help
.skip;.i -28;1.2#DEMONSTRATION PROGRAMS
.i -28;M		(Not listed here)
.ei help
.s
.tp 8
.i -28;2.#SIMULA SOURCE CODE CONVERSION PROGRAMS
.s;[These are main programs, and thus not placed in LIBSIM]
.s;.tp 3
.i -28;M		SIMED	Prettyprinting, cleaner layout, indentation of BEGIN-END, no semantic change of program
.if notready
.i -28;M		SIMSTR	[NOT READY] Automatic structure abstract of source program
.endif notready
.i -28;M		SIMEXP	Combines separately compiled modules into one module
.i -28;M		SIMIBM	Conversion to IBM Simula
.i -28;M		IBMSIM	Conversion from IBM Simula
.i -28;M		CDCSIM	Conversion from CDC Simula
.i -28;M		FQCRED	Adds frequency count statements to a SIMULA program
.i -28;M		FQCLST	Edits SIMULA source program with frequency measurements
.p -28,1,14;3.#DIRECTFILE HANDLING PROGRAMS
.s;.i -28;M		DIRED	Edits a directfile
.i -28;M		MAKEDF	Converts sequential files to directfiles
and vice versa
.i -28;M		FETCH	General-purpose SIMDBM Data Base Manipulator
.i -28;M		MAKHLP	Creates help file for use with DAHELP
.endif help
.p -28,2,8;4.#PROCEDURES NOT WRITEABLE IN SIMULA
.s;.fill
.tp  8
4.1 TIME AND DATE
.s;.i -28;T		TODAY(*)	Gives TEXT with date: yyyy-mm-dd
.i -28;I		DAYNO	Number of this day in current year
.i -28;T		DAYTIME(*)	Gives TEXT with hh:mm:ss
.i -28;R		CLOCKTIME(*)	Gives REAL with time of day in seconds
.i -28;R		CPTIME(*)	Gives LONG REAL with CPU time in seconds
.if notready
.i -28;?	?	TIMELIMIT	[NOT READY] Sets time limit for current execution
.endif notready
.p 0,1,6
4.2 REAL TIME
.s;.i -28;B	X	INPUTCHECK(*)	Anything to read on file X?
.i -28;P	R	SLEEP(*)	Delays execution for R real seconds
.i -28;I	Xa,R	INPUTWAIT(*)	Sleeps until anything to read
.i -28;K		REALTIME	Scheduler for terminal processes
.p 0,1,20;4.3 INPUT/OUTPUT
.s;.i -28;I	X	LINECOUNT(*)	Returns LINESPERPAGE setting
.i -28;I	X	FILENAME(*)	Gives TEXT with FILE object generation parameter
.i -28;C		GETCH(*)	Inputs character, will not wait for carriage return
(input from controlling terminal only)
.i -28;B	R	TTYCHECK(*)	Checks if a character has been typed in at the controlling terminal
.i -28;P	X,C,I	OUTCHR(*)	Outputs character bypassing image
.i -28;P	X	FORCEOUT(*)	Terminal output buffer to terminal
.i -28;C	X	INSINGLECHAR(*)	Inputs character,
does not wait for carriage return
(Input from disk or controlling TTY)
.i -28;C	X	INSNGL(*)	As INSINGLECHAR, but line mode
(waits for break character)
.i -28;P	ILRCPa.. READ(*)	Reads many values in standard format
.i -28;P	ILRCTPa.. WRITE(*)	Writes many values in standard format
.i -28;I	X,RLICBTXa.. OUTPUT(*)	Binary output
.i -28;I	X,RLICBTXa.. INPUT(*)	Binary input
.i -28;I	RLICBTXa.. PUTSIZE(*)	How much will OUTPUT write?
.if notready
.i -28;B	X,I	BYPASS(*)	[NOT READY] Bypass I characters in a file
.endif notready
.if notready
.i -28;B	X,LRIC	LOOK(*)	[NOT READY] Binary one-word lookahead in input
.endif notready
.i -28;B	T	SCRATCHFILE(*)	Deletes file on secondary storage
.i -28;X	T	FINDINFILE(*)	NEW INFILE, but no error if file is not available
.i -28;X	T,B	FINDDIRECTFILE(*)	NEW DIRECTFILE, NONE if not available for requested access
.i -28;X	T	FINDOUTFILE(*)	NEW OUTFILE, NONE if write protected
.i -28;X	T	FINDPRINTFILE(*)	NEW PRINTFILE, NONE if write protected
.i -28;I	X	LASTLOC(*)	Highest written line in a DIRECTFILE
.if notready
.i -28;I	X	MAXLOC(*)	[NOT READY] Highest writeable line in a DIRECTFILE
.endif notready
.if notready
.i -28;P	X	CLOSEOPEN(*)	[NOT READY] Close and immediately open a file
.endif notready
.i -28;B	X	DOTYPEOUT(*)	Resets CTRL-O bit to resume terminal output.
					TRUE if file is a terminal and the operation was successful.
.p 0,1,7
4.4 CONTROLLED ERROR HANDLING
.s
.i -28;P	B	ENTERDEBUG(*)	Transfers to SIMULA debugging system
.i -28;P	T	ABORT(*)	User program generated error interrupt
.i -28;P	I	FORSIM(*)	Traps I/O calls from FORTRAN external procedures
.s;.test page 5
4.5 SCHEDULING AND JOB CONTROL
.s;.if notready
.i -28;P	B	SUBMIT(*)	[NOT READY] Enter file into input batch stream
.endif notready
.i -28;P	T,I	RUN(*)	Runs a new program under current job
.i -28;I	T,B	SAVE(*)	Saves current main memory on a file
.i -28;P	T	RESTORE(*)	Resumes execution from save file
.i -28;P	I	FREEZE(*)	Exits to monitor, ready for SAVE
.i -28;P	I	EXIT(*)	Exits directly to monitor (I=0),
				after closing files (I=1),
				to SIMDDT (I=2).
.if notready
.s;.test page 7
4.6.1 PRIMARY MEMORY HANDLING
.s
.i -28;I	I	FREEBITS(*)	[NOT READY] Forces garbage collection, return maximal free area size
.endif notready
.if notready
.s;.test page 7
4.6.2 VIRTUAL MEMORY CONTROL
.if notready
.s;.i -28;B	I	COREGUIDE(*)	[NOT READY] Sets physical guideline
.endif notready
.if notready
.i -28;B	I	CORELIMIT(*)	[NOT READY] Sets physical limit
.endif notready
.if notready
.i -28;P	XP..	SWAP(*)	[NOT READY] Swaps out given module from main store
.endif notready
.s;.test page 13
4.7 ENVIRONMENT ENQUIRY
.s;.i -28;I		MAXINT(*)	Returns largest positive INTEGER
.i -28;R		MAXREAL(*)	Returns largest positive REAL
.if notready
.i -28;R		MINREAL(*)	[NOT READY] Returns smallest positive REAL
.endif notready
.if notready
.i -28;L	LR,LR	APPROX(*)	[NOT READY] Returns integer value corresponding to numbers of bits differing in two arguments
.endif notready
.if notready
.i -28;T		IMPLEMENTATION(*)	[NOT READY] CPU manufacturer and model
.endif notready
.if notready
.i -28;T		LOGINFO(*)	[NOT READY] User and job id
.endif notready
.if notready
.i -28;I	a	DIMENSIONS(*)	[NOT READY] Number of dimensions (subscripts) of ARRAYs
.endif notready
.p 0,1,5;4.8 PACKING INTO PARTS OF WORDS(*)
.s;.i -28;B	IRLa,I,IRLCBTa,I,..#PACK	Packs many variables of varying type
.i -28;B	IRLa,I,IRLCBTa,I,._. UNPACK	Reverse of pack
.p 0,1,5
4.9 MIN AND MAX
.s
.I -28;I	I1,I2	IMAX(*)	Max(I1,I2)
.I -28;I	I1,I2	IMIN(*)	Min(I1,I2)
.I -28;R	R1,R2	RMAX(*)	Max(R1,R2)
.I -28;R	R1,R2	RMIN(*)	Min(R1,R2)
.I -28;L	L1,L2	LMAX(*)	Max(L1,L2)
.I -28;L	L1,L2	LMIN(*)	Min(L1,L2)
.s;.fill
.ifnot help
.test page 8
.endif help
.p -28,1,8;5.#PROCEDURES WRITEABLE IN SIMULA
.s;5.1 PARTITIONING OF TEXTS
.s;.i -28;T	T	REST(*)	Subtext after POS
.i -28;T	T	FRONT(*)	Subtext before POS
.i -28;T	T,I	FROM(*)	Subtext after pos=I in T
.i -28;T	T,I	UPTO(*)	Subtext before pos=I in T
.i -28;T	T	FRONTSTRIP(*)	Subtext without leading blanks
.i -28;T	T	GETITEM(*)	Subtext = next identifier, number or delimiter after POS
.i -28;T	X	INITEM(*)	GETITEM on INFILE
.if notready
[NOT READY FOR DIRECTFILES]  or DIRECTFILE
.endif notready
.i -28;C	T,I	FETCHAR(*)	Returns T.Sub(I,1).Getchar, null if I out of range
.i -28;P	T,I,C	DEPCHAR(*)	T.Sub(I,1).Putchar(C), no action if out of range.
.i -28;T	T,I1,I2	TSUB(*)	T.Sub(I1,I2), NOTEXT where Sub gives error
.s;.tp 8
.endif help
5.2 SEARCHING AND TESTING OF TEXTS
.s;.i -28;T	T,C	SCANTO(*)	Next occurrence of C in T
.i -28;T	C	SKIP(*)	Skips string of characters = C from T.Pos
.i -28;B	T1,T2	FRONTCOMPARE(*)	Does rest of T1 begin with subtext = T2?
.i -28;B	T1,T2	UPCOMPARE(*)	Same as FRONTCOMPARE, but upper and lower
case letters are regarded as equal
.i -28;I	T1,T2	SEARCH(*)	Finds first subtext = T2 from T1.Pos
.if notready
.i -28;I	T	GETTYPE	[NOT READY] Does a TEXT contain REAL, INTEGER, IDENTIFIER or what ITEM?
.endif notready
.i -28;I	T	CHECKREAL(*)	Checks if GETREAL can be performed
.i -28;I	T	CHECKINT(*)	Checks if GETINT can be performed
.i -28;I	T	CHECKFRAC(*)	Checks if GETFRAC can be performed
.i -28;I	T,I	HASH	Computes hash value from text in interval [0:I-1]
.i -28;C	T1,T2	FINDTRIGGER(*)	Next occurrence of any character of T2 in T1
.i -28;B	T,I,Ta,I MENU	Searches for unambiguous text in a text array
.i -28;B	T,Ta,I,I,I LOOKUP	Performs binary search in sorted text array
.s
.ifnot help
.test page 8
.endif help
5.3 OPERATIONS ON TEXTS
.s
.i -28;T	T,T	CONC2(*)	Concatenation of TEXTs, two parms
.i -28;T	T..	CONC(*)	Concatenation of variable no_. of TEXTs
.i -28;B	T1,T2	PUTTEXT(*)	Copies value of T2 starting at T1.Pos
.i -28;T	T	UPCASE(*)	Converts to upper case
.i -28;T	T	LOWCASE(*)	Converts to lower case
.i -28;T	C,I	MAKETEXT(*)	NEW text, all I characters equal to C
.i -28;T	T,C	COMPRESS(*)	Removes given character from text
.i -28;I	T	STARTPOS(*)	Returns starting position for a (sub)text
.i -28;B	T1,T2,T3#CHANGE	Replaces first substring of T1 = T2,
if any, with T3. Search starts at T1.Pos
.i -28;L	T	SCANREAL(*)	GETREAL, safe from bad data, starts at T.Pos
.i -28;I	T	SCANINT(*)	GETINT, safe from bad data, starts at T.Pos
.i -28;I	T	SCANFRAC(*)	GETFRAC, safe from bad data, starts at T.Pos
.if notready
.i -28;I	T,Ra,I	GETARRAY	[NOT READY]
Reads from a text real values into a REAL ARRAY
.i -28;I	T,Ia,I	GETINTARRAY	[NOT READY] Ditto INTEGER ARRAY
.i -28;I	T,Ra,I	GETLONGARRAY	[NOT READY] Ditto LONG REAL ARRAY
.endif notready
.i -28;T	T,R,C,I	PUTTIME	Edits a number in TIME format
.i -28;T	T,R	PUTFLOAT	Edits a number using minimum no_. of characters
.i -28;T	I,I	RADIX	Edits 2nd parm to an item in 1st parm base.
.i -28;I	I,T	GETRADIX	Deedits an item(T) in base I to an integer value.
.i -28;P	T,T,T,T	SPLIT	Splits a text at given delimiter string
.i -28;I	T,T,Ta,I#SPLITA	Splits a text and stores the parts in a text array
.i -28;I	T,C,Ta,I#SPLITC	Same as SPLITA but with character delimiter
.i -28;I	T,I,Ta,Ta#SCAN	Identifies keywords in a command string.
.i -28;I	T,I,Ta,Ta#SSCAN	Version of SCAN used by GETVIS.
.i -28;K	I	DECOM	(Subclass to SAFMIN)
Interprets input command of the format
.br;outfil.ext/switch1/switch2... =infil.ext/switch3/switch4...
.i -28;I	Ta	ARRLGD(*) Total length of texts in Ta + number of elements. Used in SIMDBM.
.i -28;P	Ta,T,C	ARRTXT(*) Put all texts of Ta in T, with delimiter = C. Used in SIMDBM.
.ifnot help
.test page 8
.endif help
.s;5.4 INPUT/OUTPUT
.skip
.i -28;C	X	LOOKAHEAD(*)	Next non-blank character readable by INCHAR
.if notready
.i -28;P	T,X	OUTLINE(*)	[NOT READY] Output TEXT on new line(s), TEXT may be longer than image
.endif notready
.if notready
.i -28;P	T,X	BREAKOUTLINE(*)	[NOT READY] Output TEXT on same line, TEXT may be longer than image
.endif notready
.i -28;T	T,X	INLINE	Types out a prompting question and copies an infile image (stripped)
.i -28;T	T,T,T,B,T,T#REQUEST	Sophisticated INLINE with input check, help etc.
.i -28;P	X,R,C,I	OUTTIME	Prints simulated time in hh:mm:ss.cc format
.i -28;P	..	HISTP	Prints histogram of Ia on file X
.skip
.ifnot help
.test page 8
.endif help
5.5 SORTING AND SUMMATION ETC.
.skip
.i -28;I	R	ILOG	Returns integer part of 10LOG(Abs(R))+1;
	if R = 0 return 0. I.e. Number of integer digits if Abs(R) >= 1 else number
	of leading zeros after decimal point
.i -28;I	Ia,I	ISUM	Returns sum of an integer array
.i -28;L	La,I	LSUM	Returns sum of long real array (almost) preserving precision
.i -28;R	Ra,I	RSUM	Returns sum of real array
.i -28;R	R,R,Ra,I SIGMA2	Returns variance, mean value of a real array
.i -28;P	R,R,I,R	SIGMEAN	Returns current variance and mean value including new observation
.i -28;P	"x"a,I	SORTxy	Sorts a given array in ascending or descending order.
.br;	x = T(ext), R(eal), I(nteger) or L(ong real)
.br;	y = A(scending), D(escending) order
.i -28;P	Ia,I1,I2,I3#SORTDN	Sorts slice Ia[1:2,I1:I1-1+N]
with respect to either or both integers in each row.
.i -28;R	R,R,I	SCALESTEP	Adjusts approx. max and min for diagram design
.i -28;B	Ia,I,I,I,B#IASHIFT(*)	Moves part of an integer array leftward.
.fill
.skip
.ifnot help
.test page 8
.endif help
5.6 RANDOM NUMBER GENERATION ETC.
.skip
.i -28;P	Ia,I,I,I SCRAMBLE	Random permutation of array
.i -28;C	Ia,N	PERGEN	Systematic generation of permutations
.i -28;R	R,R	RANDOM(*)	Random generator of random number series start
numbers
.i -28;I		UNIQUE	Unique number to be used e.g. as start random number (seed)
.i -28;I	I1,I2	NEXTRANDOM(*)	Returns the I1:th successor to random seed I2
.p 0,1,8
5.7 SIMULA VERSIONS OF SYSTEM CLASSES
.s;.i -28;K		ZIMSET	SIMULA tracing version of SIMSET
.i -28;K		ZIMULATION	SIMULA tracing version of SIMULATION
.p -28,2,5;6.## SWEDISH LANGUAGE TEXT PROCESSING AND INPUT/OUTPUT
.s;.i-28;B	C	BOKSTAV(*)	Swedish version of Letter
.i -28;T	X	INORD(*)	Swedish version of INITEM
.s;.i-28;T	T	LITENBOKSTAV(*)	Swedish version of LOWCASE
.s;.i-28;B	T,I,Ta,I MENY	Swedish version of MENU
.s;.i-28;T	T	STORBOKSTAV(*)	Swedish version of UPCASE
.i -28;T	T	TAGORD(*)	Swedish version of GETITEM
.skip
.if notready
.i -28;I	T	TAGTYP	[NOT READY] Swedish version of GETTYPE
.endif notready
.p -28,1,5;7.## UTILITIES SPECIFIC TO DECSYSTEM-10
.p -28,1,5;I	I1,I2	ADJPTR(*)	Byte pointer I1 adjusted by I2 bytes
.p -28,1,1;I	I1,I2	ANDINT(*)	Bitwise AND function
.ifnot help
.i -28;K		ATRSTR	ATR file structure
.ei help
.i -28;I	I1,I2,I3 BITFIELD(*)	Returns a bit field within I1 starting at bit
I2 (0-35) with length Abs(I3) (1-36) (I3 negative gives sign extension)
.I -28;B	I1,I2	BITGET(*)	BITGET:=I1.bit(36-I2)=1
.i -28;P	I1,I2,B	BITPUT(*)	I1.bit(36-I2):=IF B THEN 1 ELSE 0
.i -28;I	I1,I2,I3 BOOLFUNC(*)	One (0<=I1<=15) of 16 Boolean functions of I2,I3 (bitwise, like ANDINT).
For any valid I1, BOOLFUNC(I1,5,3)=I1.
.i -28;B	T,T	CALLMIC	Uses MIC to perform other tasks and optionally return
.i -28;T	T,T	CHECKEXTENSION	Adds default extension if file spec contains no dot and is not just of the form DEV:
.i -28;I	I1,I2,I3,I4 DEPBYTE(*) I=I2 with byte at bit
I3 of length I4 replaced by I1.
.i -28;P	X,I	ECHO(*)	Suppresses monitor echoing of terminal input
.i -28;I	X,T	FILCOP(*)	Efficient copying of disk files. Also copies creation date and version.
.i -28;K		FILED	Reads and writes DEC 10 line numbered files
.i -28;T	X,I	FILSPC	Returns file specification string for
file X in format controlled by value of I.
.i -28;I	I	FLOKUP(*)	Look up file specified by FILOP_. and LOOKUP blocks.
.i -28;I	I1,I2	GETTAB(*)	Returns item I1 in monitor table I2
.i -28;T	I	IDRX50(*)	Interprets a 36-bit word as a "RADIX50"
symbol (code bits and 6-character identifier)
.p -28,0,1;T	I1,I2	IDSIXBIT(*)	ASCII representation of up to 12 character
identifier given in I1 and I2 in SIXBIT (DEC 64-character code)
.i -28;I	R	INTREA(*)	"Retype" R as integer (same
36-bit pattern)
.i -28;I	X	JOBSTATUS(*)	Get JOBSTS word for PTY or TTY (subjob control)
.i -28;I	I1,I2	LOADBYTE(*)	Get any byte in readable core.
.i -28;I	I	LOADWORD(*)	Get word at address (I) - any readable word.
.i -28;I	I1,I2,I3 MATCH6(*)	SIXBIT match of I1 to I2 according
to wildcard mask I3.
.i -28;B		NUMBERED(*)	Did last inimage get a line-numbered line?
.i -28;T	T,I	OCTAL(*)	Octal representation of I, using T as work area.
.i -28;I	X,R	PTYCHECK(*)	Any PTY (Infile X) activity in R seconds?
.i -28;X	X	PTYFIL(*)	PTY Outfile companion to PTY Infile X.
.i -28;I	X	PTYINIMAGE(*)	Get line of input from PTY Infile X.
					Result shows how line ended.
.i -28;I	T,I	RDX50	Converts I,T to "RADIX50"
.i -28;R	I	REAINT(*)	"Retype" I as real (same
36-bit pattern)
.i -28;B X/T,T[,B]#RENAME(*)	Renames or deletes first arg
(file ref/spec) to second arg (file spec).
.i -28;B		RESCAN(*)	Makes invoking monitor command readable
					by invoked program
.ifnot help
.i -28;M		SIMATR	Displays the information in an ATR file
.endif help
.i -28;I	T	SIXBIT(*)	First 6 characters in T converted to
					sixbit word.
.i -28;I	I1,I2,I3 STOREBYTE(*)	Stores the byte I1 using byte pointer
					I2, modified (I3) bytes.
.i -28;I	I1,I2	STOREWORD(*)	Store I1 at (I2) (abs memory address).
.i -28;I	I	SXRX50		RADIX50 to SIXBIT.
.i -28;T	T,B	TMPIN(*)	Reads a "TMPCOR" core file into a new
text object, and deletes the file if B is TRUE.
.i -28;T	T	TMPNAM(*)	Creates a temporary file name like "021PIP.TMP"
.i -28;B	T1,T2 	TMPOUT(*)	Writes a "TMPCOR" core file from T2.
					Returns TRUE if successful.
.i -28;I	I,X,I	TRMOP(*)	Modifies monitor-terminal interface
.i -28;I	I	TTYLINE	Gives network node and line for tty number I
.i -28;T	I1,I2	TTYNUMBER	TTY number for node I1 line I2 in network
.i -28;I	I1,I2,B,I3 XCALLI(*)	Execute CALLI AC1,(I2). AC1=I1. Return (I3) if
					CALLI does not skip and B is TRUE,
					otherwise return new value of AC1.
.i -28;I	T,I1,I2 WILDSIX(*)	SIXBIT translation of T,
recording wildcards (? or *) in I1.
.lm 5
.if help
.s;.c;[END OF LIBSIM.HLP]
.endif help
.lm 5
.ifnot help
.nj
.st 1. UTILITY PACKAGES
.ps 55,65;.f.lm 5
.page
.index ^^UTILITY PACKAGES
.i -5;1.##UTILITY PACKAGES
.i -5;--------------------
.s;.i -5;1.1##APPLICATION PACKAGES
.index ^^SAFEIO conversational i/o package
.index ^^Conversational I/O
.index ^^Dialogue I/O
.index ^^Checking of terminal input data
.index ^^Help facility in user programs
.index ^^Terminal input data checking
.index ^^Input data checking
.p -5,1,0;**** SAFEIO
 is a package to enable a safe question-and-answer
.index ^^SAFEIO EXTERNAL CLASS
dialogue with a conversational terminal. The programs
in the package allow you to ask the user for variables
of various SIMULA types. The user answers are checked
for correct type and for acceptance according to criteria
specified by the programmer.
 Help and error
messages are given. The package protects from error interrupts
in programs which may receive faulty input data from
the user.
The user may save his input in a log file.
This file can later be used as input instead of the terminal.
Other files may also be used as input, intermixed with terminal input.
.if qz
See also SAFEIO.HLP, SAFMIN.HLP, SAFEIO.MAN.
.endif qz
.ifnot qz
SAFEIO is distributed as the files
SAFEIO.SIM, SAFMIN.SIM,
SIMEIO.SIM, SIMMIN.SIM,
SAFEIO.RNM, SAFEIO.MAN, SAFEIO.NEW, SAFMIN.HLP,
SAFEIO.ENG, SAFEIO.SWE and SAFEIO.HLP.
.endif qz
.br;Written by Mats Ohlin, Swedish National Defense Research Institute.
.s;.f;The SAFEIO system offers the following facilities in
a single procedure call :
.s;.tab stops 13,21,29,37,45,53,61,69,77

.lm 13
.p -8,1,1;1.	Issue a prompting question to the user.
.p -8,1,1;2.	Store the input in a simple variable.
.p -8,1,1;3.	Optionally accept default answers (equal to CR).
.p -8,1,1;4.	Check the syntax of the input.
.p -8,1,1;5.	Issue an appropriate message if the input is invalid.
.p -8,1,1;6.	Issue an explanatory message if the user responds with
anything starting with a question mark '?'.
.p -8,1,1;7.	Allow the user to substitute terminal input for disk file input.
This may be done at any time a question is to be answered.
.p -8,1,1;8.	Allow the user to save all accepted program input on a disk file.
This file may be used as an input file in a subsequent run.
Correspondence between saved and current question will
be checked (option by default).
.s;.lm 5
It is assumed that the user type only one item on each
input line.
.s;A question to the user is defined by the call:
.s;REQUEST("prompting#question", default, ***input(variable,validity),
"#error#message#if#not#valid", helpproc__expression);
.s;The parameter default is usually a text (constant) containing a
default answer value.
There is a SAFEIO attribute
NODEFAULT which can be used if default answers should be
prohibited.
.s;*** may be replaced by INT,REAL,LONGREAL,BOOL or TEXT.
For the BOOLINPUT procedure there is only one argument though, the
receiving variable.
.s;VALIDITY is usually a Boolean expression involving
VARIABLE but may also be a call of a Boolean procedure
if more complicated validity checking is necessary.
If the SAFFEIO attribute CHECKVALIDITY is set to FALSE, no
validity checking (i.e. no evaluation of the 2nd parameter to
the ***input procedure) will occur, thus speeding up
SAFEIO execution. Note, however, that this will endanger the
security of your program.
.s 2;The error message is printed if VALIDITY becomes FALSE.
The prompting question will then be repeated.
.s;HELPPROC__EXPRESSION will be evaluated each time the
user types in an answer beginning with a question mark '?'.
.s;The SAFEIO Boolean procedure HELP (with one text parameter =
the help text) may be used for displaying a text on the user's terminal.
.s;If no special information should be issued the SAFEIO procedure
NOHELP may be used. (The message - "There is no help in this case."
will be issued.)
.s;An example:
.nofill
.s;BEGIN
    EXTERNAL REF (Infile) PROCEDURE findinfile;
    EXTERNAL REF (Outfile) PROCEDURE findoutfile;
    EXTERNAL TEXT PROCEDURE conc,upcase,frontstrip,
    rest,checkextension;
    EXTERNAL CHARACTER PROCEDURE fetchar,findtrigger;
    EXTERNAL LONG REAL PROCEDURE scanreal;
    EXTERNAL INTEGER PROCEDURE checkreal,checkint,
    scanint,ilog;
    EXTERNAL BOOLEAN PROCEDURE menu;
    EXTERNAL CLASS safeio;
.s;    safeio(..<name of log file for input or "">,
	<"English" or "Swedish">..)
	! Use "English" if you want English texts.
	  Use "Swedish" if you want Swedish texts. ;
.s;    BEGIN
	INTEGER i;   REAL x;   LONG REAL y;
        TEXT t;   BOOLEAN b;
	TEXT ARRAY table[1:4];
.s;	request("Enter integer:","14",
        intinput(i,irange(i,1,20)),
        outofirange(i,1,20),
        help("...info issued at '?'.."));
.s;	! The default value is 14. Only positive numbers
	! are allowed.;
	! Note the use of the procedures IRANGE(i,low,high)
	! and OUTOFIRANGE(i,low,high).
	! See also Summary Chapter 5 in SAFEIO.MAN.;
.s;	request("Enter real item:",nodefault,
        realinput(x,TRUE),"",nohelp);
.s;	! Default answer not allowed. Any legal real item
	! is accepted since validity is TRUE.
	! No help information available.;
.s;	request("Enter long real value:","E1",
        longrealinput(y,y NE 0),
	"? Must not be zero.",nohelp);
.s;	! Default value is 10 = E1;
.s;	request("Enter yes or no:",nodefault,
        boolinput(b),"",nohelp);
.s;	! Note that procedure boolinput has only one
	! parameter.;
.s;	table[1]:- Copy("START");
	table[2]:- Copy("END");
	table[3]:- Copy("GO");
	table[4]:- Copy("GOTO");
.s;	request("Enter command:",nodefault,
        textinput(t,menu(t,i,table,4)),
	commandmessage(index),commandhelp(table,4));
.s;	! The user may use an abbreviated form when no
	! ambiguity exists.
	! (Exact matches are always considered correct.)
	! The variable i will return the table index.
	! The length of the table (4) must also be supplied.
	! Note that the table must contain upper case
	! letters only.
	! The procedure MENU resides in LIBSIM and checks
	! for correspondence between T and TABLE.;
	! The text procedure COMMANDMESSAGE will tell the
	! user if his (illegal) command was either
	! Unknown or Ambiguous.
.s;	! A simple text request: ;
.s;	request("Enter A or B:","A",
	   textinput(t,t = "A" OR t = "B" OR
           t = "a" OR t = "b"),
	   "? Answer A or B.",nohelp);
.s;	! The user may define his own boolean procedure for
	! input validation if more complicated tests are
	! necessary.;
.s;	GO TO start;	! Will restart from SAFEIO prefix;
			! START is a SAFEIO label located
			! just in front of INNER.;
.s;	! If the label EOF exists,
        ! End-of-file on SYSIN (=_^Z)
	! will jump to this label. If EOF does not not exist
	! in the user program, the SAFEIO block will
	! terminate through an internal SAFEIO jump.
	! NOTE! Once Sysin.Endfile is TRUE, there can be no
	! more input on Sysin! This mechanism will only
	! work for blocks prefixed by SAFEIO
	! (i.e. NOT when using NEW SAFEI(O)).;
.s;    END of SAFEIO block;
.s;END of program;
.s;.s;.s;On receiving any SAFEIO question on the terminal
the user may input one of the SAFEIO commands:
.s;
.tab stops 15;.left margin 15
.f
.i -10;?	to get help information.
.s;.i -10;!	FOLLOWED by:
.s;.i -10;*	to change the switch: Display-prompting-question.
.i -10;/	to change the switch: Display-default-value.
.i -10;=	to change the switch: Display-input (+ the *- and /-switches).
.i -10;[	to change the switch: Trace (file messages).
.i -10;+	to close and reopen current recording file in append mode.
.i -10;;	to treat the line as a comment.
.i -10;%	to call special procedure.
.i -10;_&	followed by input to override validity test.
.i -10;<FIL.EXT    to open new input file in wait mode. Default extension =.saf
.i -10;__	to continue input in nowait mode.
.i -10;<	to close current input file.
.i -10;_^ (uparrow) to close all active input files.
.i -10;__FIL.EXT    to open new input file in nowait mode. Default extension =.saf
.i -10;>FIL.EXT    to open new recording file. Default extension =.saf
.i -10;>	to close current recording file.
.i -10;?	to print this text.
.f.lm 5;.s;Anything else following ! will cause current question to be displayed.
.s;The != command will always change the values of the switches
Display-prompting-question and Display-default-value to the same value
as the switch Display-input.
.s;Note that the !_& facility may be switched off by calling
the procedure NOOVERRIDE.
.s;The !% facility gives the programmer the possibility to declare his
own procedure SPECIAL (with exactly that name and without parameters)
which will be called when the user responds with !%. It is
possible to interpret the information following the !% in the
procedure, thereby expanding the power of the SAFEIO - ! commands.
See SAFEIO.MAN for further information on SAFEIO attributes.
.s;If you are using SAFEIO via INSPECT it is not meaningful to specify any
initial recording file, since it will be closed immediately. This
is because the INNER in SAFEIO will be passed. In order to
close all possible open SAFEIO files, end the connection block with
a call of the SAFEIO procedure closefiles. I.e. :
.s;.nf
BEGIN   EXTERNAL declarations.....;
.s;    ....
    INSPECT NEW SAFEIO("","") DO	! Default
    language is English ;
.s;    BEGIN .... using SAFEIO ......
	closefiles;
    END;
.s;END program
.s;.f
By substituting the class SAFEI for SAFEIO (with the language
parameter only) the facilities numbered 1 to 6 will still be present
while the file handling facilities will absent. The class SAFEI
requires about 2/5 as much core as SAFEIO.
.s;By substituting SAFMIN still more SAFEIO facilities
.index ^^SAFEI EXTERNAL CLASS
.index ^^SAFMIN EXTERNAL CLASS
are excluded. See SAFMIN.HLP. The size of SAFMIN is about 1/2 that of SAFEI.
.s;The three classes SIMMIN, SIMEI and SIMEIO are identical in all respects
to SAFMIN,
.index ^^SIMMIN EXTERNAL SIMULATION CLASS
.index ^^SIMEIO EXTERNAL SIMULATION CLASS
.index ^^SIMEI EXTERNAL SIMULATION CLASS
.index ^^SIMMIN EXTERNAL SIMULATION CLASS
SAFEI and SAFEIO respectively except that they are prefixed with
SIMULATION.
.p -5,4,8;**** SIMDBM Data Base Management System.
.index ^^SIMDBM system
.index ^^Data Base Management
.index ^^Codasyl-type Data Base Management
.s;SIMBDM is a data base handling system based on the ideas in the
CODASYL DBTG proposal, but written entirely in SIMULA for use
by SIMULA programs. Facilities exist for defining SCHEMAs (Data
Base Structure Descriptions) and storing them in the data base,
for accessing the SCHEMA from the SIMULA program and for accessing
data using the SCHEMA. Data base fields of type
TEXT or ARRAY have indefinite length. New fields can be added
to existing records. Memory need not be reserved for the largest
instance of each record type. Data base records are mapped onto
CLASS instances in core. A SIMULA program can access and use
the SCHEMA, which allows writing "data-independent"
programs in SIMULA.
.s;Restrictions: No built-in facilities exist for privacy constraints
or for solving multi-terminal access conflicts.
.s;.s;Written by Kalle Maekilae, Swedish National Defense Research
Institute.
.if total
.p -5,2,8;BASIC CONCEPTS
.p 0,1,5;SIMDBM is a simple Data Base Management System (DBMS)
based on the CODASYL Task Group (DBTG) proposal. The
.index ^^Data Base Management System
.index ^^CODASYL Task Group proposal
DBMS system described is written entirely in the SIMULA programming
language. It was developed to test how an interface between SIMULA
.index ^^SIMULA - DBMS interface
and a DBMS system can be arranged. The same methods could then
be used to interface SIMULA to a larger DBMS system, not written
in SIMULA.
.p 0,1,5
Such an interface could use the same procedures to be
called from SIMULA and could map the data onto the same SIMULA-type
data structures in core. However, the actual procedures would of
course have to be rewritten.
.p
Our experience is that our DBMS system itself is fully usable
for applications of moderate size. It is
also, because of its simple structure, useful as a tool in teaching
data base management techniques.
.p
Two central concepts in the DBTG proposal are those of a RECORD and
a SET.
.p
A RECORD is in some ways similar to a SIMULA CLASS. There can
be several types of RECORDs, each with a RECORD type name. The RECORD
is divided into FIELDs, which have a name and a type,
just like CLASS attributes in SIMULA.
.p
A SET is a set of RECORDs. One RECORD is the OWNER of the SET. The other
RECORDs are called MEMBERs. The MEMBERs can be of more than one RECORD
type, and the number of MEMBERs can vary.
.p
SETs are often implemented by letting the OWNER refer to the first
MEMBER, that MEMBER to the next member etc. There must also be a
way of finding the OWNER from any of the MEMBERs. This is either
implemented by having a direct reference from each MEMBER to
the OWNER, or by letting the last MEMBER in the chain refer back to
the OWNER, so that the OWNER can be found indirectly by following
this chain from any of the MEMBERs.
.p
The SET concept can be used to create rather complex data structures
in the data base.
.p -5,2,15
IMPORTANT ASPECTS IN THE DEVELOPMENT OF THE SYSTEM
.p -5,1,7
#+++#The system should be easy to use for a person writing
an application program.
.skip
The manuals for a CODASYL-type DBMS system can be very
difficult to read, because of the many details.
A simple system can be a good introduction, and also be
sufficient for many applications. For more advanced
applications, the system is easy to extend, since it is
written entirely in SIMULA.
.p -5,1,7
#+++#Flexible data structures.
.skip
Data from the data base should be supplied in a form
suitable to the application program. A pre-processor
can be used to create SIMULA source program data structure
declarations, including procedures for reading and
writing data. These procedures will also convert
between the internal and external data format.
.p -5,1,7
#+++#Ways of extending the data base.
.index ^^Extendibility of existing data bases
.skip
The user should be allowed to add new
RECORD types and to add more FIELDs to an existing
RECORD type. This should
not require any change in old programs using the data
base, and old data in the data base should still be readable.
.p -5,1,7
#+++#The application program should have access to to
a description of the data base structure.
.skip
This makes it possible to write fully general purpose
.index ^^General-purpose, data independent application programs
programs, which do not depend on the actual structure of the
data base. These programs will thus work for any data base,
independent of the actual RECORD types, SETs and
structures in that data base.
.skip
An example would be a program which informs the
user at a conversational terminal about
the structure of data, and which allows him to read and write arbitrary
data within the structure of the data base.
.skip
Many commercial DBMS system do not have such a facility for
writing general-purpose programs in the high-level language.
.p -5,1,7
#+++#The code of the DBMS system itself should be easy to read and modify.
.skip
Since the system is written entirely in the high-level language
SIMULA, it is also easy to move from one computer to another.
The system is also rather small (about 1400 lines of SIMULA code).
.skip
This makes it possible for an experienced SIMULA programmer to
get control over the system, to modify and extend it.
.p -5,2,15
ASPECTS NOT YET CONSIDERED
.p -5,1,7
#+++#High efficiency in the use of CPU-time and core.
.s;Some effiency considerations have influenced the design, but the main
goal has been to keep the program simple. The system can
probably be made very much faster by rewriting a few central
procedures in assembly language.
.p
#+++#Supporting several simultaneous users.
.index ^^Simultaneous users, support of
.skip
Every user program is a closed unit, which does not share code
with other people working against the data base. Several users
can simultaneously read the data base, but only one at a time
can write into it.
.p
#+++#Protection codes.
.index ^^Protection of the data base
.index ^^Data base security and protection
.skip
Code words to ensure security for parts of the data base have not
been introduced. This is rather simple to add.
However, such codes are not necessary for many applications.
.ei total
.ifnot qz
.p
FILES ON THE DISTRIBUTION TAPE FOR SIMDBM:
.index ^^SIMDBM files on the distribution tape
.s;SIMDBM.DOC briefly describes the other files of the system.
.s;External classes for use with SIMULA application programs
using SIMDBM: DBMMIN.SIM, SIMDBM.SIM, DBMSET.SIM.
.index ^^DBMMIN, part of SIMDBM system
.index ^^DBMSET, part of SIMDBM system
.index ^^SIMDBM, class DBMMIN
(.ATR and .REL files for these are part of SYS:LIBSIM).
.skip
Documentation: SIMDBM.DOC, SIMDBM.RNO, SIMDBM.HLP, NEWDBM.RNO.
.s;General purpose program (FETCH) for
.index ^^SIMDBM data base query system
conversational queries to data bases: FETCH1.SIM,
.index ^^FETCH.SIM part of SIMDBM
.index ^^SIMDBM, class FETCH.SIM
FETCH2.SIM, FETCH.SIM, FETCH.RNO, HMESS.DMP, FETCH.EXE,
DBLOAD.SIM, DBDUMP.SIM.
.skip
Loading of SIMDBM-data bases from a sequential file:
.index ^^LOAD.SIM part of SIMDBM
.index ^^SIMDBM, routine LOAD.SIM
LOAD.SIM, LOAD.HLP, DBLOAD.SIM, DBDUMP.SIM.
.skip
Text editing of SIMULA direct access files from a terminal:
.index ^^Text editing of SIMULA direct access files
.index ^^Editing of SIMULA direct access files
.index ^^Direct access files, text editing of
.index ^^DIRED Direct file editor
DIRED.SIM, DIRED.HLP.
.skip
Entering a SCHEMA (Data Base Structure Specification) into a data base:
.index ^^SCHEMA, entering into a data base
SPEC.SIM, SPEC.EXE.
.skip
Preprocessor, producing SIMULA procedures for loading records
from a SIMDBM data base: PREP2.SIM.
.skip
Preprocessor, producing SIMULA class with internal
.index ^^Preprocessor in SIMDBM producing SIMULA classes
representation of records from a SIMDBM data base:
PREP1.SIM.
.index ^^PREP1.SIM part of SIMDBM
.index ^^SIMDBM, routine PREP1.SIM
.endif qz
.lm 5;.p -5,4,15;**** STORE
is a simple text oriented data base handler providing
.index ^^Data base handling
.index ^^STORE data base handling package
.index ^^Direct access files, application package with
two main procedures PUTMESSAGE and GETMESSAGE. PUTMESSAGE
stores a message under a key in a direct access file, and
GETMESSAGE returns the message stored under a given key.
Both key and message can be text strings of arbitrary length.
STORE is distributed as the files STORE.SIM, STORE.RNO,
STORE.HLP and STOREU.SIM.  STORE.RNO is STORE.HLP
in RUNOFF format. STOREU.SIM is an application
example which also uses the SAFEIO package.
.br;Written by Jacob Palme, Swedish National Defence Research Institute.
.p -5,1,5;**** SELECT is a SIMULA class to facilitate searching of
.index ^^Search with Boolean condition
.index ^^Information Retrieval
.index ^^SELECT EXTERNAL CLASS
TEXT strings or files applying Boolean conditions like
.br;"(SIMULA+ALGOL)_&(DEC+DIGITAL)"
.br;The Boolean condition is first translated into a formula tree.
This formula tree can then be applied to any number of TEXTs,
and TRUE will be returned for those TEXTs containing words
satisfying the Boolean condition.
.s;Files: SELECT.SIM, SELECT.RNH and SELECT.HLP.
In LIBSIM, SELECT.REL and SELECT.ATR can be available.
.s;Written by Jacob Palme, Swedish National Defence Research
Institute.
.p -5,1,5;**** GPSSS
.index ^^GPSSS system written in SIMULA
.index ^^QUEUE system simulation using GPSSS
.index ^^General Purpose System Simulator (GPSS) in SIMULA
is a package which converts SIMULA (by additions within the language)
into a programming language very similar to GPSS.
.p 0,1,4
GPSS is a well-known system for simulating systems of queues
and work stations and objects moving from work station to
work station. GPSSS provides the same facilities in SIMULA,
including the built-in standard statistics, in a way which is
very similar to GPSS. The advantage with using GPSSS may
be that you can easier go outside the GPSS boundaries,
since SIMULA is a much more general-purpose language.
.p
GPSSS may also be useful for introducing SIMULA to people who know
GPSS.
.p
GPSSS was originally written by Professor Jean G. Vaucher at the
Universit'e de Montr'eal, and was converted to DECsystem-10
by Joakim Bose.
.p
GPSSST is an extended version of GPSSS with much more tracing
facilities.
.s;Further information, see GPSSS.MAN.
.ifnot qz
.p
GPSSS is distributed on the SIMULA distribution tape in the following 
files: GPSSS.SIM, GPSSST.SIM, GPSSS.ATR, GPSSST.ATR, GPSSS.REL,
GPSSST.REL. An english-language manual is available in the files 
GPSSS.RNM, GPSSS.MAN. The tape also
includes IBM SIMULA versions as GPSSS.IBM and
GPSSST.IBM.
A swedish language version of the manual is included
as the files GPSSWE.RNM and GPSSWE.MAN.
.endif qz
.p -5,1,5;**** FIGURE
.index ^^FIGURE graphic package
.index ^^Graphic package for tektronix terminals
.index ^^Tektronix terminal graphics package
.index ^^Picture processing
 is a basic graphic package for handling TEKTRONIX
graphic terminals in SIMULA.
FIGURE is described in the help file FIGURE.HLP.
.br;Written by Aake Blomberg, Swedish National Defence Research Institute.
.if qz
.p -5,2,8
**** CALSIM
.index ^^CALSIM EXTERNAL CLASS
.index ^^CALCOMP Plotting CLASS
is an external CLASS with routines for plotting on a CALCOMP 835
plotter. See CALSIM.HLP.
.endif qz
.p -5,2,8
**** VISTA is a package to get full control of an alphanumerical display
.index ^^VISTA EXTERNAL CLASS
.index ^^Display terminal
.index ^^Alphanumerical display terminal
terminal. You can move the cursor freely around the screen, and produce
programs for e.g_.:
.p -2,1,4;>#Moving pictures,
.p;>#Continuously changing tables,
.p;>#Form-fill-in method of data entry with immediate validity checking
of each field,
.p;>#Table-fill-in method of data entry with immediate validity checking
of each field.
.s;VISTA will not work on all kinds of alpahnumeric display terminals.
At the time of this writing, the package works on the following
terminal types:
.s;Infoton VISTA, VISTAR SATTELITE and I 200, DEC VT52, TEC MINITEC and TELE-TEC,
BEEHIVE B100, MINIBEE, TANDBERG TDV 2000, Datamedia ELITE 1520 , 2520, 3025,
CDC 713-10, Volker 404.
.skip
Work is going on to modify it for other terminals.
In many cases, the user can in a simple way describe a new kind
of terminal by a few keystrokes when running the package.
.skip
See the VISTA.MAN handbook for current information on
which terminals can be handled by the package.
.s;VISTA.PAP contains a textual description of what can be done
with the VISTA package, VISTA.MAN(VISTA.RNM) contains a programmers manual
to the package.
.ifnot qz
.s;Files: VISTA.SIM, FORM.SIM, CAT.SIM, SHIP.SIM, QSIM.SIM, VIDED.SIM,
TERMTY.SIM, GETVIS.SIM, VIDED.MAN,
VIDED.HLP, FORMT.SIM, VISTA.RNM, VISTA.RNH, VISTA.PAP.
.endif qz
.s;Written by Jacob Palme, Swedish National Defence Research Institute.
.p -5,2,8
**** FORM package for formula input using VISTA, see above.
.index ^^FORM form fill in data entry package
.index ^^Form fill in data entry
.index ^^Input of data by form fill in
.index ^^Data entry by form fill in
.index ^^Entry of data by form fill in
.p -5,2,8
.index ^^GETVIS terminal type enquirer
.index ^^TMP:TRM file containing terminal type identification
.index ^^Terminal type enquiry
**** GETVIS procedure for finding out what kind of terminal the user
has from SWITCH.INI, TMP:TRM, command line or user input, before
calling VISTA; see above.
.p -5,2,8
**** DAHELP
.index ^^HELP facility, package for providing of
.index ^^DAHELP EXTERNAL CLASS
.index ^^Direct Access Help files
.s;The DAHELP class may be used in order to save core in
application programs when the HELP text segments are very long
and/or numerous.
.s;
If you prepare a number of sequential files with names equal to
the respective keywords, the MAKHLP program may be used in order
to create a DAHELP direct access file. This file could then
be used by the DAHELP class in order to display any of the included
(sub)files on the terminal (i.e_. Sysout). It is also possible to
make DAHELP list all entries (keywords) in the DAHELP file.
.skip
Written by Mats Ohlin, Swedish National Defense Research Institute.
.ifnot qz
Files: DAHELP.SIM, DAHELP.HLP, and in LIBSIM DAHELP.ATR, DAHELP.REL.
.endif qz
.p -5,2,8
**** SQHELP
.index ^^HELP facility, package for providing of
.index ^^SQHELP EXTERNAL BOOLEAN PROCEDURE
is a program to simplify the provision of a help facility
in a conversational program, where different parts of the help
file may be printed via different help requests in the program.
.skip
SQHELP makes a sequential search of the help file,
and displays all pages containing a certain word. Compared to
DAHELP, this has the following advantages and disadvantages:
.p -2,1,3
>#The help file can be a sequential file, readable also via
the monitor HELP command and requiring less core than direct
access files.
.p -2,1,3
>#The user can supply key words to guide
the help file search.
.p -2,1,3
>#Much slower than DAHELP, not suitable for very large help files.
.p -2,1,3
>#The search is governed by words contained in the help file
text, not by the title of the help file segments.
.ifnot qz
.s;Files: SQHELP.SIM, SQHELP.RNH and SQHELP.HLP. LIBSIM can
contain SQHELP.ATR and SQHELP.REL.
.endif qz
.s;Written by Jacob Palme and Mats Ohlin, Swedish National Defence
Research Institute.
.p -5,2,10
1.2##DEMONSTRATION PROGRAMS
.index ^^Demonstration programs
.index ^^Demo programs
.index ^^Test programs
.index ^^SIMDEM demo programs
.s;The save set SIMDEM on the SIMULA distribution tape
contains some simple SIMULA programs
which can be used to demonstrate the ideas of the SIMULA programming
language. (Written by Jacob Palme.)
.s;The programs are:
.s;QASETE, which is a very simple question-answering
.index ^^QASETE question-answering demo program
.index ^^Question-answering demo program
system accepting statements like "BOOK IS DOCUMENT. DOCUMENT IS OBJECT."
and being able to answer questions like "IS BOOK OBJECT?".
.index ^^Simulation demo program
.index ^^STAT1E simulation demo program
.s;STAT1E, which is a very simple simulation program of the transport
operation between a harbour, a store and a factory. The simulation
program lacks all tracing and result output.
.s;STAT2E is the same simulation program as in STAT1E, but with
.index ^^STAT2E simulation demo program
tracing and result output added without obscuring
the logic of the simulation program. The intention is to illustrate
the power of the SIMULA language for this kind of structured
programming.
.index Structured programming
.s;DDTDEM which is a simple program to demonstrate SIMDDT.
.index ^^DDTDEM SIMDDT demo program
.index ^^SIMDDT demo program DDTDEM
STAT1E can also be used to demonstrate SIMDDT.
.s;CAT, SHIP and QSIM are simple demonstrations of simulations
.index ^^VISTA package, applications
.index ^^CAT demo program, cat and mouse game
.index ^^SHIP demo program, troup transport simulation
.index ^^QSIM demo program, doctor's waiting room
.index ^^Simulation of troup transport
.index ^^Simulation of doctor's waiting room
.index ^^Simulation of cat and mouse game
.index ^^Game of cat and mouse
using the VISTA package for "moving pictures" on alphanumeric
display terminals.
CAT is a cat-and-mouse game on the screen, SHIP a troup transport
simulation, QSIM a simulation of a doctor's waiting room.
.s;FORMT and TABLE are simple demonstrations of the form methods
.index ^^FORM package, test programs
.index ^^Form method of data collection
.index ^^Data collection, form method
.index ^^TABLE package, test of formula data collection
for data collection, based on the VISTA package.
.subtitle 2. SIMULA SOURCE PROGRAM CONVERSION PROGRAMS
.paper size 55,65
.left margin 5;.fill;.nojustify;.page
.index ^^SIMULA SOURCE PROGRAM CONVERSION PROGRAMS
.index ^^Conversion programs
.i -5;2.##SIMULA SOURCE PROGRAM CONVERSION PROGRAMS
.i -5;---------------------------------------------
.p -5,2,9
**** SIMED
 converts SIMULA source programs to a
.index ^^SIMED SIMULA Program Editor
more readable format. The block structure is indicated by indentation
and reserved words are (optionally) capitalized to distinguish them from other
identifiers.
SIMED is described further in the DECsystem-10 SIMULA Language Handbook Part II
Appendix L.
.ifnot qz
SIMED is distributed as four files, SIMED.SIM, SIMED.HLP and SIMED.EXE.
.endif qz
.break
Written by Mats Ohlin, Swedish National Defence Research Institute.
.skip
.if notready
.i -5;**** SIMSTR [NOT READY]
.index ^^SIMSTR SIMULA PROGRAM Stripper
.break
Documents a SIMULA program by extracting only structural
lines from the program.
.skip 1
.endif notready
.i -5;**** IBMSIM
 converts SIMULA source programs from
.index ^^IBMSIM Conversion Program
IBM 360/370 to DECsystem-10. The program is described in
Appendix M.1 of the DECsystem-10 SIMULA Language Handbook Part II.
.ifnot qz
IBMSIM is distributed
as three files, IBMSIM.SIM, IBMSIM.HLP and IBMSIM.EXE.
.endif qz
.break
Written by Mats Ohlin, Swedish National Defence Research Institute.
.skip 1
.i -5;**** SIMIBM
converts SIMULA source programs from
.index ^^SIMIBM Conversion Program
DECsystem-10 to IBM 360/370. The program is described in
Appendix M.2 of the DECsystem-10 SIMULA Language Handbook Part II.
.ifnot qz
SIMIBM is distributed as
three files, SIMIBM.SIM, SIMIBM.HLP and SIMIBM.EXE.
.endif qz
.break
Written by Mats Ohlin, Swedish National Defence Research Institute.
.skip 1
.i -5;**** CDCSIM
converts SIMULA source programs from
.index ^^CDCSIM Conversion Program
CDC to DECsystem-10. The program is described in 
Appendix M.3 of the DECsystem-10 SIMULA Language Handbook Part II.
.ifnot qz
CDCSIM is distributed as
two files, CDCSIM.SIM and CDCSIM.EXE.
.endif qz
.break
.skip 1
Originally produced at the Norwegian Computing Center,
modified by Lars Enderin and Jacob Palme at the Swedish National
Defence Research Institute.
.skip 1
.index ^^SIMEXP program for merging source files
.i -5;**** SIMEXP merges a SIMULA source program
and the external modules it refers to into a single
segment. This is sometimes necessary when moving
SIMULA programs from the DECsystem-10 to other computers.
SIMEXP is described in SIMEXP.HLP
.ifnot qz
 and distributed as
SIMEXP.SIM and SIMEXP.EXE
.endif qz
_.
.break
Written by Sten Perers, Swedish National Defence Research Institute.
.skip 1
.index ^^FQC Program measurement system
.index ^^Program measurement system FQC
.i -5;**** FQC
measures the frequency with which
the statements in a SIMULA program are executed.
FQC is described in Appendix J in
the DECsystem-10 SIMULA Language Handbook Part II.
.ifnot qz
FQC is distributed as FQCRED.SIM, FQCRED.EXE,
FQCLST.SIM, FQCLST.EXE, FQC.HLP.
.endif qz
.br;Written by Stefan Arnborg,  modified by Dag Gruneau and Mats Ohlin, Swedish National Defence Research Institute.
.subtitle 3. DIRECTFILE HANDLING PROGRAMS
.ps 55,65;.f;.nj;.pg;.index ^^DIRECTFILE HANDLING PROGRAMS
.i -5;3. DIRECTFILE HANDLING PROGRAMS
.i -5;--------------------------------
.p -5,2,8
**** DIRED program
.s;.index ^^DIRED program
.index ^^Directfile text editing - DIRED
.index ^^Text editing on directfiles
A general editor for DIRECTFILEs.
.ifnot qz
.s;Files: DIRED.SIM, DIRED.SAV, DIRED.HLP.
.endif qz
.s;Written by Kalle Maekilae, Swedish National Defense Research Institute.
.p -5,2,8
**** MAKEDF program
.s;Converts a sequential file into a DIRECTFILE and vice versa.
If the sequential file is line numbered, the line numbers are
used as locations for the DIRECTFILE.
.ifnot qz
.break
Files on the distribution tape: MAKEDF.SIM, MAKEDF.EXE, MAKEDF.HLP.
.endif qz
.index ^^MAKEDF program
.s;Written by Jacob Palme, Swedish National Defense Research Institute.
.index ^^DIRSEQ program
.index ^^DIRECTFILE to seqeuential file conversion
.index ^^File conversion, to and from directfile
.index ^^Sequentail file to DIRECTFILE conversion
.p -5,2,8
**** FETCH program
.s;FETCH is part of the SIMDBM package. FETCH
allows you to access the data base directly from a terminal,
without running any programs. Changes to the SCHEMA must however
be made with the program SPEC. See further the SIMDBM documentation.
.s;Written by: Kalle Maekilae, Swedish National Defense Research Institute.
.p -5,2,8
**** MAKHLP program
.index ^^MAKHLP PROGRAM generating DAHELP files
.s;.index ^^MAKEDF program
The MAKHLP program modifies or creates a DAHELP
Direct Access Help file by appending named sequential file
references.
.s;MAKHLP can not delete any parts of the Direct Access
file. For such purposes - reconstruct the file from scratch
or use the DIRED program to patch up the file according to
DAHELP format (imagesize:73). See DAHELP.HLP for more
information.
.s;Files on the distribution tape: MAKHLP.SAV, MAKHLP.SIM, MAKHLP.HLP.
.lm 5;.s
.subtitle 4. PROCEDURES NOT WRITEABLE IN SIMULA
.paper size 55,65;.left margin 5;.fill;.nojustify
.page
.i -5;4. PROCEDURES NOT WRITEABLE IN SIMULA
.i -5;####----------------------------------
.s;NOTE: Some of these routines are not yet written. See the
list in chapter 0.2, which indicates which routines are
ready.
.s;The source code for these routines can usually be found
in the large files LIBSM1.PAC and LIBSM2.PAC. Unpack the individual files
with the program FILPAC.SAV.
FILPAC places the unpacked files on DSKD. If you want the files on another file
structure, say DSKB, do .ASSIGN DSKB DSKD before running FILPAC.
.s;.subtitle 4.1 TIME AND DATE
.index ^^TIME AND DATE
.i -5;4.1 TIME AND DATE
.s;.i -5;**** TEXT PROCEDURE TODAY
.index ^^DATE
.index ^^TODAY EXTERNAL TEXT PROCEDURE
.s;Returns a reference to a text object of length 10 with contents:
.br;"yyyy-mm-nn"
.br;where yyyy is year, mm is month(in digits 01-12), nn is day (in digits
01-31).
This is the internationally standardized format for dates.
.fill
.p -5,2,8
**** INTEGER PROCEDURE dayno
.index ^^DAYNO EXTERNAL INTEGER PROCEDURE
.s;Integer procedure DAYNO returns the ordinal day
number in current year.
.s;EXTERNAL PROCEDURE required: TEXT PROCEDURE today;
.s;.nf;BEGIN
    INTEGER day,month,year;   TEXT t;
.s;    t:- today;
    month:= t.Sub(6,2).Getint;
    day:= 30*(month-1) + (4*month-7)//6;
    IF month > 4 THEN day:= day - 1 ELSE
    IF month = 2 THEN day:= day + 1;
    IF month > 2 THEN
    BEGIN   year:= t.Getint;
	day:= IF Mod(year,400) = 0 THEN day - 1 ELSE
	day - Sign(Mod(year,4));
    END After February;
    dayno:= day + t.Sub(9,2).Getint;
.s;END of dayno;
.f;.skip 2
.test page 8
.i -5;**** TEXT PROCEDURE DAYTIME
.index ^^DAYTIME EXTERNAL TEXT PROCEDURE
.s;Returns a reference to a new text object of length 8 with contents:
.nofill
"hh:mm:ss"
where hh        is hours
      mm        is minutes
      ss        is seconds.
at the time of the call.
.fill
.s;This is the internationally standardized format for writing time-of-day.
.if notready
.p -5,2,8
**** PROCEDURE TIMELIMIT(maxtime);   REAL maxtime;
.s;.index ^^TIMELIMIT EXTERNAL PROCEDURE
.s;The execution will be interrupted when the allotted time is up.
The parameter is the time limit in seconds.
If the argument is non-positive, the effect will be as if TIMELIMIT was never called.
.endif notready
.p -5,2,8
**** REAL PROCEDURE CPTIME
.index ^^CP(U)TIME EXTERNAL REAL PROCEDURE
.s;Returns total CPU time spent since the beginning of
                the SIMULA program execution, expressed in                
seconds.
.skip 2
.test page 8
.i -5;**** REAL PROCEDURE CLOCKTIME
.index ^^CLOCKTIME EXTERNAL REAL PROCEDURE
.s;Returned value is time of day in  seconds, i.e. the absolute
difference between the results of two successive calls
is the time which elapsed between the calls (except when
passing midnight).
.SUBTITLE 4.2 REAL-TIME FOR MULTI-TERMINAL SIMULTANEOUS I/O.
.index ^^REAL-TIME FOR MULTI-TERMINAL SIMULTANEOUS I/O.
.lm 5
.p -5,4,28
4.2 REAL-TIME FOR MULTI-TERMINAL SIMULTANEOUS I/O.
.nt;These procedures will usually not work on the DECsystem-20 under the
TOPS-20 monitor.
.en
.s;The goal of this is to allow one program to talk simultaneously
to several conversational terminals and other on-going processes (jobs) in
the computer. A break in one such dialouge should not inhibit
the conversation with the other terminals and processes.
.s;Chapter 4.2.1 below describes three simple assembly
procedures which you can use if you want to write your
own scheduling of the parallel processes for handling
the external devices.
.s;Chapter 4.2.2 and appendix A describe a simple scheduler
for realtime applications written in SIMULA. The scheduler
allows you to use SIMULA processes, one for each external
device.
.fill
.p -5,2,15
4.2.1 BASIC ASSEMBLY PROCEDURES FOR REAL TIME
.s;.i -5;**** BOOLEAN PROCEDURE INPUTCHECK(inputfile);
.br
REF (infile) inputfile;
.s;.index ^^INPUTCHECK EXTERNAL BOOLEAN PROCEDURE
The parameter infile is connected to an external device or another job process.
INPUTCHECK will return TRUE if an INIMAGE can be made on
the INFILE without delay, that is if data for the INIMAGE is already
available.
If the external device has no pending input, INPUTCHECK will
return FALSE. INPUTCHECK will also return FALSE if the parameter
is NONE, refers to a closed file or refers to a file where
ENDFILE is TRUE.
Supported devices are those which can be used from SIMULA.
DSK is regarded to be ready for input without delay.
(WARNING: INPUTCHECK may not work when heavy transmission of
data is going on to the same terminal. In that case, use of the
TTYCHECK procedure may be a better alternative.)
TTY and PTY are the primary devices considered.
See PTYCHECK etc in section 7 of this handbook.
.br;NOTE: Will not work on DECsystem-20!
.p -5,1,5
**** PROCEDURE SLEEP(sleepsec);   REAL sleepsec;
.s;This procedure takes one parameter of type
.index ^^SLEEP EXTERNAL PROCEDURE
REAL and will stop the execution for a real time interval of at least
this duration.
Resolution is 0.001 on a DECsystem-10.
.br;A special version is needed on the DECsystem-20 (uses DISMS JSYS).
.p -5,1,10
**** INTEGER PROCEDURE INPUTWAIT(filearray,maxtime);
.br;REF (infile) ARRAY filearray; REAL maxtime;
.index ^^INPUTWAIT EXTERNAL INTEGER PROCEDURE
.s;NOTE: This procedure will not work on DECsystem-20!
.s;This procedure stops the executing
SIMULA program until INPUTCHECK would be TRUE for at least
one of the parameter files, or until MAXTIME seconds have elapsed.
MAXTIME = 0 indicates
no time limit on the wait.
Some of the array elements may be NONE.
Whenever INPUTCHECK would be TRUE for one of these files,
execution of the SIMULA program continues.
If INPUTCHECK is already TRUE for one of the files when
INPUTWAIT is called, then
INPUTWAIT will return immediately to the calling program.
The procedure returns an integer
which is the index of a file in the parameter array
from which input has
been received, not necessarily the first one if input has been
received from more than one of the input files.
INPUTWAIT disregards those array elements which are NONE or
which refer to closed files, and files with ENDFILE = TRUE.
If all the array elements are disregarded
in this way, then inputwait does not stop execution but
returns an integer which is 1 less than
the lower bound of the parameter array.
If the wait was interrupted becuse of the time limit maxtime,
then an integer which is 2 less than the lower bound of the
parameter array is returned.
.br;Special feature: If the first file to wake up the program is a PTY file,
and it has no output ready (ready for Inimage), but it can accept input
(i.e_. output on the corresponding Outfile), the returned value is the array
index as above + 2_^18.
.lm 5;.sp 1;.nj
.p -5,4,15
4.2.2 REALTIME - A SCHEDULER FOR TERMINAL PROCESSES
.f;.s;REALTIME is a separately compiled CLASS written in SIMULA as
a subclass to SIMULATION. REALTIME is based on the idea
that you have one SIMULA process connected to
each conversational terminal. The processes can then execute
in parallel, and the SIMULATION scheduler is used to
distribute the execution between the terminals. The CLASS
REALTIME is not only useful for simulation programs,
it can also be used for other real time applications.
.s;A full description is included in appendix A.
.s;REALTIME will not work on DECsystem-20.
.subtitle 4.3 INPUT/OUTPUT
.p -5,4,28
4.3 INPUT/OUTPUT
.fill;.s;.subtitle 4.3.1 ASCII-FORMATTED I/O
.i -5;4.3.1 ASCII-FORMATTED I/O
.index ^^INPUT/OUTPUT
.s;.i -5;**** INTEGER PROCEDURE linecount(pf);
.br;REF (Printfile) pf;
.index ^^LINECOUNT EXTERNAL INTEGER PROCEDURE
.s;The parameter should be a reference to an open printfile object.
Result: Returns the value of the LINESPERPAGE attribute of the printfile.
.skip 2
.i -5;**** TEXT PROCEDURE filename(x);
.br;REF (FILE) x;
.s;.index ^^FILENAME EXTERNAL TEXT PROCEDURE
The parameter
should be a simple valid reference to an object
of an I/O class.
Returns a reference to a text object whose value is equal to the
NAME parameter of the FILE object. The resulting text value may or may not be stripped of
blanks before return.
.p -5,2,8;**** CHARACTER PROCEDURE insinglechar(inf);
.br;REF (Infile) inf;
.index ^^INSINGLECHAR EXTERNAL CHARACTER PROCEDURE
.s;The parameter should be a reference to an infile object using
a terminal or a disk file.
Returns next input character from the infile
 (after last INIMAGE)
without waiting for break character.
Succeeding INIMAGE will begin reading after the last character which has been
input with INSINGLECHAR.
.s;Restriction: With the current release of DECsystem-10 SIMULA, INSINGLECHAR only
works on the controlling terminal or a disk file.
.p -5,2,8;**** CHARACTER PROCEDURE insngl(inf);
.br;REF (Infile) inf;
.index ^^INSNGL EXTERNAL CHARACTER PROCEDURE
.s;The parameter should be a reference to an infile object using
a terminal or a disk file.
Returns next input character from the infile (after last INIMAGE).
Unlike INSINGLECHAR, it works in line mode (waits for break character).
Succeeding INIMAGE will begin reading after the last character which has been
input with INSNGL.
.p -5,2,8;**** CHARACTER PROCEDURE getch
.index ^^GETCH EXTERNAL CHARACTER PROCEDURE
.s;GETCH is similar to INSINGLECHAR (see above) but has no parameter and always takes input
from the conversational terminal controlling the current job.
.fill
.p -5,2,8
**** BOOLEAN PROCEDURE ttycheck(timelimit); REAL timelimit;
.index ^^TTYCHECK EXTERNAL BOOLEAN PROCEDURE
.s;TTYCHECK waits for an input character from the terminal and returns with the
value TRUE if a character is typed in before TIMELIMIT seconds have elapsed,
otherwise false. TIMELIMIT should not be greater than about 60 seconds.
If TIMELIMIT is exactly zero, TTYCHECK waits indefinitely for input.
TTYCHECK does NOT read the input, only checks for it. GETCH can be used to
read the actual character when TTYCHECK returns TRUE.
Ordinary SIMULA input procedures can also
be used provided a line is typed in.
.p -5,2,15
**** PROCEDURE outchr(ofile,c,n);
.index ^^OUTCHR EXTERNAL PROCEDURE
.index ^^Output of CHARACTER immediately
.index ^^CHARACTER output, direct
.br;REF(Outfile)ofile; CHARACTER c; INTEGER n;
.s;Outputs n identical ASCII characters to the file,
which is normally a terminal.
Ofile.Image is not affected.
.br;If n<=0, no character is output, otherwise the character c is output n times.
The buffer is used directly.
.s;Note: Use "forceout" before terminal input after the use of "outchr".
Warning: ofile must be open, otherwise outchr will loop!
.p -5,2,15
**** PROCEDURE outstring(ofile,t);
.index ^^OUTSTRING EXTERNAL PROCEDURE
.index ^^Output of TEXT immediately
.br;REF(Outfile) ofile; TEXT t;
.s;Copies the text T directly to the output buffer bypassing Image.
T is not changed. No output is forced.
Output will appear when (Break)Outimage or FORCEOUT is called.
ofile == NONE is treated as Sysout.
.s;Note: Use "forceout" before terminal input after the use of "outstring".
.p -5,2,7
**** PROCEDURE forceout(ofile);
.index ^^FORCEOUT EXTERNAL PROCEDURE
.index ^^Output, forced, to the TTY
.br;REF(Outfile)ofile;
.skip;Ensures that all previous output to the TTY made with
OUTCHR or OUTSTRING reaches the TTY. Use FORCEOUT before inputting anything
from the terminal, to ensure that previous output reaches
the terminal. FORCEOUT checks if there is any unwritten
output in the buffer, so you can call it with little cost
before every input operation.
.P 0,1,10;A procedure similar to FORCEOUT, but much slower, could be written
in SIMULA:
.s;.nf;BEGIN TEXT image_copy;
  image_copy:- ofile.image;
  ofile.image:- NOTEXT;
  ofile.breakoutimage;
  ofile.image:- image_copy;
END;
.fill;.p -5,2,15;**** PROCEDURE read(..)
.index ^^READ EXTERNAL PROCEDURE
.s;Any parameters of type integer, (long) real or
character. A reference type parameter, if used, must
be a reference to an object of class infile or
directfile. A parameter may be an array identifier of
suitable type.
.s;New values for the actual parameters are obtained one by one
from the current input file (initially SYSIN). If a parameter is an
array identifier, new values are read and assigned for all
elements of the array. A parameter which is
a reference to an open infile or directfile causes
all successive read operations (in the parameter list) to be
applied to this file.
.p -5,2,17
**** PROCEDURE write(..)
.index ^^WRITE EXTERNAL PROCEDURE
.SKIP
Any parameters of type integer, (long) real,
character or text. Constants and arrays are also allowed.
A reference type parameter, if used, must be a simple
reference to an object of class outfile, printfile
or directfile.
.SKIP
Values of actual parameters are output one by one on the
current output file (initially SYSOUT). The output formats
for the respective values are
.skip
.fill
.left margin 21
.tab stops 21
                this machine plus 1
.i -16;INTEGER i	outint(i,n) where n is the number of digits
                printed for the largest possible integer on
		this machine plus 1
.s;.i -16;REAL x	print x in flexible format according to:
.skip;.nofill
if x = 0 then outfix(x,0,w) else
if abs(x) >= 10_^d then outreal(x,d,w) else
if abs(x) >= 10_^(-e) then
outfix(x,d-ilog(x)+(if abs(x) >= 1 then 0 else -1),w)
else outreal(x,d,w);
.skip
.fill
where d is number of significant digits, e is number of positions required
for the exponent part and w := e + d + 2 (sign and dot positions).
.s;.i -16;LONG REAL z	same as for real but for long real significance
.s;.i -16;CHARACTER c	outchar(c)
.s;.i -16;TEXT t	outtext(t)
.lm 5
.fill
.s;If the actual parameter is an array identifier, the values
of all its elements are output. A parameter which is a
reference to an open printfile, outfile or directfile,
causes all successive output operations to be applied to
this file.
Each call on WRITE ends with a call on OUTIMAGE which also
is called implicitly if the image is filled before all parameters
are processed. The final OUTIMAGE concerns every file mentioned;
thus OUTIMAGE (for the previous file) is called when a new file reference is given as well as
at the end of the parameter list.
.index ^^Unformatted input/output
.index ^^Record input/output
.index ^^Object input/output
.index ^^Binary input/output
.SUBTITLE 4.3.2 UNFORMATTED (BINARY) I/O.
.index ^^UNFORMATTED (BINARY) I/O.
.p -5,3,15
4.3.2 UNFORMATTED (BINARY) I/O.
.SKIP 1
.skip
.nofill
***********************  WARNING  **************************
* Use of the procedures described in this section may make *
* your programs difficult to move to another SIMULA system.*
************************************************************
.skip
.fill
Unformatted I/O is a tricky problem because we have many diverse
requirements to put together, if possible, in one construct.
.skip 1
.indent -2
>#Very fast and efficient input and output of much data.
.indent -2
>#Simple input and output procedures, taking whole texts, arrays,
or objects at a time.
.indent -2
>#General purpose input and output procedures, to be able to read and write easily any kind of file,
e.g. a file containing line numbered lines, an object program
file, a file which was produced by FORTRAN binary output, a disk
directory file etc.#etc.
.index ^^INPUT EXTERNAL INTEGER PROCEDURE
.index ^^OUTPUT EXTERNAL INTEGER PROCEDURE
.SKIP 1
Two procedures INPUT and OUTPUT have been written.
.skip
The first
parameter to INPUT is a reference
to an object of the CLASS infile or directfile,
the first argument to OUTPUT is a reference to an object of
the CLASS outfile or directfile.
.skip 1
Both these procedures can take any number of additional parameters of any
SIMULA type except label, switch or procedure. The action of OUTPUT is:
.skip
.indent -5
**** INTEGER PROCEDURE OUTPUT
.skip 1
OUTPUT returns the number of characters (over)written
in the file. (Including any output produced which is not directly
related to the parameters, e.g. null characters, null words etc.
IF OUTPUT is made on a DIRECTFILE, it may be important for the user
to know how many lines on the file that are covered by one or
several calls to OUTPUT. He can do this by dividing the sum of the INTEGERs
returned from OUTPUT with (image.length+2) of the directfile.
Such a program will be machine-independent since OUTPUT returns number
of characters.
.skip
For parameters of type INTEGER, [LONG]REAL or BOOLEAN:
the value of the parameter is output in such a way that it can be read by
a FORTRAN program.
One word (36 bits on the DECsystem-10) is output.
Two words (72 bits) are output for LONG REALs.
.skip 1
For parameter of type CHARACTER: The internal value is output. SIMULA systems
which pack CHARACTERs in words will output only the character byte, systems
which store CHARACTERs in full words will output the full word.
.skip 1
For parameters of type TEXT:
First the LENGTH of the TEXT is output in the same way as if it
had been given as an explicit INTEGER parameter to OUTPUT.
Then the characters of the text value are output in internal
implementation dependent format
 (ASCII-7-bit
code packed 5 characters to a word on the DECsystem-10).
If the characters
are packed
 (as they are on the DECsystem-10)
and the last output word is not
full, then it is filled with NULL characters.
The output TEXT value may #n#o#t# be preceded by NULL characters to permit
faster output of subtexts.
NOTEXT is output as only the integer LENGTH(=0), and nothing more.
.skip
All  characters which can be created with the procedure CHAR
can be part of a TEXT which is written
by OUTPUT and read by INPUT, and they should all be returned unchanged
after OUTPUT and a corresponding INPUT.
.skip
Note that for subtexts, only the subtext part of the value is output.
If several texts have a common part, the value is still output completely
for each text.
.skip
For parameters of kind ARRAY:
Each element of the ARRAY is output just as if it
had been a non-array parameter to OUTPUT. (Even for REF-arrays.)
The dimensions and bounds of the ARRAY are not output.
.skip 1
For parameters of type REF:
.break
All value attributes of
the referred object except REF and REF-array
attributes are output just as if these
attributes had been parameters to OUTPUT.
REF or REF ARRAY attributes are not output at all.
.skip
OUTPUT may, in an implementation dependent way, output other
descriptive data about the structure of the CLASS to ensure
correct input by INPUT as described below.
.skip
If the argument to OUTPUT has the value NONE, then some kind of
indication about this is output.
.skip
The order in which the attributes are output is implementation
dependent, and not necessarily the same as the order in which they
are declared in the SIMULA source program.
.skip
Important: If the parameter to OUTPUT is qualified by a SUPERCLASS (an outer class) of the actual
object to which it refers, then only attributes of the SUPERCLASS are output.
.p -5,2,10
**** INTEGER PROCEDURE INPUT
.skip
.index ^^INPUT EXTERNAL INTEGER PROCEDURE
INPUT works analogously
with OUTPUT so that anything written
with OUTPUT can be read with INPUT.
.skip
The INTEGER value returned by INPUT is the number of characters read (see
OUTPUT). If all the data required  could not be read because of end of
file, the negated number of characters that were read is returned.
A call to INPUT when ENDFILE is already TRUE causes an error interrupt.
.skip 1
For TEXT parameters, INPUT allocates a new
TEXT of appropriate length using BLANKS and reads the 
string into the new TEXT. POS of the new text is set to 1.
.skip 1
For ARRAY parameters: INPUT works just as if INPUT had been
called once for each item in the array.
.skip 1
For REF parameters: INPUT may do a certain amount
of implementation dependent checking
for agreement between the data in the file and the structure of the
class to which the REF parameter refers.
Those attributes of the CLASS which were output with
OUTPUT will then be read in. 
TEXTs will be allocated with POS = 1 and LENGTH  as from the
file.
.skip
INPUT will only work correctly for REF parameters if the data at that
place in the file was previously written via a REF parameter to OUTPUT
in a SIMULA program,
and if the qualification of CLASS object which was
output and the qualification of the parameter 
which is input from the same place in
the file agree in the following respects:
.break
.p 0,1,0;.ls;.le;The order and type of all attributes which are output and later
input agree.
.le;An attribute which was a parameter to the CLASS in OUTPUT must
also be a parameter in INPUT.
.le;If the CLASS has superclasses, then the attributes
must be distributed between the subclasses in the same way.
.le;The number and bounds of the dimensions of ARRAY attributes
must agree.
.le;If the argument to OUTPUT had the value NONE, then
the corresponding argument to INPUT must also have the value
NONE.
.els
However, even if the requirements above are not fulfilled,
INPUT is still protected from changing any data in core except
attributes of the CLASS of type
INTEGER, REAL, LONG REAL, CHARACTER or TEXT, which are accessible
to the programmer.
.skip
The following characteristics need #n#o#t# agree between
the CLASS in INPUT and the CLASS in OUTPUT:
.break
.p 0,1,0;.ls;.le;The SIMULA source program identifier names of the attributes.
.break
.le;Number, type, qualification etc.#of attributes which were not
output with OUTPUT (e.g.#REF or PROCEDURE attributes).
.break
.le;The executable code in the CLASS.
.break
.le;The structure of such subclasses which were not output
with OUTPUT because of the qualification of the REF parameter to OUTPUT.
.els
Note that the data OUTPUT with an OUTPUT statements does not constitute
any "logical block". It is therefore possible to output certain
data with "OUTPUT(file,a,b);" and then input the data
with "INPUT(file,a); INPUT(file,b);".
.skip
The organisation of files produced by OUTPUT and read by INPUT should,
if reasonably possible, be such that FORTRAN programs on the same
computer can read and write such files.
.skip
.p -5,1,8
.index ^^PUTSIZE EXTERNAL INTEGER PROCEDURE
**** INTEGER PROCEDURE PUTSIZE
.s;To help the programmer avoid overwriting previous information
in a directfile there is an auxiliary INTEGER PROCEDURE PUTSIZE with
.index ^^DIRECTFILE binary I/O
the same kind of parameters as OUTPUT, except for the first parameter
(giving the output file) which need not be given to PUTSIZE.
PUTSIZE will return
the same integer as would be returned by OUTPUT if called with
an identical parameter list.
.if notready
.p -5,1,6
**** BOOLEAN PROCEDURE BYPASS
.index ^^BYPASS EXTERNAL BOOLEAN PROCEDURE
.s;BOOLEAN PROCEDURE BYPASS(fileref,x) will move the internal buffer
pointer x characters. X may be
negative if fileref is a directfile.
If end of file is encountered for an infile, BYPASS should return TRUE the
first time; if called again a run time error should occur.
The first parameter may refer to any kind of file except a printfile.
.skip
.p -5,2,5
.index ^^LOOK EXTERNAL BOOLEAN PROCEDURE
.s;There is a further BOOLEAN PROCEDURE LOOK which takes two
parameters, the first a reference to an infile object, the second
of type INTEGER, [LONG] REAL or CHARACTER. LOOK examines the
next word in the input buffer without reading it.
Array parameters are not allowed.
Should return TRUE if end of file is encountered;
run time error for the next call.
.skip 1
LOOK might for example be used to check if a line is line numbered
before reading the line.
.skip 1
.endif notready
.skip
.indent -5
COMBINING OUTPUT AND INPUT WITH INIMAGE AND OUTIMAGE.
.skip
Future versions of DECsystem-10 SIMULA may, because of standardization
work with other SIMULA systems, forbid the combination of OUTIMAGE
and INIMAGE with OUTPUT and INPUT on the same file. The user is
strongly recommended not to use such a combination.
.skip
At your own risk, OUTPUT and INPUT can
be combined with OUTIMAGE and INIMAGE on the same
file.
The file may be padded with NULLs after OUTIMAGE to a word
boundary before the data written by OUTPUT.
OUTPUT and INPUT do not work through the IMAGE of the file, which
is thus not touched in any way.
.skip
For DIRECTFILES, OUTPUT and INPUT will not change the value of
LOC. The first OUTPUT or INPUT after an INIMAGE, OUTIMAGE or LOCATE
will start at the indicated location. Successive OUTPUTs or INPUTs will
start at the place in the file where the previous OUTPUT or INPUT stopped.
A call to LOCATE preceding OUTPUT or INPUT will cause the OUTPUT/INPUT operation
to start at the indicated position.
Note that this means that an OUTIMAGE immediately after an OUTPUT
may overwrite what was output with the OUTPUT.
(Since LOC was not changed). OUTPUT may overwrite several lines
in the directfile.
.skip
OUTPUT and INPUT are allowed on INFILEs, OUTFILEs and DIRECTFILEs but not
on PRINTFILEs.
.skip
WARNING!!!! The procedures above
have not been approved by the SIMULA DEVELOPMENT GROUP. If
your programs rely on them, they may be difficult to transfer
to SIMULA systems on other computers than the DECsystem-10.
This is especially true if you combine OUTIMAGE and INIMAGE
with OUTPUT and INPUT on the same file.
.subtitle 4.3.3 FILE HANDLING
.p -5,4,28
.if notready
.index ^^FILE HANDLING
4.3.3 FILE HANDLING
.skip
.index ^^REWIND of magtapes
.index ^^BACKSPACE of magtapes
.index ^^UNLOAD of magtapes
.index ^^ADVANCE of magtapes
.endif notready
.index ^^LOOKUP of files
.index ^^FINDINFILE EXTERNAL REF (INFILE) PROCEDURE
.index ^^FINDPRINTFILE EXTERNAL REF (PRINTFILE) PROCEDURE
.index ^^Deleting files
.index ^^Scratching files
.i -5;**** REF (infile) PROCEDURE FINDINFILE(filespec);
.br;VALUE filespec; TEXT filespec;
.s;.i -5;**** REF (directfile) PROCEDURE FINDDIRECTFILE(filespec,update);
.index ^^FINDDIRECTFILE EXTERNAL REF (DIRECTFILE) PROCEDURE
.br;VALUE filespec, update;
.br;TEXT filespec; BOOLEAN update;
.break
.skip
.indent -5
**** REF (outfile) PROCEDURE FINDOUTFILE(filespec);
.break
.index ^^FINDOUTFILE EXTERNAL REF (OUTFILE) PROCEDURE
VALUE filespec;
.break
.skip
.indent -5
**** REF (printfile) PROCEDURE FINDPRINTFILE(filespec);
.break
.index ^^FINDPRINTFILE EXTERNAL REF (PRINTFILE) PROCEDURE
VALUE filespec;
.break
.skip
The four procedures findinfile, finddirectfile, findoutfile
and findprintfile
are rather similar to the statements NEW infile, NEW directfile,
NEW outfile, NEW printfile. The difference is that the value NONE is returned,
if such a file cannot be opened. For directfiles,
if the input parameter update is TRUE, NONE is also returned if
such a file cannot be opened for output.
.skip
Reasons why a file cannot be opened may be:
.skip
.indent -2
> That an infile does not exist.
.indent -2
> That the file exists, but the file protection system of the
computer does not allow opening.
.indent -2
> For a directfile with update=TRUE or for an outfile: That
you cannot open the file because someone else is updating it.
.skip
If possible, the indicated file is reserved for the user
so that "a:- finddirectfile(....,TRUE); a.open;" will not fail
because someone else opens the file between the two procedure
calls in the example.
.skip
Example of use:
.skip
.nofill
FOR D:- finddirectfile("....",TRUE)
WHILE D == NONE DO sleep(10);
.fill
Will sleep until the directfile is updateable.
.skip 1
.skip 1
.indent -5
**** BOOLEAN PROCEDURE SCRATCHFILE(filespec);
.index ^^SCRATCHFILE EXTERNAL BOOLEAN PROCEDURE
.br;VALUE filespec; TEXT filespec;
.s;If the file indicated by filespec exists and the program is allowed to
delete (scratch) it, the file is deleted (scratched).
The result is TRUE if a file could be
deleted, FALSE if no file could be deleted.
Delete (scratch) implies removing the file so
that it becomes inaccessible to this and other programs
on the computer.
File specifications of the form TMP:xxx are also acceptable and refer to incore
files handled by the TMPCOR UUO on the DEC-system-10.
.if notready
.p 0,2,8
.nofill
.indent -5
**** PROCEDURE CLOSEOPEN(f); REF (file) f;
.index ^^CLOSEOPEN EXTERNAL PROCEDURE
.s;Closes and opens a file again. If the file
is an infile, this will mean that input will start from the beginning
of the file. If it is an out(print)file, then - if it was defined
with /ACCESS:APPEND, the result up to point of calling
CLOSEOPEN, will be secured against system break-down, else -
the old information will be lost at next close.
.s;INSPECT f DO
BEGIN TEXT t;
   t:- image; close; open(t);
END;
.endif notready
.lm 5;.nj;.nf
.p -5,2,8;**** BOOLEAN PROCEDURE DOTYPEOUT(tty); REF (outfile) tty;
.index ^^DOTYPEOUT EXTERNAL BOOLEAN PROCEDURE
.index ^^CTRL-O bit resetting
.index ^^_^O bit resetting
.s;IF tty == conversational terminal AND
the computer can restart typeout to the terminal
THEN restart this typeout, beginning with the
next outimage or breakoutimage, return TRUE;
.f;COMMENT on the DECsystem-10, the CTRL-O bit is reset;
.p -5,2,8;**** INTEGER PROCEDURE LASTLOC(df);
REF (directfile) df;
.index ^^LASTLOC EXTERNAL INTEGER PROCEDURE
.s;Lastloc returns the highest location of any image which has
been written in the directfile during this or any previous use of the file.
Returns -1 when the directfile is not open.
.if notready
.p -5,1,5;**** INTEGER PROCEDURE MAXLOC(df);
REF (directfile) df;
.index ^^MAXLOC EXTERNAL INTEGER PROCEDURE
.s;Maxloc returns the largest integer such that "locate(maxloc); outimage;"
will not cause any error interrupt of the program.
.endif notready
.fill
.subtitle 4.4 CONTROLLED ERROR HANDLING.
.p -5,4,28
4.4 CONTROLLED ERROR HANDLING.
.index ^^CONTROLLED ERROR HANDLING.
.lm 5;.nj
.s;See also the procedures SCANREAL, SCANINT and SCANFRAC
in chapter 5 of this handbook for control of bad data errors.
.s;A proposal for advanced integrated error handling is described in
appendix B. It is not implemented and no promise is made to ever do that.
.p -5,1,8
.p -5,4,28
.index ^^ERROR INTERRUPT ROUTINES
.indent -5
.index ^^ENTERDEBUG EXTERNAL PROCEDURE
.index ^^SIMDDT, procedure for calling
**** PROCEDURE enterdebug(maycontinue);
BOOLEAN maycontinue;
.break
.fill
.s;The debugging system
is entered. If maycontinue is TRUE, execution of the
SIMULA program is allowed to resume after the debugging session.
.nofill
.p -5,2,8
**** PROCEDURE abort(message); VALUE message; TEXT message;
.index ^^ABORT EXTERNAL PROCEDURE
BEGIN
   IF message =/= NOTEXT THEN
   BEGIN
     outimage;
     outtext("EXECUTION TERMINATED "
     "DUE TO CALL OF ERROR PROCEDURE");
     outimage;
     outtext("MESSAGE: "); outtext(message); outimage;
   END;
   enterdebug(FALSE);
END;
.fill
.p -5,2,8
**** PROCEDURE forsim(n); INTEGER n;
.s
.index ^^FORSIM EXTERNAL PROCEDURE
FORTRAN subroutines called from SIMULA are not allowed to do I/O
or otherwise access the FORTRAN high segment, since SIMULA requires
the SIMULA high segment. If you want to use a FORTRAN subroutine
which uses facilities in the FORTRAN high segment, you can load your
program with the FORSIM procedure. References from FORTRAN subroutines
to the FORTRAN high segment will then be trapped by FORSIM. Note however
that FORSIM does not perform any actual I/O, so the I/O in FORTRAN
subroutines will become dummy statements.
.br;FORSIM may also be called from FORTRAN with no parameter.
.s;.nf;If n=0,			any attempt at I/O in a FORTRAN routine
			is trapped and a message is written the
			first time,  but execution continues.
.s;If n>0,			execution continues n-1 times,
			and then the message is typed followed by
			an error entry into SIMDDT.
.s;If n<0,			execution continues, and no message
.br
			is typed.
.subtitle 4.5 SCHEDULING AND JOB CONTROL
.f;.p -5,4,28
.index ^^SCHEDULING AND JOB CONTROL
4.5 SCHEDULING AND JOB CONTROL
.p -5,2,8
**** PROCEDURE run(filespec,entrypoint);
.br;VALUE filespec; TEXT filespec; INTEGER entrypoint;
.index ^^Transferring control to another program, RUN procedure
.index ^^RUN EXTERNAL PROCEDURE
.s;FILESPEC is a text expression specifying
a file containing an executable
program.
RUN will transfer control to the program specified without
closing files. If the program is not found in the user area,
and device and ppn were not given, SYS: is tried as device. On
failure, RUN aborts via HALT.
.BR;NOTE: If the RUN procedure is loaded in the high segment, it will
be wiped out. Thus only one attempt can be made.

.s;ENTRYPOINT is an integer in the range [1,16], which specifies where
the program should be started. ENTRYPOINT = 1 is the normal value and
specifies the standard entry point which is used when the program is
executed via a monitor RUN command or the sequence GET, START.
The value 2 corresponds to the secondary entry of standard CUSP's like PIP,
COMPIL, MACRO, LINK, SIMULA. When started in this way, the CUSP will try to
read a temporary command file, which may be in core as a so-called TMPCOR
file with a three-character name, e.g_. PIP or SIM.
.s;If the CUSP does not find the relevant TMPCOR file, it will look for a disk
file with a name of the form jjjppp.TMP, where jjj is the decimal job number
with leading zeros if necessary, and ppp is the three-character name.
Examples: 007PIP.TMP, 129SIM.TMP.
.s;Filenames with the required format can be generated by the procedure TMPNAM.
Normally, a CUSP command file contains several lines specifying
output and input files. The last line can be a file specification for an
executable program, followed by "_!", e.g_. a LOAD or EXECUTE command will generate a command
file to the compiler whose last line is "LINK!" specifying that LINK-10
should get control at its secondary entry point.
.s;Command files may thus be generated in a SIMULA programs, and by using SAVE
and RUN together, control may be automatically regained after executing another program.
.s;Example: A SIMULA program could first save itself by calling the
procedure SAVE (see  below), then generate a command file to
PIP, then call PIP with the procedure RUN,
then via _! in the PIP command file cause PIP to return control
to the saved SIMULA program.
.if notready
.p -5,2,8
**** BOOLEAN PROCEDURE submit
.index ^^SUBMIT EXTERNAL BOOLEAN PROCEDURE
.SKIP
.indent -5
Parameters:     One text reference or text constant.
.SKIP
.indent -5
Result: The parameter is a file reference with the same format
as the text parameter to the class INFILE.
The file, if found, is put into the input batch stream on the
computer.
Returns TRUE if this could be done, FALSE otherwise.
.skip 1
The current job continues, independent of the new file in the
batch stream.
.endif notready
.skip 1
.indent -5
**** INTEGER PROCEDURE save(filespec,continueonerror);
.break
VALUE filespec; TEXT filespec; BOOLEAN continueonerror;
.skip
.index ^^SAVE EXTERNAL INTEGER PROCEDURE
The PROCEDURE save forces a garbage collection and then
outputs all dynamic memory to the file described by filespec.
The default file extension is .SAV, which is supplied if no extension
appears in filespec.
If filespec==NOTEXT, FREEZE (see below) is called from SAVE.
.skip
The second parameter, CONTINUEONERROR, is TRUE if error messages from SAVE
should be suppressed. Failure will be indicated by the returned value, see below.
If CONTINUEONERROR is FALSE, the run time system may issue error messages and
demand user response. This may eventually lead to successful completion if
the user elects to proceed after dealing with the error messages.
.skip
Save returns a value which indicates program status on continuation.
The possible values for the returned value (S) are:
.skip
S<0: Some error occurred, e.g_. the file specified may be protected.
The program may try to recover by giving another file specification and
calling SAVE again.
.skip
S=0: The program was continued directly, save was successful.
This value is also returned if RESTORE was called, see below.
.skip
1<=S<=16: The program was restarted via the RUN procedure or an equivalent
command or code sequence. The normal value 1 is assumed when the saved file
is executed by a RUN monitor command or by the RUN procedure with second
parameter = 1. Values 2-16 occur if the second parameter to the
RUN procedure is 2-16.
.nf
.p -5,2,9
**** PROCEDURE restore(filespec); VALUE filespec; TEXT filespec; 
.index ^^RESTORE EXTERNAL PROCEDURE
.fill
.s;The procedure RESTORE restores dynamic memory to the contents
of the file indicated by filespec. Execution is then resumed
following the point where SAVE (or FREEZE) was called to create
the file indicated by filespec.
SAVE is ignored and a warning message
is issued when any file except sysin or sysout is open.
.c;****#WARNING#****
.br;Sysin and sysout should both be the user terminal, since they will be read
and written from the start when restarting, unless sysout is written in
append mode (switch /ACCESS:APPEND).
.skip
Sysin and sysout can also refer to the .CTL and .LOG file of
a batch job.
.skip 1
The SAVE-RESTORE facility is intended primarily for applications with a fairly
time-consuming build-up phase, such as a large simulation, where one wants to
explore different continuations from the same branching point.
Together with the RUN procedure, which works like an extended RESTORE, one
can build a "program system" consisting of many segments
controlled almost fully by one or
several SIMULA programs.
See further the RUN procedure (above).
.skip 1
.indent -5
**** PROCEDURE freeze(returncode);
.break
 NAME returncode; INTEGER returncode; 
.index ^^FREEZE EXTERNAL PROCEDURE
.s;FREEZE is a simpler and smaller version of SAVE. The parameter
RETURNCODE assumes the same values as SAVE.
The files of the program are handled as in SAVE. FREEZE does not itself write a save
file but exits to monitor level, where the user can issue a SAVE command with
an appropriate file name. Execution can be continued by a START command, which
will give a returned value = 1 in RETURNCODE. (START can also be given with a
non-zero argument, but this is tricky and not generally recommended, since it
is impossible to guard against wild results).
The saved file can be handled as explained above.
If no save file is wanted, the user simply issues a CONTINUE command, giving
the result RETURNCODE = 0, and execution continues.
.p -5,1,5;**** PROCEDURE exit(n);
.index ^^CONTROL-C, simulated from program
.index ^^CTRL-C, simulated from program
.index ^^_^C, simulated from program
.index ^^EXIT, immediate, from execution
.index ^^STOP, immediate, of execution
.index ^^EXIT EXTERNAL PROCEDURE
.br;INTEGER n;
.s;EXIT(0) terminates the program immediately, exactly as if the user had typed
CONTROL-C (twice). Useful if you want your program to
terminate with some short message like "Thank you." instead
of the standard message "End of execution...". Note that you have
to close your files (except TTY files) explicitly, since no checking
of open files will occur. EXIT(0) is therefore also useful
where the program is to terminate without closing all files - not invoking
the standard SIMDDT action.
Note that if EXIT(0) is called just before last END, CONTINUE
will cause the standard termination message "End of execution.."
to appear. One additional  CONTINUE will invoke SIMDDT as usual.
.s;EXIT(1) will terminate execution just as if the final END of the
program had been passed. The standard message will appear.
.s;EXIT(2) will invoke SIMDDT in debug mode, and the user is free to
do anything SIMDDT permits, including issuing the EXIT command to terminate
execution. C.f. procedure ENTERDEBUG.
.s;Other values of n are reserved for possible extensions.
.skip 2
.subtitle 4.6 MEMORY HANDLING
.p -5,4,28
.index ^^MEMORY HANDLING
4.6 MEMORY HANDLING [Not ready]
.s;This section concerns procedures which are not implemented
with the current release of DECsystem-10 SIMULA. We may
perhaps never implement them.
.if notready
.subtitle 4.6.1 PRIMARY MEMORY HANDLING
.p -5,1,8
.index ^^PRIMARY MEMORY HANDLING
4.6.1 PRIMARY MEMORY HANDLING
.p -5,2,8
EXTERNAL INTEGER PROCEDURE freebits
.index ^^FREEBITS EXTERNAL INTEGER PROCEDURE
.SKIP
.indent -5
Parameters:     One integer parameter.
Negative parameter means no garbage collection,
zero or positive parameters means garbage collection.
If the parameter is positive, then it indicates
the amount of core (in bits)
that will be assigned to the job after the forced garbage
collection, to be used up before the next automatic garbage
collection. If the parameter is too large, no error is caused, the system
will then wait as long as technically possible before the next
garbage collection. If the parameter is zero the allocation will follow
the default procedure.
For systems with fixed core size, positive and zero parameter
will probably be equivalent.
.SKIP
.indent -5
.index ^^Garbage collection
Result:         Forces a garbage collection for non-negative parameter.
Returns the integer value in bits of the amount of
more memory that
this program can allocate without causing an error interrupt.
For a virtual memory machine, the returned value is virtual core.
If the parameter is negative, then the returned value is as said
above minus present amount of garbage.
.indent -5
.subtitle 4.6.2 VIRTUAL MEMORY HANDLING (OR OVERLAY FACILITY)
.p -5,2,20
.index ^^VIRTUAL MEMORY HANDLING (OR OVERLAY FACILITY)
.index ^^Segmentation into overlayed core code segments
4.6.2 VIRTUAL MEMORY HANDLING
.index ^^VIRTUAL MEMORY HANDLING
.SKIP 1
This might use the overlay mechanism built into the DECsystem-10 linking
loader. Overlay might be between separately compiled segments in SIMULA.
Problems may occur with unique-numbered entry-points and with the
debugging system?
.skip 1
If overlay is considered, overlaying of SIMDDT with some other
system functions should also be considered at the same time.
.skip 1
Implementing overlay into the DECsystem-10 SIMULA
system will give many technical difficulties with the debugging
system, prototypes etc. and should perhaps therefore have low
priority, especially if the virtual memory
system could be used instead.
.skip 1
A way of making the virtual memory system on the DECsystem-10
work as an overlay system, with high efficiency, is to make a small
change to the page fault handler allowing a user program to ask
for certain pages to be swapped out. We could then add to the
SIMULA system a
.indent -5
**** PROCEDURE swap, with one or
more parameters which are either EXTERNAL PROCEDUREs, or
.index ^^SWAP EXTERNAL PROCEDURE
REF-s qualified by EXTERNAL CLASSes. SWAP will swap out all
pages containing only object code for the parameter
PROCEDUREs and CLASSes. Note that the REF-parameters to SWAP
may have the value NONE and still cause swapping out of object code.
Prefixing classes are not swapped out
if not explicitly indicated.
.skip
.nofill
Example of use:
BEGIN
   EXTERNAL PROCEDURE p; EXTERNAL CLASS a, b, c;
   EXTERNAL PROCEDURE swap;
   COMMENT a is prefix to b, b is prefix to c;
   REF (a) pa; REF(b) pb; REF(c) pc;
   swap(p,pb,pc); COMMENT will swap out the object
   code of p, b and c, but not the object code of a;
END;
.fill
.skip
At the same time, we should perhaps add procedures to SIMULA
to be able to set the physical core limit and the
physical guideline from a SIMULA program.
.skip
.indent -5
**** BOOLEAN PROCEDURE corelimit(i); INTEGER i;
.break
.index ^^CORELIMIT EXTERNAL BOOLEAN PROCEDURE
COMMENT sets PHYSICAL CORE LIMIT. The parameter "i"
is limit in bits. To get limit in
pages, multiply by 36*512 (if wordsize is 36 bits and pagesize is 512 words).
E.G. CORELIMIT(50*36*512) will
set a limit of 50 pages. Returns TRUE if setting was successful;
.p -5,1,5
?####Perhaps the parameter should be given in number of pages, not
in number of bits????
.skip
.indent -5
**** BOOLEAN PROCEDURE COREGUIDE(i); INTEGER i;
.break
.index ^^COREGUIDE EXTERNAL BOOLEAN PROCEDURE
COMMENT same for setting physical guideline;
.endif notready
.subtitle 4.7 ENVIRONMENT ENQUIRY
.p -5,4,11
.index ^^ENVIRONMENT ENQUIRY
4.7 ENVIRONMENT ENQUIRY
.p -5,1,0;**** INTEGER PROCEDURE maxint
.index ^^MAXINT EXTERNAL INTEGER PROCEDURE
.s;The largest positive integer number. 
.p -5,1,0;**** LONG REAL PROCEDURE maxreal
.s;The largest positive long real number.
.index ^^MAXREAL EXTERNAL LONG REAL PROCEDURE.
.if notready
.indent -5
**** LONG REAL PROCEDURE minreal
.index ^^MINREAL EXTERNAL LONG REAL PROCEDURE
.br;The smallest normalized positive real number.
.index ^^MINREAL EXTERNAL LONG REAL PROCEDURE
.endif notready
.skip
.if notready
.p -5,2,10
**** INTEGER PROCEDURE approx(a,b); [LONG] REAL a,b;
.fill
.index ^^APPROX EXTERNAL INTEGER PROCEURE
COMMENT Returns number of bits differing, or, if overflow,
- maxint;
.p -5,2,8;**** INTEGER PROCEDURE DIMENSIONS
.index ^^DIMENSIONS EXTERNAL INTEGER PROCEDURE
.skip 1
.indent -5
Parameters: One of kind ARRAY.
.skip 1
.indent -5
Result: Number of dimensions (subscripts) of the ARRAY.
.p -5,2,8
**** TEXT PROCEDURE IMPLEMENTATION
.index ^^IMPLEMENTATION EXTERNAL TEXT PROCEDURE
.SKIP
.indent -5
Parameters:     none
.SKIP
.indent -5
Result:         Returning a text reference to a text object with the value
"DEC-10 KI" ("IBM 370/145", "UNIVAC 1110", etc). The exact wording of
this text is decided by each implementation, but the first word
should indicate manufacturer, the following type and model if possible.
The procedure may optionally return the version of the SIMULA system
e.g.#"IBM 370/145 VERSION 3.03".
.skip
A list of what the returned reference should begin with for some wellknown
computers: "IBM 360", "IBM 370", "UNIVAC 11", "DEC-10", "CDC CYBER",
"CII", "ICL SYSTEM-4", etc.
.skip 2
.test page 8
.indent -5
**** TEXT PROCEDURE LOGINFO
.index ^^LOGININFORMATION EXTERNAL TEXT PROCEDURE
.SKIP
.indent -5
Parameters:     none
.SKIP
.indent -5
Result: Returns a text reference, machine-dependent, with the information
customarily given at LOGIN or in a JOB card. (Monitor version, Project number, programmer number,
external job number, internal job number, priorities, protection privilegies
etc.)
.endif notready
.skip 2
.subtitle 4.8 PACKING INTO PARTS OF WORDS
.p -5,3,28
.index ^^PACKING INTO PARTS OF WORDS
4.8 PACKING INTO PARTS OF WORDS
.skip
By Stephan Oldgren, ENEA Data AB
.nojustify
.left margin 5
.figure 2
.index ^^PACK EXTERNAL BOOLEAN PROCEDURE
.index ^^UNPACK EXTERNAL BOOLEAN PROCEDURE
.fill
This chapter describes two general-purpose and machine-independent
packing procedures. They will make it easier to produce programs which
can be moved to other computers than the DECsystem-10.
Chapter 7 below describes more efficient,
less general-purpose and more machine-dependent packing procedures.
.s;.i -5;**** BOOLEAN PROCEDURE PACK and
.i -5;**** BOOLEAN PROCEDURE UNPACK are two external MACRO-10 procedures
which pack and unpack data in parts of words.
.s 2;.i -5;4.8.1##PACK and UNPACK, PARAMETERS
.s;In the most simple case the procedures can be called with 
four parameters as follows:
.s;Parameter kinds for procedure PACK:
.lm 15;.i -10;.s;Parameter 1: The area into which data are to be packed. This parameter
can be of type INTEGER, REAL, LONG REAL or BOOLEAN and of kind
SIMPLE or ARRAY.
.br;The procedure will check that the bounds of this area are not exceeded.
.skip 1
.indent -10
Parameter 2: A non-negative INTEGER which specifies the number of bits
to be bypassed at the beginning of the area specified in
parameter 1, before start of packing. The purpose of this is to allow
partial packing and unpacking.
.skip 1
.indent -10
Parameter 3: The data to be packed. This parameter can be of type
INTEGER, REAL, LONG REAL, CHARACTER, BOOLEAN or TEXT and of kind
SIMPLE  or ARRAY. Observe that TEXT variables should not be NOTEXT.
.skip 1
.indent -10
Parameter 4: An INTEGER indicating the size in number of bits of the packed field. 
If parameter 3 is an array parameter 4 is the size for one element of the array .
The value of this parameter must be as follows:
.skip 1
.tab stops 10,28,48,55
.no fill
Type of	less than	greater than
parameter 3	or equal	or equal

INTEGER	WORD LENGTH	 2
REAL	 - " -	10
CHARACTER	 - " -	 7
BOOLEAN	 - " -	 1
LONG REAL	DOUBLE WORD LENGTH	10
TEXT	   7	 6
.fill
.left margin 5
.subtitle ^^4.8.1	PACK and UNPACK, PARAMETERS
.p 0,2,15
.figure 3
The procedure will also accept any even number of parameters 
up to thirty. Then parameters 5,7 etc. are of the same kind
as parameter 3 and parameters 6,8 etc. are of the same kind
as parameter 4.

.skip 1
The procedure UNPACK takes the same parameters as
procedure PACK and works conversely.
.skip 1
All packing and unpacking is done independently of word boundaries.
If for example parameter 2 is 70 and parameter 4 is 6, then
the data will be packed into a 6-bit area consisting
of the last two bits in the second word of parameter 3,
and the first four bits of the third word.
.p -5,2,8;4.8.2##PACK and UNPACK, ERROR HANDLING
.skip 2
The program will be interrupted if the number of parameters
is less than four or not even.
Before the interrupt, the following messages is written:
.br;"PARAMETER IS MISSING IN <procedure name> PROCEDURE"
.br;"? ERROR IN JOB ...."
.br;"ZYQ214 ERROR IN UTILITY PROCEDURE"
.skip 1
.br;.skip 1
Control is transferred to SIMDDT.
.skip 1
In the following cases the BOOLEAN procedure PACK will 
return the value FALSE:
.skip 1
a)#Parameters are of illegal type or kind.
.br;b)#Bounds of area specified in Parameter 1 are exceeded.
.br;c)#TEXT variable is NOTEXT.
.br;d)#Parameter 4(,6 etc) has illegal value.
.lm 8;.i -3;.br;e)#Truncated bits of an INTEGER variable are
significant (ie. contain ones if positive variable or zeroes
if negative variable).
.lm 5;.s;The procedure UNPACK will return FALSE in the same cases.
.subtitle ^^4.8.3##PACK and UNPACK, METHODS OF PACKING
.p -5,2,20
4.8.3##PACK and UNPACK, METHODS OF PACKING 
.skip 1
INTEGERs and BOOLEANs are packed by deleting bits
after the sign bit at the start of the word to be packed.
.skip 1
CHARACTERs are packed by deleting the necessary bits in the
left part of the word to be packed.
.skip 1
REALs and LONG REALs are packed by deleting as many 
bits as necessary at the low order end of the (single or double)
word to be packed.
.skip 1
TEXTs are packed by conversion of the characters from ASCII-7
to SIXBIT if the parameter for size of the packed field is 6.
If the parameter is 7 , each character is transferred
without conversion.
LENGTH and POS are not packed implicity.
.skip 2
.indent -5
4.8.4##PACK and UNPACK, METHODS OF UNPACKING
.skip 2
INTEGERs and BOOLEANs are unpacked by copying the 
sign bit into the previously deleted bits.
.skip 1
CHARACTERs are unpacked by returning previously deleted
bits as zeroes.
.skip 1
REALs and LONG REALs are unpacked by filling up the
previously deleted bits with zeroes.
.skip 1
TEXTs are unpacked by conversion of the characters from SIXBIT
to ASCII-7 if the parameter for size of the packed field is 6.
If the parameter is 7, each character is transferred
without conversion.
The LENGTH of the TEXT  indicates the number of characters 
to unpack.
.subtitle ^^4.8.5##PACK and UNPACK, EXAMPLES
.p -5,2,10
.figure 3
4.8.5##PACK and UNPACK, EXAMPLES
.skip 1
Example of SIMULA main program:
.skip 1
.tab stops 5,12,20,30,40
.no fill
BEGIN
	EXTERNAL BOOLEAN PROCEDURE pack,unpack;
	BEGIN
		ARRAY pool[1:100];
		INTEGER i,j;
		TEXT t,s;
.skip 1
		! check integer;
		i:=-5;
		Outint(i,2);	Outimage;
		pack(pool,0,i,5);
		unpack(pool,0,j,5);
		Outint(j,2);	Outimage;
.skip 1
		! check text;
		t:- Copy("*?AZz");
		s:- Blanks(5);
		Outtext(t);	Outimage;
		pack(pool,30,t,6);
		unpack(pool,30,s,6);
		Outtext(s);	Outimage;
.skip 1
		! check illegal;
		pack(pool,0,t);
	END;
END of program
.skip 2
Example of output from execution of the program above:
.skip 1
	-5
	-5
	*?AZz
	*?AZZ
	PARAMETER IS MISSING IN PACK PROCEDURE
	? ERROR IN JOB 15 AT PACK O 002314
	ZYQ214 ERROR IN UTILITY PROCEDURE
	*
.subtitle 4.9 MIN AND MAX
.p -5,4,28
.index ^^MIN AND MAX
4.9 MIN AND MAX
.s;These procedures are efficient - almost no overhead.
.p -5,3,8;**** INTEGER PROCEDURE imax(x,y);
.index ^^IMAX EXTERNAL INTEGER PROCEDURE
.index ^^Max and min, IMAX procedure
.index ^^Min and max, IMAX procedure
.br;INTEGER x,y;
.s;rmax:=IF x>y THEN x ELSE y;
.p -5,3,8;**** INTEGER PROCEDURE imin(x,y);
.index ^^IMIN EXTERNAL INTEGER PROCEDURE
.index ^^Max and min, IMIN procedure
.index ^^Min and max, IMIN procedure
.br;INTEGER x,y;
.s;imin:=IF x<y THEN x ELSE y;
.p -5,3,8;**** REAL PROCEDURE rmax(x,y);
.index ^^RMAX EXTERNAL REAL PROCEDURE
.index ^^Max and min, RMAX procedure
.index ^^Min and max, RMAX procedure
.br;REAL x,y;
.s;rmax:=IF x>y THEN x ELSE y;
.p -5,3,8;**** REAL PROCEDURE rmin(x,y);
.index ^^RMIN EXTERNAL REAL PROCEDURE
.index ^^Max and min, RMIN procedure
.index ^^Min and max, RMIN procedure
.br;REAL x,y;
.s;rmin:=IF x<y THEN x ELSE y;
.p -5,3,8;**** LONG REAL PROCEDURE lmax(x,y);
.index ^^LMAX EXTERNAL LONG REAL PROCEDURE
.index ^^Max and min, LMAX procedure
.index ^^Min and max, LMAX procedure
.br;LONG REAL x,y;
.s;lmax:=IF x>y THEN x ELSE y;
.p -5,3,8;**** LONG REAL PROCEDURE lmin(x,y);
.index ^^LMIN EXTERNAL LONG REAL PROCEDURE
.index ^^Max and min, LMIN procedure
.index ^^Min and max, LMIN procedure
.br;LONG REAL x,y;
.s;lmin:=IF x<y THEN x ELSE y;
.skip 2
.subtitle 5. ROUTINES WRITEABLE IN SIMULA.
.lm 5;.ps 55,65;.f;.nj;.PAGE
.index ^^ROUTINES WRITEABLE IN SIMULA.
.i -5;5.##ROUTINES WRITEABLE IN SIMULA
.i -1;----------------------------
.if notready
.s;NOTE: Some of these routines are not yet written. See the
list in chapter 0.2, which indicates which routines are
ready and which are not.
.endif notready
.s
.lm 5;.ps 60,65;.sp 1;.nf;.nj
.sk;.tp 15
.index ^^TEXT handling
.f; Most of the routines
are writeable or almost writeable in SIMULA, and the SIMULA
code for the procedures is given in full below to make
it easy to move programs to installations which do not
provide these procedures in their libraries.
.ts 13,21,29,37,45,53
For certain procedures below, some TEXT parameters are VALUE-specified.
In these cases, an assembly procedure can usually be written which
gives the same result in all cases without actually making any VALUE
copying of the TEXT. However, a corresponding procedure written entirely
in SIMULA must be VALUE- or NAME-specified to allow TEXT constants as actual
parameters.
.subtitle 5.1 PARTITIONING OF TEXTS
.index ^^PARTITIONING OF TEXTS
.p -5,2,10;5.1 PARTITIONING OF TEXTS
.index ^^REST EXTERNAL TEXT PROCEDURE
.nf.p -5,1,4;**** TEXT PROCEDURE rest(t); TEXT t;
.s;Returns a subtext reference of a text starting at Pos.
.s;IF t =/= NOTEXT THEN
rest:- t.Sub(t.pos,t.Length-t.pos+1);
.p -5,1,4;**** TEXT PROCEDURE front(t); TEXT t;
.index ^^FRONT EXTERNAL TEXT PROCEDURE
.s;Returns a reference to the longest subtext of T before Pos.
.s;IF t =/= NOTEXT THEN
front:- t.Sub(1,t.pos-1);
.p -5,1,4;**** TEXT PROCEDURE from(t,i); TEXT t; INTEGER i;
.index ^^FROM EXTERNAL TEXT PROCEDURE
.s;Returns a reference to the longest subtext of T starting at Pos = I.
.s;IF i <= t.Length THEN
from:- IF i <= 0 THEN t ELSE t.Sub(i,t.Length-i+1);
.p -5,1,4;**** TEXT PROCEDURE upto(t,i); TEXT t; INTEGER i;
.index ^^UPTO EXTERNAL TEXT PROCEDURE
.s;Returns a reference to the longest subtext of T before Pos = I.
.s;IF i > 0 THEN
upto:- IF i > t.Length THEN t ELSE t.Sub(1,i-1);
.p -5,2,9
.p -5,1,4;**** TEXT PROCEDURE frontstrip(t); TEXT t;
.index ^^Blanks, removal of
.index ^^FRONTSTRIP EXTERNAL TEXT PROCEDURE
.fill;.s;Returns a reference to the longest subtext of T starting with the first
non-blank character.
.s;.fill
BEGIN
.nofill
  t.Setpos(1);
  WHILE t.More DO
  IF t.Getchar NE ' ' THEN
  BEGIN
    frontstrip:- t.Sub(t.pos-1,t.Length-t.pos+2);
    t.Setpos(0);
  END;
END;
.fill
.p -5,2,8
**** CHARACTER PROCEDURE fetchar(t,p);
TEXT t; INTEGER p;
.index ^^FETCHAR EXTERNAL CHARACTER PROCEDURE
.s;Returns the P:th character from T.
.s;IF p >= 1 AND p <= t.length THEN
.br
fetchar:= t.Sub(p,1).Getchar;
.p -5,2,5;**** PROCEDURE depchar(t,p,c);   TEXT t;   INTEGER p;   CHARACTER c;
.fill
.index ^^DEPCHAR EXTERNAL PROCEDURE
.s;Deposits the character C in the text T at position P.
If P is out of range, no action will be taken;
.nofill
.s;IF p >= 1 AND p <= t.Length THEN
t.Sub(p,1).Putchar(c);
.p -5,2,8
**** TEXT PROCEDURE tsub(t,p,l);   TEXT t;   INTEGER p,l;
.fill
.index ^^TSUB EXTERNAL TEXT PROCEDURE
.s;TSUB acts like text attribute Sub. In cases where
t.Sub(p,l) would have caused a run time error, NOTEXT is returned.
.nofill
.s;IF p >= 1 AND l >= 0 AND p+l <= t.Length + 1 THEN
tsub:- t.Sub(p,l);
.p -5,2,10
**** TEXT PROCEDURE getitem(tt); NAME tt; TEXT tt;
.fill
.index ^^GETITEM EXTERNAL TEXT PROCEDURE
.s;First any blanks or tabs after POS in the text are skipped.
Then the procedure reads an item. By an item is meant
either an identifier (a letter followed by letters,
digits) or a number (a series of digits which
may contain one dot) or any other character except blank.
.s;The input text "IF CAR.WHEEL__SIZE > 13.5" will thus
by successive calls to GETITEM give:
IF/CAR/_./WHEEL/__/SIZE/>/13.5
.s;The result is a reference to a subtext
(not a copy) of the text passed as a
parameter, or NOTEXT if
there are only blanks left or pos > length.
.s;Notes:
.lm 9;.i -4; 1.      The position of the parameter starts from
current pos.
.i -4;2.      Preceding blanks or tabs (if any) are skipped.
.i -4;3.      The resulting position indicator setting
is that following the last character of the matched word;
.lm 5.nf;.s;IF tt =/= NOTEXT THEN
BEGIN
.test page 23

  CHARACTER window; INTEGER startpos; TEXT t;
.s
  CHARACTER PROCEDURE Getchar;
  IF t.more THEN
  Getchar:= window:= t.Getchar ELSE GOTO out;
.s
  BOOLEAN PROCEDURE idchar(c); CHARACTER c;
  idchar:= letter(c) OR digit(c);
.s
  t:- tt; t.Setpos(tt.Pos);
  startpos:= t.length+1;
  Getchar;
  WHILE window = ' ' OR window = Char(9) DO Getchar;
  startpos:= t.Pos-1;
  IF NOT letter(window) THEN
  BEGIN
    IF digit(window) THEN WHILE digit(Getchar) DO;
    IF window = '.' THEN WHILE digit(Getchar) DO;
  END ELSE WHILE idchar(Getchar) DO;
  IF t.Pos > startpos + 1 THEN t.Setpos(t.Pos-1);
  out:
  getitem:- t.Sub(startpos,t.Pos-startpos);
  tt.Setpos(t.Pos);
END;
.s 2
.nf
.i -5;.tp 14;.note
The  procedures INITEM, LOOKAHEAD, OUTLINE, BREAKOUTLINE, INLINE
all have a file reference parameter. It may not be omitted -
but may be NONE, in which case SYSIN or SYSOUT are assumed
as appropriate.
.end note
.i -5
**** TEXT PROCEDURE initem(fileref);
REF(infile COMMENT or directfile;) fileref;
.index ^^INITEM EXTERNAL TEXT PROCEDURE
.fill
.s;Same as GETITEM for files. LASTITEM is called before reading an item.
NOTEXT is returned if only blanks or tabs are left in the file
or if ENDFILE is TRUE. Note that since the ITEM-s are not
copied, a call on INITEM may cause inimage and thus destroy previously
located items, if they have not been copied by the program.
.nf.tp 4;.s;INSPECT fileref DO
initem:- IF lastitem THEN NOTEXT
ELSE getitem(image);
.subtitle 5.2 SEARCHING AND TESTING OF TEXTS
.p -5,4,28
5.2 SEARCHING AND TESTING OF TEXTS
.index ^^SEARCHING AND TESTING OF TEXTS
.tp 18
.index ^^SCANTO EXTERNAL TEXT PROCEDURE
.p -5,1,18;**** TEXT PROCEDURE scanto(tt,c); NAME tt; VALUE c;
.br;TEXT tt; CHARACTER c;
.fill
.s;SCANTO will scan from pos in TT until the next occurrence of the
character C. Pos of TT will be placed after the character found,
and the subtext from previous pos up to but not including the found character
will be returned
as result (not copied). If no C is found, the rest of the text is returned.
.nofill
.s;BEGIN TEXT t; INTEGER p;
  t:- tt; p:= t.pos;
  WHILE t.more DO
    IF t.getchar = c THEN
    BEGIN
      scanto:- t.sub(p,t.pos-p-1);
      GOTO out;
    END;
.br

  scanto:- from(t,p);
  out: tt.setpos(t.pos);
END of scanto;
.p -5,2,5;**** CHARACTER PROCEDURE findtrigger(master,triggers);
.index ^^FINDTRIGGER EXTERNAL CHARACTER PROCEDURE
NAME master;   TEXT master,triggers;
.fill
.s;Starting from current MASTER.POS, find first occurrence
of any of the characters in TRIGGERS.
.nofill
.s;BEGIN   CHARACTER c;   TEXT t;
.s
    t:- master;
    WHILE t.More DO
    BEGIN   c:= t.Getchar;
	triggers.Setpos(1);
	IF scanto(triggers,c) =/= triggers THEN
	BEGIN !C found in triggers;
	    findtrigger:= c;
	    GO TO out;
	END
    END loop;
    out:  master.Setpos(t.Pos);
END of findtrigger;
.p -5,2,5;**** TEXT PROCEDURE skip(tt,c);  NAME tt;  TEXT tt;  CHARACTER c;
.index ^^SKIP EXTERNAL TEXT PROCEDURE
.fill
Skip will skip all characters C in the text T starting from T.POS.
IF the next character (at T.POS) is not equal to C, T.POS will
remain unaltered, otherwise it will be situated at the first
character not equal to C.
Skip will also return the subtext rest of t.
;
.nofill
.s
BEGIN   TEXT t;
    t:- tt;
    WHILE t.More DO
    IF t.Getchar NE c THEN
    BEGIN   t.Setpos(t.Pos-1);
	skip:- t.Sub(t.Pos,t.Length-t.Pos+1);
	GO TO out
    END;
    out: tt.Setpos(t.Pos)
END of skip;
.p -5,2,11
**** BOOLEAN PROCEDURE frontcompare(string, config);
.index ^^Text value comparison
.index ^^FRONTCOMPARE EXTERNAL BOOLEAN PROCEDURE
VALUE  config;   TEXT string, config;
.fill
.s;Starting at current pos, does STRING begin with a substring equal to CONFIG?
.nf;.s;IF string.Length - string.pos + 1 >= config.Length THEN
frontcompare:=
string.Sub(string.pos,config.Length) = config;
.p -5,2,8
**** BOOLEAN PROCEDURE upcompare
.fill;.s
.index ^^UPCOMPARE EXTERNAL BOOLEAN PROCEDURE
Upcompare is similar to frontcompare except that a match is found
also when the character in the first parameter string is
a lower case letter and the other character is upper case of the same letter.
.nofill;.s 2
.test page 18
.indent -5
**** INTEGER PROCEDURE search(master, config);
.index ^^SEARCH EXTERNAL INTEGER PROCEDURE
TEXT master, config;
.fill
.s;Returns pos of 1st character of the first substring equal to config,
starting at the current Pos of MASTER.
If no such subtext exists, then
the result is MASTER.Length+1.
.s;.nf;BEGIN
    WHILE master.Length - master.Pos + 1 >= config.Length DO
    IF master.Sub(master.Pos,config.Length) = config THEN
    GO TO out ELSE
    master.Setpos(master.Pos+1);
    master.Setpos(0);
    out:
  search:= master.Pos;
END of search;
.s 2
.indent -5
**** INTEGER PROCEDURE checkint(t);    NAME t;    TEXT t;
.index ^^CHECKINT EXTERNAL INTEGER PROCEDURE
.s;CHECKINT analyses the text t from t.pos and on.
If a getint operation from this position is legal the
returned value is +1. If it would give an error - then
if the remaining text string is blank, the result is 0,
otherwise -1. Pos is placed after a legal item (+1),
after the first non-blank illegal character (-1) or after
the text if the rest is empty (0).
C.f_. SCANINT.
.s;Maxintegerlength and Maxfloatinteger are implementation dependent.
See also procedure GETTYPE below.
.nf;.s;IF t.Strip.Length < t.Pos THEN t.Setpos(0) ELSE
BEGIN   TEXT u;   CHARACTER c;   INTEGER p;   LONG REAL x;
   c:= ' ';   u:- t;
   WHILE (c = ' ' OR c= Char(9)) AND u.More DO c:=
   u.Getchar;
   IF c = ' ' OR c = Char(9) THEN !checkint:= 0; ELSE
   IF c = '+' OR c = '-' THEN
   BEGIN  c:= ' ';
      WHILE c = ' '  AND u.More DO c:= u.Getchar;
      IF Digit(c) THEN
      BEGIN   trymoredigits:
         WHILE c = '0' AND u.More DO c:= u.Getchar;
         p:= u.Pos - 1;
         WHILE Digit(c) AND u.More DO c:= u.Getchar;
         p:= (IF NOT Digit(c) THEN u.Pos-1 ELSE u.Pos) - p;
         IF p <= maxintegerlength - 1 THEN checkint:=  1
         ELSE
         IF p >  maxintegerlength + 1 THEN checkint:= -1
         ELSE
         BEGIN
            x:= u.Sub(IF NOT Digit(c) THEN u.Pos-p-1 ELSE
            u.Pos-p,p).Getreal;
            checkint:= IF Abs(x)  <= maxfloatinteger THEN 1
            ELSE -1
         END maxinteger digits;
         IF NOT Digit(c) THEN u.Setpos(u.Pos-1);
      END digits ELSE
      GO TO error
   END sign ELSE
   IF Digit(c) THEN GO TO trymoredigits ELSE
   BEGIN   error:   checkint:= -1   END;
   t.Setpos(u.Pos)
END of checkint;
.p -5,2,5;**** INTEGER PROCEDURE checkreal(t);   NAME t;   TEXT t;
.index ^^CHECKREAL EXTERNAL INTEGER PROCEDURE
.fill
.s;CHECKREAL analyses the text t from t.pos and on.
If a getreal operation from this position is legal the
returned value is +1. If it would give an error - then
if the remaining text string is blank, the result is 0,
otherwise -1. Pos is placed after a legal item (+1),
after the first non-blank illegal character (-1) or after
the text if the rest is empty (0). C.f_. SCANREAL.
.s;Ln10, Lowtencharacter, Lnmaxreal, Maxdigits are
implementation dependent.
.if notready
See also procedure GETTYPE below.
.endif notready
.s;.nf;IF t.Strip.Length < t.Pos THEN t.Setpos(0) ELSE
BEGIN   TEXT u;   CHARACTER c;   INTEGER expitem,p,p2;
LONG REAL decitem;
   PROCEDURE skip;
   BEGIN   c:= ' ';
      WHILE (c = Char(9) OR c = ' ') AND u.More DO c:=
      u.Getchar
   END of skip;

   decitem:= 1.0_&_&0;
   u:- t;   skip;   p:= u.Pos - 1;
   IF c = ' ' OR c = Char(9) THEN !checkreal:= 0; ELSE
   IF c = lowtencharacter THEN
   BEGIN   testexp:   skip;   p:= u.Pos - 1;
      IF c = '+' OR c = '-' THEN
      BEGIN   c:= ' ';
      WHILE c = ' ' AND u.More DO c:= u.Getchar   END;
      IF Digit(c) THEN
      BEGIN   WHILE Digit(c) AND u.More DO c:= u.Getchar;
         p2:= IF NOT Digit(c) THEN u.Pos - 1 ELSE u.Pos;
         u.Setpos(p);
         IF checkint(u) = 1 THEN expitem:= u.Sub(p,
         p2-p).Getint ELSE
         GO TO error;
         u.Setpos(p2+1);
         IF decitem = 0 THEN checkreal:= 1 ELSE
         IF Ln(Abs(decitem)) + expitem*ln10 < lnmaxreal THEN
         checkreal:= 1 ELSE GO TO error
      END digit in exponent ELSE GO TO error
   END exponent ELSE
   IF Digit(c) THEN
   BEGIN  testdigits:   p:= u.Pos - 1;
      WHILE Digit(c) AND u.More DO c:= u.Getchar;
      p2:= IF NOT Digit(c) THEN u.Pos - 1 ELSE u.Pos;
      IF p2 - p > maxdigits - 1 THEN GO TO error;
      IF c = lowtencharacter THEN
      BEGIN  realpart:    decitem:= u.Sub(p,p2-p).Getreal;
      GO TO testexp   END ELSE
      IF c = '.' THEN
      BEGIN   testfrac:
         IF u.More THEN c:= u.Getchar;
         IF NOT Digit(c) THEN GO TO error;
         WHILE Digit(c) AND u.More DO c:= u.Getchar;
         p2:= IF NOT Digit(c) THEN u.Pos - 1 ELSE u.Pos;
         IF c = lowtencharacter THEN GO TO realpart
      END fraction;
      IF NOT Digit(c) THEN u.Setpos(u.Pos-1);
      checkreal:= 1
   END digit ELSE
   IF c = '.' THEN GO TO testfrac ELSE
   IF c = '+' OR c = '-' THEN
   BEGIN   c:= ' ';
      WHILE c = ' ' AND u.More DO c:= u.Getchar;
      GO TO
      IF c = lowtencharacter THEN  testexp ELSE
      IF Digit(c) THEN  testdigits ELSE
      IF c = '.' THEN  testfrac ELSE error;
   END sign ELSE
   BEGIN   error:   checkreal:= -1   END;
   t.Setpos(u.Pos)
END of checkreal;
.p -5,2,8
**** INTEGER PROCEDURE CHECKFRAC
.index ^^CHECKFRAC EXTERNAL INTEGER PROCEDURE
.skip
Same as checkint/checkreal for grouped items.
.if notready
.NOFILL
.SPACING 1
.p -5,2,10
**** INTEGER PROCEDURE gettype(paratext);
NAME paratext; TEXT paratext;
.index ^^GETTYPE EXTERNAL INTEGER PROCEDURE
.fill
.s;Investigate the subtext of the parameter without leading blanks.
Will return:
.indent -2
1 If the next item is readable by GETREAL and contains a dot
and/or a lowtencharacter, else
.indent -2
2 If the next item is readable by GETINT, else
.indent -2
3 If the next item begins with a letter, else
.indent -2
4 If the next item is not NOTEXT, else
.indent -2
5 If the next item is NOTEXT(i.e. if the parameter to gettype is
either NOTEXT or a wholly blank TEXT);
.s;This procedure cannot be coded fully
machine-independent, since the maximal size of integers
and reals vary with the machine;
.endif notready
.p -5,2,14
**** INTEGER PROCEDURE hash(t,n); VALUE t; TEXT t;  INTEGER n;
.f
.index ^^HASH EXTERNAL INTEGER PROCEDURE
.s;Returns a hash coded value of T in the interval [0:N-1].
It is recommended to choose n as a prime number.
.s;.nf;BEGIN
  TEXT tstrip; INTEGER a;
  tstrip:-frontstrip(t.Strip);
  IF tstrip == NOTEXT then hash:= Mod(t.Length,n) ELSE
  BEGIN
    a:= Rank(tstrip.Getchar);
    if tstrip.Length > 3 then
    BEGIN
      a:= a + 8*Rank(tstrip.Getchar);
      a:= a +64*Rank(tstrip.Getchar);
    END;
    tstrip.Setpos(tstrip.Length);
    a:= a + 512*Rank(tstrip.Getchar) + t.Length;
    hash:= Mod(a,n);
  END;
END of hash;
.skip 1
.nofill
.p -5,2,5;**** BOOLEAN PROCEDURE menu(t,i,table,n);
.index ^^MENU EXTERNAL BOOLEAN PROCEDURE
NAME i;   TEXT t;   TEXT ARRAY table;   INTEGER i,n;
.skip
.fill
The MENU procedure is designed to be used for validity checks
in MENU-like command requests.
[See chapter 7 - MENY for command handling in Swedish.]
.skip
The MENU procedure will check for nonambiguous
correspondence between T and an element from the text array TABLE.
(Note that an exact match will always be accepted, even if it is a
substring of another table element.) The table must contain
upper case letters only with no trailing blanks. The input
may have lower case letters.
If no match is found, I will return 0.
If T is ambiguous, I returns -1, otherwise
the table matching index will be returned.
An example:
.nofill
.skip
! BEGIN   TEXT ARRAY menutable[1:5];
!      INTEGER index;
!      BOOLEAN ok;
!      TEXT t;
.skip
!      menutable[1]:- Copy("STOP");
!      menutable[2]:- Copy("START");
!      menutable[3]:- Copy("END");
!      menutable[4]:- Copy("ENDURE");
!      menutable[5]:- Copy("EXIT");
.skip
!      t:- <... input ...>;
!      ok:= menu(t,index,menutable,5);
.skip
! OK will become TRUE if T is equal to
.skip
START		(INDEX =  2)
start		(INDEX =  2)
Sta		(INDEX =  2)
sto		(INDEX =  1)
enD		(INDEX =  3)
endure		(INDEX =  4)
endu		(INDEX =  4)
.skip
and FALSE for
.skip
ST		(INDEX = -1)
x		(INDEX =  0)
e		(INDEX = -1)
en		(INDEX = -1)
.s;EXTERNAL Procedures required: TEXT PROCEDURE upcase;
.s;    BEGIN   TEXT u;   INTEGER j,k,hit;
.skip
	! Checking the array index bounds: ;
	OPTIONS(/A); COMMENT START ARRAY BOUND CHECKING;
	u:- table[1];
	u:- table[n];;
	OPTIONS(/-A); COMMENT NO ARRAY BOUND CHECKING;
	u:- upcase(t.Strip);
.skip
	FOR j:= 1 STEP 1 UNTIL n DO
	IF u = table[j] THEN
	BEGIN   hit:= 1;   k:= j;   GO TO ready  END
	ELSE
	IF u.Length < table[j].Length THEN
	BEGIN
		IF u = table[j].Sub(1,u.Length) THEN
		BEGIN   k:= j;   hit:= hit + 1   END
	END;
.skip
	ready:
	menu:= hit = 1;
	i:= IF hit = 1 THEN k ELSE Sign(-hit)
.skip
    END of menu;
.skip 2
.skip 2
.test page 12
.skip 2
.indent -5
.index ^^LOOKUP EXTERNAL BOOLEAN PROCEDURE
**** BOOLEAN PROCEDURE lookup(t,ta,low,high,i);  NAME i;  TEXT t;
TEXT ARRAY ta;   INTEGER low,high,i;
.fill
.s;Procedure LOOKUP will perform a binary search for T
in the text array TA within the interval [LOW,HIGH].
The text array contents must be sorted in ASCENDING order!
(I.e. TA[J] < TA[J+1]. Use procedure SORTTA for sorting if necessary.)
If the text is found in TA the matching index I will be returned
(for which TA[I] = T) and LOOKUP will return TRUE.
If the text is NOT found LOOKUP will return FALSE and I will
be either in the range [LOW,HIGH-1] in case TA[I] > T > TA[I+1]
or else I = HIGH if T > TA[HIGH] or I = LOW-1 IF T < TA[LOW].
.br;Author: Mats Ohlin, FOA 1, S-104#50 STOCKHOLM 80, SWEDEN.
.s;.nf;IF low <= high THEN
BEGIN   INTEGER j;
.skip
    OPTIONS(/A); COMMENT START ARRAY BOUND CHECKING;
    IF
    ta[low] < t AND t < ta[high]
    THEN
    BEGIN ;
    OPTIONS(/-A); COMMENT NO ARRAY BOUND CHECKING;
	FOR j:= (low+high)//2 WHILE high > low + 1 DO
	IF ta[j] > t THEN high:= j ELSE
	IF ta[j] < t THEN low:= j ELSE
	BEGIN   lookup:= TRUE;   GO TO out  END
    END  inside range ELSE
    IF ta[low] = t THEN
    BEGIN   lookup:= TRUE;   j:= low END ELSE
    IF ta[high] = t THEN
    BEGIN   lookup:= TRUE;   j:= high END ELSE
    IF ta[low] > t THEN j:= low - 1 ELSE
    IF ta[high] < t THEN j:= high;
.skip
    out:  i:= j
.skip
END of lookup;
.skip 2
.subtitle 5.3 OPERATIONS ON TEXTS
.p -5,3,25
.index ^^OPERATIONS ON TEXTS
5.3 OPERATIONS ON TEXTS
.skip 2
.indent -5
**** LONG REAL PROCEDURE scanreal(t);   NAME t;   TEXT t;
.index ^^SCANREAL EXTERNAL LONG REAL PROCEDURE
.fill
.s;Scanreal is similar to GETREAL, but the handling
of ERROR conditions due to bad data is different.
Scanreal returns the value of the next real item in
the text T. T.Pos will only be moved if deediting was successful.
.nofill
.s;BEGIN   TEXT s;   INTEGER p;
    p:= t.Pos;   s:- rest(t);
    scanreal:= s.Getreal;
    ! *** If this goes wrong, return -MAXREAL ELSE
    t.Setpos(p+s.Pos-1);
END of scanreal;
.skip 2
.indent -5
**** INTEGER  PROCEDURE scanint(t);   NAME t;   TEXT t;
.index ^^SCANINT EXTERNAL INTEGER PROCEDURE
.fill
.s;Scanint is similar to GETINT, but the handling
of error conditions due to bad data is different.
Scanint returns the value of the next integer item in
the text T. T.Pos will only be moved if deediting was successful.
.nofill
.s;BEGIN   TEXT s;   INTEGER p;
    p:= t.Pos;   s:- rest(t);
    scanint:= s.Getint;
    ! *** If this goes wrong, return -MAXINT-1 ELSE
    t.Setpos(p+s.Pos-1)
END of scanint;
.p -5,2,8
.index ^^SCANFRAC EXTERNAL INTEGER PROCEDURE
**** INTEGER PROCEDURE scanfrac
.skip
Same as scanint/scanreal for grouped items.
.skip 2
.test page 8
.indent -5
**** TEXT PROCEDURE conc(t,...);   TEXT t,...;
.index ^^CONC EXTERNAL TEXT PROCEDURE
.fill;.s;Text concatenation procedure. Variable number of
TEXT parameters.
Since the number of parameters is variable, CONC can NOT be written in
SIMULA.
The parameters are handled as if transferred in reference mode, although
constants are allowed.
.p -5,2,14
**** TEXT PROCEDURE conc2(t1,t2);
VALUE t1, t2; TEXT t1, t2;
.index ^^CONC2 EXTERNAL TEXT PROCEDURE
.fill
.s;T1 and T2 are handled as if transferred by reference (text descriptors are
copied) although constants are allowed.
.nofill
.s;BEGIN TEXT c;
  c:- blanks(t1.Length+t2.Length);
  c.Sub(1,t1.Length):= t1;
  c.Sub(1+t1.Length,t2.Length):= t2;
  conc2:- c;
END;
.p -5,2,15
**** BOOLEAN PROCEDURE puttext(oldstring, newstring);
NAME oldstring; VALUE newstring;
.index ^^PUTTEXT EXTERNAL BOOLEAN PROCEDURE
TEXT oldstring, newstring;
.fill
.s;Puts the short word newstring into the long string oldstring.
Newstring is OUTPUT after POS in oldstring, and POS of oldstring is
moved after the end of the new word. Returns FALSE if there
was not room for the new string.
.nofill
.s;BEGIN TEXT s;
  s:- oldstring;
  IF s.Pos+newstring.length-1 <=
  s.length THEN
  BEGIN
    puttext:= true;
    s.Sub(s.Pos,newstring.length):=
    newstring;
    s.Setpos(s.Pos+newstring.length);
  END;
  oldstring.Setpos(s.Pos);
END;
.p -5,2,18
.fill
**** TEXT PROCEDURE upcase(t); TEXT t;
.index ^^UPCASE EXTERNAL TEXT PROCEDURE
.break
.s;Will convert all lower case letters within T to the
corresponding upper case letter. No copying of the text.
Only English alphabet letters (for which the procedure "letter"
returns TRUE) are converted.
.nofill
.s;IF t =/= NOTEXT THEN
BEGIN
  CHARACTER c; INTEGER shift;
  shift:= rank('a') - rank('A');
  t.Setpos(1);
  WHILE t.more DO
  BEGIN
    c:= t.Getchar;
    IF letter(c) AND c >= 'a' AND c <= 'z' THEN
    BEGIN
      c:= char(rank(c) - shift);
      t.Setpos(t.Pos-1); t.Putchar(c);
    END;
  END;
.![124];  t.Setpos(1);
  upcase:- t;
END;
.p -5,2,18
**** TEXT PROCEDURE lowcase(t); TEXT t;
.index ^^LOWCASE EXTERNAL TEXT PROCEDURE
.fill
.s;LOWCASE is the opposite of UPCASE.
Defined via simple modifications of the
UPCASE procedure definition.
Just exchange 'a' with 'A' and 'z' with 'Z'.
.nofill
.p -5,2,10
**** TEXT PROCEDURE maketext(c,n); CHARACTER c; INTEGER n;
.s;Returns a new text of length N filled with character C.
.s;IF n > 0 THEN BEGIN
.index ^^MAKETEXT EXTERNAL TEXT PROCEDURE
  TEXT t;
  t:- blanks(n);
  WHILE t.More DO t.putchar(c);
  t.Setpos(1); maketext:- t;
END;
.p -5,2,8
.index ^^COMPRESS EXTERNAL TEXT PROCEDURE
**** TEXT PROCEDURE compress(t,c);   TEXT t;   CHARACTER c;
.fill
.s;COMPRESS returns NOTEXT (if T contains no other characters than a number
of characters = C), or a reference to an initial subtext of T (altered) which
contains all characters of T not = C. The part of T after this subtext is
unchanged.
.br;Example: t1:-Copy("AxBxCxDx"); t2:-compress(t1,'x'); gives
t1="ABCDCxDx", t2==t1.Sub(1,4), t2="ABCD".
.nofill
.s;BEGIN   TEXT s;   CHARACTER cc;
  t.Setpos(1);   s:- t;
  WHILE t.More DO
  BEGIN   cc:= t.Getchar;
    IF cc NE c THEN s.Putchar(cc);
  END;
  compress:- front(s)
END of compress;
.p -5,2,8
.index ^^STARTPOS EXTERNAL INTEGER PROCEDURE
**** INTEGER PROCEDURE startpos(t);   TEXT t;
.fill
.s;Procedure STARTPOS returns the starting position of the
(sub)text T within T.Main.
Thus if T is a main text (T == T.Main) the result is 1.
If T == NOTEXT, 0 is returned.
Efficient MACRO-10 coded routine.
.nofill
.s;IF t =/= NOTEXT THEN
BEGIN   TEXT s; INTEGER p;
    s:- t.Main;
    IF s == t THEN startpos:= 1 ELSE
    BEGIN
	WHILE s.More DO
	BEGIN
	    p:= search(s,t);
	    IF s.Sub(p,t.Length) == t THEN
	    BEGIN   startpos:= p;   GO TO out   END;
	    s.Setpos(p+1);
	END loop
    END not main text;
    out:
END of startpos;
.p -5,2,8
.index ^^SPLIT EXTERNAL PROCEDURE
**** PROCEDURE split(t,t1,delimiter,t2);
NAME t1,t2;   TEXT t,t1,delimiter,t2;
EXTERNAL Procedures required:
TEXT PROCEDURE front,rest.
INTEGER PROCEDURE search;
.fill
.s;This procedure splits the text T into two halves - the first
part T1 denoting the part of T up to the text DELIMITER -
and the second part T2 denoting the part of T following
the DELIMITER. Thus T1 + DELIMITER + T2 = T. However, if no DELIMITER
is found, T1 will return a reference to the whole of T, while T2 will
return NOTEXT.
Note - if the delimiter is just one character long, procedure SCANTO
is recommended for efficiency reasons.
.nofill
.s;    BEGIN   TEXT s1;
	t.Setpos(1);
	t.setpos(search(t,delimiter));
	s1:- front(t);
	t.Setpos(t.pos+delimiter.Length);
	t2:- rest(t);
	t1:- s1
    END of split;
.fill
.p -5,2,8
.fill
*** INTEGER PROCEDURE splita(t,del,ta,n);
.br
TEXT t,del;   TEXT ARRAY ta;   INTEGER n;
.s;This procedure splits the text T into parts separated
by the text delimiter DEL and makes the elements of
TA[1:N] denote the different parts of T (without DEL).
The returned value SPLITA is the number of parts found.
However, if more than N parts are found, the value -1 is
returned.
.s;Note that if DEL is just one character, procedure SPLITC
is recommended. SPLITC is roughly twice as efficient as SPLITA.
.s;Author: Mats Ohlin, FOA 1, Fack, S-104 50 STOCKHOLM 80, SWEDEN.
.s;EXTERNAL PROCEDURE required: INTEGER PROCEDURE search;
.nofill
BEGIN   INTEGER i,p;
    OPTIONS(/A); ta[1]:- ta[n];; ! Check array bounds;
    OPTIONS(/-A);
    t.Setpos(1);
    FOR i:= i+1 WHILE t.More DO
    IF i>n THEN
    BEGIN   splita:= -1;   GOTO exit   END
    ELSE
    BEGIN   p:= t.Pos;
	t.Setpos(search(t,del));
	ta[i]:- t.Sub(p,t.Pos-p);
	t.Setpos(t.Pos+del.Length);
    END;
    splita:= i-1;
    FOR i:= i STEP 1 UNTIL n DO ta[i]:- NOTEXT;
    exit:
END of splita;
.index ^^SPLITA EXTERNAL INTEGER PROCEDURE
.p -5,2,8
.index ^^SPLITC EXTERNAL INTEGER PROCEDURE
**** INTEGER PROCEDURE splitc(t,del,ta,n);
.br
TEXT t;   CHARACTER del;   TEXT ARRAY ta;   INTEGER n;
.skip
This procedure splits the text T into parts separated
by the character delimiter DEL and makes the elements of
TA[1:N] denote the different parts of T (without DEL).
The returned value SPLITC is the number of parts found.
However, if more than N parts are found, the value -1 is
returned.
.skip
Author: Mats Ohlin, FOA 1, Fack, S-104 50 STOCKHOLM 80, SWEDEN.
.br
.skip
EXTERNAL PROCEDURE required: TEXT PROCEDURE scanto;
.nofill
.skip
BEGIN   INTEGER i;
    OPTIONS(/A); ta[1]:- ta[n];; ! Check array bounds;
    OPTIONS(/-A);
    t.Setpos(1);
    FOR i:= i+1 WHILE t.More DO
    IF i>n THEN
    BEGIN   splitc:= -1;   GOTO exit   END
    ELSE  ta[i]:- scanto(t,del);
    splitc:= i-1;
    FOR i:= i STEP 1 UNTIL n DO ta[i]:- NOTEXT;
    exit:
END of splitc;
.p -5,2,8
.index ^^CHANGE EXTERNAL BOOLEAN PROCEDURE
**** BOOLEAN PROCEDURE change(master,oldt,newt);   NAME master;
TEXT master,oldt,newt;
.s;EXTERNAL Procedures required: TEXT PROCEDURE conc,from,front.
INTEGER PROCEDURE search.
.s;.fill
Change will change the subtext OLDT in MASTER - if
found when searching from MASTER.POS and on - to NEWT.
If OLDT.Length >= NEWT.Length then MASTER will denote
(a subtext of) the original MASTER text, otherwise MASTER will
denote a new text object.
Changing all occurrences of OLDT to NEWT may
be done with the following procedure;
.nofill
.skip
! PROCEDURE edit(master,oldt,newt);
! NAME master;
! TEXT master,oldt,newt;
! BEGIN  TEXT local;
!    local:- master;
!    WHILE local.More DO change(local,oldt,newt);
!    master:- local
! END of edit;
.skip
BEGIN   TEXT local;   INTEGER p;
  local:- master;
  p:= search(local,oldt);
  IF p <= local.Length THEN
  BEGIN   change:= TRUE;
    IF oldt.Length >= newt.Length THEN
    BEGIN   local.Sub(p,newt.Length):= newt;
      IF oldt.Length > newt.Length THEN
      BEGIN
        from(local,p+newt.Length):=
        from(local,p+oldt.Length);
        local:- local.Sub(1,
        local.Length-oldt.Length+newt.Length)
      END
    END ELSE
    local:-
    conc(front(local),newt,from(local,p+oldt.Length));
    local.Setpos(p+newt.Length);
    master:- local
  END ELSE master.Setpos(0);
END of change;
.nofill
.p -5,2,8
**** TEXT PROCEDURE puttime(field,time,unit,secdec);
.index ^^PUTTIME EXTERNAL TEXT PROCEDURE
.br
TEXT field;   REAL time;
.br
CHARACTER unit;   INTEGER secdec;
.skip
Puttime edits a REAL variable representing a TIME value
left justified into the text FIELD in
seconds	if UNIT = 'S'
minutes	if UNIT = 'M'
hours	if UNIT = 'H'
days	if UNIT = 'D'
Else Putreal editing will be used.
.skip
The FIELD must have a minimum length of
12	if secdec < 0
15	if secdec = 0
16+secdec	if secdec > 0
.skip
Format:
.skip
[-]dddD  hh:mm[.ss[.xxx...]]
.skip
where
ddd	is number of days	(Blanked if day < 1)
hh	is number of hours
mm	is number of minutes
ss	is number of seconds (only if SECDEC >= 0)
xxx	is fraction of second with SECDEC digits
.skip
PUTTIME also returns a reference to parameter FIELD.
Thus it can be used as parameter to Outtext -
i.e.  Outtext(puttime(field,Time,'H',-1);
or editing Image directly -
      puttime(Image.Sub(Pos,17),Time,'H',-1);
.br
C.f. procedure OUTTIME.
.skip
EXTERNAL PROCEDURE required: TEXT PROCEDURE putfloat;
.br;IF field.Length >=
(IF secdec < 0 THEN 12 ELSE IF secdec = 0 THEN 15 ELSE secdec+16)
THEN
BEGIN   INTEGER days,hours,m,powersec;   REAL seconds;
.skip
    PROCEDURE fixedit(x,w);   REAL x;   INTEGER w;
    BEGIN
	field.Sub(field.Pos,w).Putfix(x,secdec);
	field.Setpos(field.Pos+w);
    END of fixedit;
.skip
    PROCEDURE intedit(i,w);   INTEGER i,w;
    BEGIN
	field.Sub(field.Pos,w).Putint(i);
	IF field.Getchar = ' ' THEN
	BEGIN   field.Setpos(field.Pos-1);
	    field.Putchar('0');
	END;
	field.Setpos(field.Pos-1+w);
    END of intedit;
.skip
    BOOLEAN PROCEDURE adjusted;
    BEGIN
	IF m = 60 THEN
	BEGIN   adjusted:= TRUE;
	    hours:= hours + 1;   m:= 0;
	    IF hours = 24 THEN
	    BEGIN   days:= days + 1;   hours:= 0   END
	END;
	field.Sub(2,6):= "   D  ";
	field.Setpos(5);
	IF days < 1 THEN
	field.Putchar(' ') ELSE
	IF days < 10 THEN
	BEGIN
	    field.Setpos(4);
	    field.Putchar(Char(days+Rank('0')));
	END ELSE
	IF days < 100 THEN
	BEGIN   field.Setpos(3);   intedit(days,2)   END
	ELSE
	IF days < 1000 THEN
	BEGIN   field.Setpos(2);   intedit(days,3)   END
	ELSE
	IF days <= 9999 AND days >= -999 THEN
	BEGIN   field.Setpos(1);   intedit(days,4)   END
	ELSE
	field.Sub(1,4):= "****";
	field.Setpos(8);
	intedit(hours,2);   field.Putchar(':');
    END of adjust;
.skip
    powersec:= 1;
    FOR m:= 1 step 1 UNTIL secdec DO powersec:= powersec*10;
    IF unit = 'D' THEN time:= 1440*time ELSE
    IF unit = 'H' THEN time:= 60*time ELSE
    IF unit = 'M' THEN ELSE
    IF unit = 'S' THEN time:= time/60 ELSE
    BEGIN   putfloat(field,time);
	GO TO stop
    END;
.skip
    field.Setpos(1);
    field.Putchar(IF time < 0 THEN '-' ELSE ' ');
    time:= Abs(time);
    IF time > 34 359 738 367 THEN GO TO error;
    m:= Entier(time);
    seconds:= 60*(time - m);
    hours:= m//60;
    m:= Mod(m,60);
    days:= hours//24;
    hours:= Mod(hours,24);
    IF secdec >= 0 THEN
    BEGIN
	IF Entier(seconds*powersec+0.5) = 60*powersec THEN
	BEGIN   m:= m + 1;   seconds:= 0   END;
	adjusted;
	intedit(m,2);   field.Putchar('.');
	IF seconds < 9.5 THEN
	BEGIN   field.Putchar('0');
	    fixedit(seconds,
	    IF secdec = 0 THEN 1 ELSE secdec+2)
	END ELSE
	fixedit(seconds,IF secdec = 0 THEN 2 ELSE secdec+3);
    END ELSE
    BEGIN   time:= m + seconds/60;
	m:= time;
	IF adjusted THEN time:= 0;
	IF time < 9.5 THEN   field.Putchar('0');
	secdec:= 0;
	fixedit(time,IF time < 9.5 THEN 1 ELSE 2)
    END;
    stop:
    field.Setpos(1);   puttime:- field
END of puttime OK ELSE
error:
BEGIN   field.Setpos(1);
    puttime:- putfloat(field,time);
END of puttime error;
.nofill
.p -5,2,8
**** TEXT PROCEDURE putfloat(t,x);   TEXT t;   REAL x;
.skip
.fill
.index ^^PUTFLOAT EXTERNAL TEXT PROCEDURE
PROCEDURE PUTFLOAT edits a number X into the text T
(right justified).
.skip
Insignificant trailing zeros in fractions are removed.
.skip
Representation errors (of type 98.9999999) are corrected.
If fixed point format cannot be used (displaying significant
digits), floating point format is used instead.
The output will depend on the length of the text T.
A value in the range [8,16] is recommended.
.skip
PUTFLOAT also returns a reference to the text parameter.
.skip
.nofill
TEXT PROCEDURE putfloat(t,x);   TEXT t;   REAL x;
BEGIN   INTEGER w;
.skip
    w:= t.Length;   t:= NOTEXT;
.skip
    IF w = 0 THEN ! NOTEXT !; ELSE
    IF x = 0 THEN t.Sub(w,1).Putchar('0') ELSE
    BEGIN   REAL saved;   BOOLEAN negative;
	INTEGER d,i,pow,j;
.skip
	negative:= x < 0;   d:= 8;  ! No. of sign. digits;
	saved:= x;   x:= Abs(x);
.skip
	IF x >= _&8 OR x < _&-7 THEN
	realedit:
	BEGIN   pow:= 0;
	    WHILE x >= 10 DO
	    BEGIN   x:= x*0.1;   pow:= pow + 1   END;
	    WHILE x < 1 DO
	    BEGIN   x:= x*10;    pow:= pow - 1   END;
	    ! Calculate length for exp part;
	    j:= IF pow >= 10 THEN 3 ELSE
	   	IF pow >=  0 THEN 2 ELSE
		IF pow >= -9 THEN 3 ELSE 4;
.skip
	    i:= w - j;
	    IF i > (IF negative THEN 1 ELSE 0) THEN
	    BEGIN   CHARACTER low10;   TEXT temp;
		putfloat(t.Sub(1,i),x*sign(saved));
		t.Setpos(1);   IF t.Getchar = '*' THEN GO TO realcase;
		temp:- blanks(4); temp.putreal(1,0);
		temp.Setpos(1);  low10:= temp.getchar;
		t.Setpos(1);
		WHILE t.Pos <= i DO
		IF t.Getchar = low10 THEN GO TO realcase;
		t.Putchar(low10);
		t.Sub(i+2,j-1).Putint(pow);
	    END ELSE
	    realcase:
	    BEGIN   i:= w - (IF negative THEN 6 ELSE 5);
		IF i < 0 THEN i:= 0;
		IF d > i THEN d:= i;
		t.Putreal(saved,d)
	    END putreal case
	END realedit block ELSE
	BEGIN   INTEGER pow__d,pow__di,n1,m,di,ix;
.skip
	    pow:= 1;
	    pow__di:= pow__d:= 100 000 000;   ! = 10**d;
.skip
	    ! Scale x to [0.1,1-eps] ;
	    WHILE x >= 1.0 DO
	    BEGIN   x:= x*0.1;
		IF pow__di = 1 THEN GO TO realedit;
		pow__di:= pow__di//10;
		i:= i - 1
	    END;
	    WHILE x < 0.1 DO
	    BEGIN   x:= x*10;  pow:= pow*10;
		i:= i + 1
	    END;
.skip
	    di:= d + i;
	    IF di < 0 THEN
	    BEGIN   d:= -i;   di:= 0  END;
.skip
	    ix:= x*pow__d;   ! IX now integer with full prec;
.skip
	    ! Fix 9999.... problem;
	    j:= Mod(ix,100);
	    IF j >= 90 THEN ix:= ix + 100 - j ELSE
	    IF j <= 10 THEN ix:= ix - j;
.skip
	    n1:= ix//pow__di//pow;	! =  Integer Part;
.skip
	    ! Calculate j = no. of chars before dec. point;
	    m:= n1;   j:= IF negative THEN 2 ELSE 1;
	    WHILE m >= 10 DO
	    BEGIN   m:= m//10;   j:= j + 1   END loop;
.skip
	    ix:= ix -(n1*pow__di)*pow;
	    ! ix = fraction ;
.skip
	    IF ix NE 0 THEN
	    ! Remove trailing zeros in IX;
	    WHILE Mod(ix,10) = 0 DO
	    BEGIN   ix:= ix//10;   di:= di-1   END mod loop;
.skip
	    IF j + (di+1)*Sign(ix) > w THEN GO TO realedit;
.skip
	    IF negative THEN n1:= -n1;
.skip
	    IF ix = 0 THEN t.Putint(n1) ELSE
	    BEGIN
		j:= w-di;
		IF negative AND n1 = 0 THEN
		t.Sub(j-2,2):= "-0" ELSE
		t.Sub(1,j-1).Putint(n1);
		t.Setpos(j);   t.Putchar('.');
		t.Sub(t.Pos,di).Putint(ix);
.skip
		! Fill in zeros;
		WHILE ix > 0 DO
		BEGIN   ix:= ix//10;  di:= di - 1  END loop;
		t.Setpos(j+1);
		FOR j:= 1 STEP 1 UNTIL di DO t.Putchar('0');
.skip
	    END fraction present
	END w > 0
    END x not = 0;
    putfloat:- t
END of putfloat;
.p -5,2,8
**** INTEGER PROCEDURE scan(command,n,arg,key,defaultkey);
.index ^^SCAN EXTERNAL INTEGER PROCEDURE, see also DECOM
.index ^^Command line scan, SCAN procedure
TEXT command;   INTEGER n;
TEXT ARRAY arg,key;   INTEGER defaultkey;
.f;.skip
Integer procedure SCAN will identify specified KEYs in a COMMAND text
string. SCAN performs - in order -
.p 0,1,5
.ls
.le;Does COMPRESS and UPCASE on the COMMAND string
.le;If the parm. DEFAULTKEY belongs to [1:N] and COMMAND string does
not start with the text KEY[DEFAULTKEY] then that key will
be assumed present in front of COMMAND.
.le;Locates (in order 1 to N) possible occurrences of the texts
defined in text array KEY[1:N].
.le;Makes ARG[x] :- whatever follows KEY[x] up to next KEY.
If the KEY is just present, but with no text following
then Blanks(1) is returned. Nonpresent KEY is indicated
with ARG[x] == NOTEXT.
.le;SCAN returns index for multiple used key in command string.
Thus, normally SCAN should return zero, indicating no
multiple used key.
.els
.nofill
.skip
Note that the contents of KEY must have Upper case letters only.
.nf
An example:
!	BEGIN
!	    EXTERNAL TEXT PROCEDURE conc,upcase,compress,
!	    rest,inline,checkextension;
!	    EXTERNAL CHARACTER PROCEDURE findtrigger;
!	    EXTERNAL INTEGER PROCEDURE search,scanint,scan;
!	    EXTERNAL REF (Infile) PROCEDURE findinfile;
!	    EXTERNAL REF (Outfile) PROCEDURE findoutfile;
!	
!	    TEXT ARRAY key,arg,default[1:6];
!	    TEXT command,infilename,outfilename;
!	    INTEGER avalue,index;
!	    BOOLEAN na,nb;
!	    REF (Infile) inf;
!	    REF (Outfile) outf;
!	
!	    key[1]:- Copy("/DEFAULT:/A:/NA/NB/N=");
!	    ! Save some space with this trick!;
!	    key[2]:- key[1].Sub(10,3);	!/A: ;
!	    key[3]:- key[1].Sub(13,3);	!/NA ;
!	    key[4]:- key[1].Sub(16,3);	!/NB ;
!	    ! This keyword (5) must come after /NA and /NB
!	    ! else it will swamp those keys (if present);
!	    key[5]:- key[1].Sub(19,2);	!/N  ;
!	    key[6]:- key[1].Sub(21,1);	!=   ;
!	    key[1]:- key[1].Sub(1,9);	!/DEFAULT: ;
!	
!	    start:
!	    FOR index:= scan(inline("*",Sysin),6,arg,key,1)
!           WHILE index NE 0 DO
!	    BEGIN   Outtext("? Keyword:");
!		Outtext(key[index]);
!		Outtext(" used more than once.");
!               Outtext(" Please try again.");
!	        Outimage;
!	    END loop;
!	
!	    ! Analyze result:;
!	    ! Assume the user entered: abc=def/A:12/N  ;
!	    ! The result will then be:
!	    ! arg[1] = "ABC"
!	    ! arg[2] = "12"
!	    ! arg[3] == NOTEXT
!	    ! arg[4] == NOTEXT
!	    ! arg[5] = " "
!	    ! arg[6] = "DEF"
!	    ;
!	
!	    ! Test file information;
!	    ! Default inputname is outputname;
!	    IF arg[6] == NOTEXT THEN arg[6]:- arg[1];
!	    infilename:- arg[6];
!	
!	    ! We also demonstrate a way of checking
!	    ! entered file specifications;
!	    IF infilename NE "TTY:" THEN
!	    BEGIN
!	        infilename:-
!	        checkextension(infilename,".EXT");
!	        FOR inf:- findinfile(infilename) WHILE
!	        inf == NONE DO
!	        BEGIN   Outtext("? Cannot find Infile:");
!	            Outtext(infilename);
!	            Outimage;
!	            infilename:-
!	            inline("Enter name of infile:",Sysin);
!	            infilename:-
!	            checkextension(infilename,".EXT");
!	        END loop;
!	    END not TTY ELSE
!	    inf:- Sysin;
!	
!	    outfilename:- arg[1];
!	    IF outfilename NE "TTY:" THEN
!	    BEGIN
!	        outfilename:-
!	        checkextension(outfilename,".EXT");
!	        FOR outf:-
!	        findoutfile(outfilename)  WHILE outf ==
!	        NONE DO
!	        BEGIN
!	            Outtext("? Cannot create Outfile:");
!	            Outtext(outfilename);
!	            Outimage;
!	            outfilename:-
!	            inline("Enter name of outfile:",Sysin);
!	            outfilename:-
!                   checkextension(outfilename,".EXT");
!	        END loop
!	    END ELSE outf:- Sysout;
!	
!	    ! Check value switch /A: ;
!	    IF arg[2] == NOTEXT THEN
!	    BEGIN   !.... Set default value arg[2]:- ... ;
!	    END;
!	    avalue:= scanint(arg[2]);
!	    ! Assume range [1,99];
!	    ! Check result, Pos = 1 is unsuccessful
!	    deediting, More indicates
!	    ! superfluous information in value;
!	    IF avalue < 0 OR avalue > 99 OR arg[2].Pos = 1
!	    OR arg[2].More THEN
!	    BEGIN   Outtext("? Illegal /A: value:");
!	        Outtext(arg[2]);
!	        Outimage;
!	        GO TO start;
!	    END;
!	
!	    ! Assume  /N short for /NA ;
!	    IF arg[3] == NOTEXT THEN arg[3]:- arg[5];
!	    na:= arg[3] =/= NOTEXT;
!	    ! More strict: IF arg[3] = " " THEN na:= TRUE
!	    ELSE Error;
!	    ! Error would indicate the string
!	    "/NAxxx/....";
!	
!	    nb:= arg[4] =/= NOTEXT;
!	
!	    !....;
!	
!	END of program
.skip
EXTERNAL Procedures required:
TEXT PROCEDURE conc,upcase,compress;
INTEGER PROCEDURE search;
.skip
IF n < 1 THEN
BEGIN  IF Pos > 1 THEN Outimage;
    Outtext("%SCAN - Illegal parm! N < 1.");
    Outimage
END ELSE
BEGIN
    INTEGER ARRAY keypos[1:n];   INTEGER i,j,posmin,keyposi;
.skip
    OPTIONS(/A);   arg[1]:- arg[n];   key[1]:- key[1];
    key[n]:- key[n];;   OPTIONS(/-A);
    command:- compress(command,' ');
    upcase(command);
    IF defaultkey > 0 AND defaultkey <= n THEN
    BEGIN
        IF (IF command.Length < key[defaultkey].Length
        THEN TRUE
        ELSE command.Sub(1,key[defaultkey].Length)
        NE key[defaultkey] ) THEN
        command:- conc(key[defaultkey],command);
    END default key ELSE command:- Copy(command);
.skip
    FOR i:= 1 STEP 1 UNTIL n DO
    BEGIN
        command.Setpos(1);
        j:= search(command,key[i]);
        IF j <= command.Length THEN
        BEGIN
            command.Sub(j,key[i].Length):= NOTEXT;
            keypos[i]:= j;
            command.Setpos(j+key[i].Length);
            IF search(command,key[i]) <= command.Length THEN
            BEGIN  scan:= i;   GO TO exit;   END mult key;
        END key found
    END i loop;
.skip
    FOR i:= 1 STEP 1 UNTIL n DO
    IF keypos[i] > 0 THEN
    BEGIN
        keyposi:= keypos[i];
        ! Search smallest keypos[j] > keypos[i];
        posmin:= command.Length + 1;
        FOR j:= 1 STEP 1 UNTIL n DO
        IF keypos[j] > keyposi THEN
        BEGIN
            IF keypos[j] < posmin THEN posmin:= keypos[j];
        END j loop;
.skip
        j:= keyposi + key[i].Length;
        arg[i]:- IF posmin = j THEN Blanks(1) ELSE
        command.Sub(j,posmin-j);
    END keypos[i] > 0 ELSE arg[i]:- NOTEXT;
.skip
    exit:
END of scan;
.p -5,2,8;**** SSCAN
.index ^^SSCAN version of SCAN
is a version of SCAN used by GETVIS (see chapter 1).
SSCAN accepts swedish letters and does not zero the "arg" array
for unused switches.
.p -5,2,8;**** DECOM
.index ^^DEC-style command interpreter, DECOM
.index ^^Command interpreter (DEC-10 style), DECOM
.index ^^DECOM EXTERNAL CLASS, see also SCAN
is a package to simplify the writing of SIMULA programs
which accept input in the conventional DEC-10 format:
.sk;OUTFIL.EXT/SWITCH1/SWITCH2...=INFIL.EXT/SWITCH3...
.s;DECOM is a subclass of SAFMIN (See SAFEIO).
.s;Files: DECOM.SIM and DECOM.HLP. DECOM.ATR and DECOM.REL are
included in LIBSIM.
.s;Written by Jacob Palme and Mats Ohlin, Swedish National Defense
Research Institute.
.p -5,2,8;.f
**** TEXT PROCEDURE radix(base,i);   INTEGER base,i;
.index ^^RADIX EXTERNAL TEXT PROCEDURE
.skip
TEXT PROCEDURE RADIX returns a text containing
the representation of input I in radix BASE.
BASE may be negative but not -1 or zero.
Resulting text will never contain blanks.
If BASE = 16 then sequence 0123456789ABCDEF will be used,
otherwise if BASE > 10 then
the sequence 0123456789(10)(11)(12)... will be used.
.skip
C.f. INTEGER PROCEDURE GETRADIX
.skip
Author: Mats Ohlin, FOA 1, Fack, S-104 50 STOCKHOLM, SWEDEN.
Date: 76-12-10
.skip
.nf
IF i = 0 THEN radix:- Copy("0") ELSE
IF base = 0 OR base = -1 OR base = 1 THEN radix:- Copy("*") ELSE
BEGIN   INTEGER j,ndig,abase;   BOOLEAN neg;
    TEXT t;   REF (dig) xdig;
.skip
    CLASS dig(c);   CHARACTER c;
    BEGIN   REF (dig) next;
        next:- xdig;   xdig:- THIS dig;
        ndig:= ndig + 1;
    END dig;
.skip
    abase:= base*Sign(base);
    IF base > 0 THEN neg:= i < 0;
    IF neg THEN i:= -i;
    WHILE i NE 0 DO
    BEGIN   j:= Mod(i,base);
        IF j < 0 THEN
        BEGIN   j:= j - base;   i:= i + base  END;
        ! 48 = '0'    55 + 10 = 'A' ;
        IF j <= 9 THEN NEW dig(Char(j+48)) ELSE
        IF abase = 16 THEN NEW dig(Char(j+55)) ELSE
        BEGIN   NEW dig(')');
            WHILE j NE 0 DO
            BEGIN   NEW dig(Char(Mod(j,10)+48));
                   j:= j//10
            END;
            NEW dig('(');
        END unusual base;
        i:= i//base;
    END loop;
    IF neg THEN NEW dig('-');
    t:- Blanks(ndig);
    WHILE xdig =/= NONE DO
    BEGIN   t.Putchar(xdig.c);   xdig:- xdig.next  END;
    t.Setpos(1);
    radix:- t
END of radix;
.f;.p -5,2,8
**** INTEGER PROCEDURE getradix(base,t);
.index ^^GETRADIX EXTERNAL INTEGER PROCEDURE
.nf
INTEGER base;   TEXT t;
.skip
INTEGER PROCEDURE GETRADIX converts a text T containing
an item in base BASE to the corresponding base-10 integer.
.skip
If BASE <= 10 only the characters 012...(BASE-1) may be used.
If BASE = 16 or -16 then the char:s 0..9 A..F may be used.
For all other bases the sequence should be written:
01...9(10)(11)(12)....
Note that texts containing illegal characters will
always be (somehow) interpreted.
.skip
C.f. TEXT PROCEDURE RADIX.
.skip
Author: Mats Ohlin, FOA 1, Fack, S-104 50 STOCKHOLM, SWEDEN.
Date: 76-12-10
.skip
.nf
EXTERNAL Procedures required:
CHARACTER PROCEDURE fetchar;
TEXT PROCEDURE from;
.skip
IF t = "0" THEN error: getradix:= 0 ELSE
IF base > 1 OR base < -1 THEN
BEGIN   INTEGER sum,b,i,flag;   CHARACTER c;
BOOLEAN neg,signflag;
.skip
    ! Skip leading blanks and sign;
    FOR c:= fetchar(t,1) WHILE c = ' ' OR c = '+'
    OR c = '-' DO
    BEGIN   t:- from(t,2);
        IF c = '-' OR c = '+' THEN
        BEGIN   neg:= c = '-';
            IF signflag THEN GO TO error;
            signflag:= TRUE;
        END sign;
    END c loop;
.skip
    ! Check first char;
    IF (IF c = '(' OR Digit(c) THEN TRUE
    ELSE 'A' <= c AND c <= 'F' AND (base = 16 OR
    base = -16) ) THEN
    BEGIN
        ! See how long the item is;
        t.Setpos(1);
        WHILE t.More DO
        BEGIN   c:= t.Getchar;
            IF Digit(c) THEN !ok; ELSE
            IF c = '(' THEN flag:= flag + 1 ELSE
            IF c = ')' THEN flag:= flag - 1 ELSE
            IF 'A' <= c AND c <= 'F' AND (base = 16 OR
            base = -16) THEN ! OK; ELSE
            GO TO endoft;
            IF flag < 0 THEN GO TO endoft ELSE
            IF flag > 1 THEN
            BEGIN   t.Setpos(t.Pos-2);
            GO TO endoft   END;
.skip
        END more loop;
        endoft:   IF t.More THEN t:- t.Sub(1,t.Pos-1);
.skip
        ! Start summation;
        b:= 1;
        FOR i:= t.Length STEP -1 UNTIL 1 DO
        BEGIN
            c:= fetchar(t,i);
            IF c NE ')' THEN
            sum:= sum + b*(Rank(c)-(IF Letter(c) THEN 55
            ELSE 48)) ELSE
            BEGIN
                i:= i - 2;
                FOR c:= fetchar(t,i)
                WHILE c NE '(' AND i > 1 DO
                i:= i - 1;
                IF i > 0 THEN
                sum:= sum + b*from(t,i+1).Getint;
            END (..) ;
            IF i > 1 THEN b:= b*base;
        END i loop;
        getradix:= sum*(IF neg THEN -1 ELSE 1)
    END starts with ( or Digit
END of getradix;
.p -5,2,8;.f
**** INTEGER PROCEDURE arrlgd(ta);
.br;TEXT ARRAY ta;
.INDEX ^^ARRLGD EXTERNAL INTEGER PROCEDURE
.s;Computes the sum of the lengths of all text array elements in TA,
plus 1 for each element in the array, allowing for a delimiter after
each element. To be used for computing the length of the second
parameter to ARRTXT (see below). Part of the SIMDBM system.
.index ^^SIMDBM, ARRLGD utility procedure
.p -5,2,8;.f
**** PROCEDURE arrtxt(ta,t,c);
.br;TEXT ARRAY ta;  TEXT t; CHARACTER c;
.INDEX ^^ARRTXT EXTERNAL PROCEDURE
.s;Copies the contents of all elements of TA to T.
The character C is placed after each copied text.
Example:
.br;TA[1:4] contains "ABC", "X", "123456", "FINISH".
T:- Blanks(ARRLGD(TA)); ARRTXT(TA,T,',') will make
T = "ABC,X,123456,FINISH,".
.BR;Used in the SIMDBM system.
.index ^^SIMDBM, ARRTXT utility procedure
.st 5.4 INPUT/OUTPUT
.f;.p -5,5,25
.index ^^INPUT/OUTPUT
5.4 INPUT/OUTPUT
.p -5,1,14;.nf;**** CHARACTER PROCEDURE lookahead(fileref);
REF(Infile COMMENT or Directfile;) fileref;
.index ^^LOOKAHEAD EXTERNAL CHARACTER PROCEDURE
.sk;.f
.s;Returns the next non-blank character value which would
have
been the result of inchar. IF lastitem THEN
result will be blank;
.sk;.nf
INSPECT fileref DO
BEGIN
  IF lastitem THEN lookahead:= ' ' ELSE
  BEGIN lookahead:= inchar; setpos(pos-1);
  END;
END;
.if notready
.p -5,2,11;**** PROCEDURE outline(t,out__file); VALUE t;
TEXT t; REF (outfile) out__file;
.index ^^OUTLINE EXTERNAL PROCEDURE
.fill
.s;OUTLINE will output the argument text as one or more lines on the output device.
Protected against errors when the parameter text is longer than
the image.
.nf
INSPECT out__file DO
BEGIN
  WHILE t.length > length DO
  BEGIN
    outtext(t.sub(1,length));
    t:- t.sub(length+1,t.length-length);
    outimage;
  END;
  outtext(t);
  outimage;
END;
.endif notready
.if notready
.p -5,2,9
**** PROCEDURE breakoutline(t,out__file); VALUE t;
TEXT t; REF (outfile) out__file;
.index ^^BREAKOUTLINE EXTERNAL PROCEDURE
.fill
.s;Same as OUTLINE, but does not output any new line indication
(<CR><LF> on ASCII terminals) before and after the text.
.nofill
INSPECT out__file DO
BEGIN
  WHILE t.length > length DO
  BEGIN
    breakoutimage;
    outtext(t.sub(1,length));
    t:- t.sub(length+1,t.length-length);
  END;
  outtext(t);
  breakoutimage;
END;
.endif notready
.p -5,2,8;**** TEXT PROCEDURE inline(question,inf);   NAME question;
TEXT question;   REF (infile) inf;
.index ^^INLINE EXTERNAL TEXT PROCEDURE
.s;Returns a stripped copy of a new INF input line
after displaying QUESTION on Sysout.
.s;INSPECT (IF inf == NONE THEN Sysin ELSE inf) DO
BEGIN   Sysout.Outtext(question);
    Sysout.Breakoutimage; Inimage;
    inline:- Copy(Image.Strip);
    Setpos(0);
END;
.sk.f
.nofill
.p -5,2,8
**** TEXT PROCEDURE request
.index ^^REQUEST EXTERNAL TEXT PROCEDURE
(prompt,default,result,valid,errmessage,help);
    NAME prompt,default,result,valid,errmessage,help;
    TEXT prompt,default,result,errmessage,help;
    BOOLEAN valid;
.skip
.fill
Procedure REQUEST may be used when putting simple questions to
an interactive user.
The PROMPTing question and the DEFAULT value will be displayed on
the user's terminal (SYSOUT).  The Stripped input line from the terminal (SYSIN)
is stored in RESULT. If then the NAME parameter VALID is TRUE
the result is accepted and (also) returned through REQUEST.
Otherwise the ERRMESSAGE is displayed followed by a new
PROMPTing question. If the user enters an empty answer -
i.e. presses the return key - the DEFAULT answer will be used.
(This may be prohibited by using an illegal answer for default.)
If the user enters a question mark '?', the text HELP will
be printed. Since it is a NAME parameter, actual parameter
may be a text procedure call with the possible side effect of
displaying additional help text.
.s;Since it may be difficult the remember the different parameters -
learn the following sentence:
Please ( P for Prompt)  Don't (D for Default) Risk (R for Result)
Villainous (V for Valid) Entries (E for Errmessage) Here (H for Help).
.nf;.s;Example:
!BEGIN EXTERNAL TEXT PROCEDURE conc,request,rest;
!    EXTERNAL REF (Infile) PROCEDURE findinfile;
!    EXTERNAL INTEGER PROCEDURE checkreal;
!
!    TEXT u;    REAL x;
!
!    request("File:",NOTEXT,u,
!    findinfile(u)=/=NONE,conc("? Can't find:",u),
!    "Enter valid file spec for input file.");
!
!    x:=
!    request("Enter x:","2.5",u,
!    checkreal(u) = 1 AND rest(u).Strip == NOTEXT,
!    "?Illegal real item.","Enter valid real item").Getreal;
!
!END
.skip
.lm 1
    ! For more frequent applications it is recommended to use
    ! a special validity testing Boolean procedure with the
    ! side-effect of saving (the finally correct) result.
    ! I.e.
    ! EXTERNAL TEXT PROCEDURE rest,request;
    ! EXTERNAL LONG REAL PROCEDURE scanreal;
    !
    ! BOOLEAN PROCEDURE testreal(u,x);
    ! NAME x;   TEXT u;   REAL x;
    ! BEGIN   INTEGER p;
    !     p:= u.Pos;   x:= scanreal(u);
    !     testreal:= IF u.Pos > p THEN rest(u).Strip == NOTEXT
    !                ELSE FALSE;
    ! END of testreal;
    !
    !    request("Enter x:","2.5",u,testreal(u,x),
    !    "?Illegal real item.","Enter valid real item");
.lm 5;.skip
TEXT PROCEDURE request
(prompt,default,result,valid,errmessage,help);
NAME prompt,default,result,valid,errmessage,help;
TEXT prompt,default,result,errmessage,help;
BOOLEAN valid;
BEGIN   TEXT t;
.skip
    GO TO start;
.skip
    WHILE NOT valid DO
    BEGIN
	Outtext(errmessage);   Outimage;
	start:
	Outtext(prompt);
	IF default =/= NOTEXT THEN
	BEGIN   Outchar('/');   Outtext(default);
	    Outchar('/');   Outchar(':')
	END;
	Breakoutimage;   Inimage;
	t:- Copy(Sysin.Image.Strip);   Sysin.Setpos(0);
	IF t == NOTEXT THEN result:- Copy(default) ELSE
	IF t.Getchar = '?' THEN
	BEGIN   Outtext(help);   Outimage;
	    GO TO start
	END ELSE
	BEGIN   t.Setpos(1);   result:- t   END;
    END loop;
.skip
    request:- result
.skip
END of request;
.p -5,2,9;**** PROCEDURE outtime(file,time,unit,secdec,fieldwidth);
.index ^^OUTTIME EXTERNAL PROCEDURE
.br;REAL time;   CHARACTER unit;   INTEGER secdec,fieldwidth;   REF (Outfile) file;
.s;Prints the variable TIME on the outfile FILE according
to PUTTIME format. C.f. procedure PUTTIME.
.br;EXTERNAL PROCEDURES required:
.br;TEXT PROCEDURE putfloat, puttime;
.f;.lm 5;.p -5,2,10
**** PROCEDURE histp(a,lowerbound,upperbound,yscale,
.index ^^HISTP EXTERNAL PROCEDURE
.br
max,min,brick,xlabels,title,pf);
.br
NAME title,xlabels;   VALUE brick;
.br
INTEGER ARRAY a;
.br
INTEGER lowerbound,upperbound,yscale,max,min;
.br
TEXT brick,xlabels,title;   REF (Outfile) pf;
.skip
Procedure HISTP prints a histogram of the
INTEGER ARRAY   A [LOWERBOUND:UPPERBOUND] on file PF.
.skip
YSCALE is the increment for the y axis (Integer > 0).
.br
MAX is the maximum y value displayed (INTEGER).
.br;MIN is the minimum y value displayed (INTEGER).
.skip
BRICK is a text which will be used when printing histogram "piles"
(TEXT by VALUE).
.skip
XLABELS is a text that will be printed at the bottom of the histogram.
If XLABELS == NOTEXT the indices LOWERBOUND and UPPERBOUND will
be printed. The start of the text will be at the first "brick"
character of the first "pile".
.skip
TITLE is a text that will be printed at the top of the histogram.
.skip
PF is the output file. If PF is a PRINTFILE, HISTP will start by calling
EJECT(1).
.skip
   Please note the following HISTP properties:
.skip
.p 0,1,0;.ls
.le;If MAX < MIN, the MAX and MIN values will be adjusted if
necessary (individually!). Thus, if MAX = -1 and MIN = 0
an array A with only positive elements will be presented in
a histogram with y axis range [0:max of A].
.le;If (resulting) MIN is zero, this level will be indicated by
the x axis (----).
.le;If BRICK starts with a blank, a single space between "piles"
will be printed.
.le;IF PF == NONE, Sysout will be used.
.le;IF the range [LOWERBOUND:UPPERBOUND] in combination with actual
BRICK.LENGTH cannot be printed on one page regarding current
PF.Length, then the rest (the rightmost part) of the histogram
will be printed on a subsequent page.
.els
.skip
An example:
.skip
Input:
.skip
.nofill
A[0:6]:=  5 -3 -1 0 3 4 2
YSCALE:=  1
MAX:=     -10
MIN:=      10
BRICK:=   " ***"
XLABELS:=  "  A   B   C   D   E   F   G"
TITLE:=    "Test example - histogram print"
PF:-       NONE
.skip
   will produce the following output on SYSOUT:
.skip
             Test example - histogram print
.skip
           5 ! ***
             ! ***                 ***
             ! ***             *** ***
             ! ***             *** *** ***
           1 ! ***             *** *** ***
             !----------------------------
             !     *** ***
             !     ***
          -3 !     ***
              --+---+---+---+---+---+---+-
                A   B   C   D   E   F   G
.skip
IF lowerbound > upperbound THEN
BEGIN   Outtext("?HISTP Illegal Array Bounds");   Outimage  END
ELSE IF yscale <= 0 THEN
BEGIN   Outtext("?HISTP Non-positive Y-scale element");   Outimage   END
ELSE
BEGIN
    INTEGER i,up,newupperbound,h2,
    tempmax,tempmin,width,negscale;
    TEXT axis;
.skip
    width:= brick.Length;
    axis:- Blanks(width);
    WHILE axis.More DO axis.Putchar('-');
    IF pf == NONE THEN pf:- Sysout;
.skip
    IF max < min THEN
    BEGIN   tempmin:= tempmax:= a[lowerbound];
	FOR i:= lowerbound+1 STEP 1 UNTIL upperbound DO
	IF a[i] > tempmax THEN tempmax:= a[i] ELSE
	IF a[i] < tempmin THEN tempmin:= a[i];
	IF max < tempmax THEN max:= tempmax;
	IF min > tempmin THEN min:= tempmin;
    END loop setting max and min;
.skip
    h2:= (max+min)//2;
.skip
    IF (upperbound - lowerbound + 1)*width + 15 > pf.Length
    THEN
    BEGIN   newupperbound:= upperbound;
	upperbound:= (pf.Length-15)//width + lowerbound - 1
    END
    ELSE newupperbound:= lowerbound - 1;
    ! That was checking histogram width;
.skip
    INSPECT pf WHEN Printfile DO
    BEGIN   Eject(1);   Setpos(14);   Outtext(title);
	Outimage;   Eject(Line+2)
    END
    WHEN Outfile DO
    BEGIN   Setpos(14);   Outtext(title);
	Outimage;   Outimage
    END;
.s
    up:= ((h2-min)//yscale)*yscale + min;
    IF up < h2 THEN up:= up + yscale;   h2:= up;
    up:= ((max-min)//yscale)*yscale + min;
    IF up < max THEN up:= up + yscale;
.s
    pf.Outint(up,12);   pf.Outtext(" !");
    negscale:= - yscale;
    FOR up:= up STEP negscale UNTIL min DO
    IF NOT (up = min AND min = 0) THEN
    BEGIN
	IF up = h2 OR up = min THEN
	BEGIN   pf.Setpos(1);   pf.Outint(up,12);
	    pf.Outtext(" !")
	END
	ELSE
	BEGIN   pf.Setpos(14);   pf.Outchar('!')   END;
.skip
	IF up NE 0 THEN
	BEGIN
	    FOR i:= lowerbound STEP 1 UNTIL upperbound DO
	    IF a[i] = up THEN pf.Outtext(brick) ELSE
	    IF a[i] > up EQV up >= 0 THEN pf.Outtext(brick)
	    ELSE pf.Setpos(pf.Pos+width);
	END ne 0 ELSE
	IF min < 0 THEN
	BEGIN   pf.Setpos(14);   pf.Outchar('!');
	    FOR i:= lowerbound STEP 1 UNTIL upperbound DO
	    pf.Outtext(axis);
	END zero axis;
.skip
	pf.Outimage
.skip
    END print loop;
.skip
    pf.Setpos(15);
    FOR i:= lowerbound STEP 1 UNTIL upperbound DO
    pf.Outtext(axis);
    i:= (upperbound-lowerbound)*width+15+width//2;
    IF width > 1 THEN
    BEGIN
	FOR h2:= 15+width//2 STEP width UNTIL i DO
	BEGIN   pf.Setpos(h2);   pf.Outchar('+')   END;
    END;
    pf.Outimage;
    IF xlabels == NOTEXT THEN
    BEGIN
	pf.Outint(lowerbound,15+width//2);
	IF i > pf.Length THEN i:= pf.Length - 4;
	pf.Setpos(i-4);   pf.Outint(upperbound,5);
    END ELSE
    BEGIN   pf.Setpos(15);   pf.Outtext(xlabels)   END;
    pf.Outimage;
    IF newupperbound >= upperbound THEN
    histp(a,upperbound+1,newupperbound,yscale,max,min,
    brick,xlabels,title,pf);
.skip
END of histp;
.skip
.fill
.subtitle 5.5 SORTING AND SUMMATION ETC.
.p -5,4,28
.index ^^SORTING AND SUMMATION ETC.
5.5 SORTING AND SUMMATION ETC.
.index ^^ILOG EXTERNAL INTEGER PROCEDURE
.fill
.p -5,3,8
**** INTEGER PROCEDURE ilog(x);   REAL x;
.fill
ilog:= IF x = 0 THEN 0 ELSE
.br;Entier(Ln(Abs(x))/2.30258 509517)+1;
.skip
.nofill
.p -5,2,8
.index ^^ISUM EXTERNAL INTEGER PROCEDURE
**** INTEGER PROCEDURE isum(ia,n);
INTEGER ARRAY ia;   INTEGER n;
.fill
.s;Procedure ISUM calculates the sum of the integer array IA:
IA[1]#+#...#+#IA[N].
.s;.nf;BEGIN   INTEGER i,s;
.skip
    OPTIONS(/A); COMMENT START ARRAY BOUND CHECKING;
    s:= ia[1];
    ia[n]:= ia[n];;
    OPTIONS(/-A); COMMENT NO ARRAY BOUND CHECKING;
    FOR i:= 2 STEP 1 UNTIL n DO  s:= s + ia[i];
.skip
    isum:= s
.skip
END of isum;
.skip 2
.indent -5
.index ^^RSUM EXTERNAL REAL PROCEDURE
**** REAL PROCEDURE rsum(a,n);   ARRAY a;   INTEGER n;
.fill
.s;Procedure RSUM calculates the sum of the array A:
A[1]#+#...#+#A[N].
.s;.nf;BEGIN   INTEGER i;   REAL s;
.skip
    OPTIONS(/A); COMMENT START ARRAY BOUND CHECKING;
    s:= a[1];   a[n]:= a[n];;
    OPTIONS(/-A); COMMENT NO ARRAY BOUND CHECKING;
    FOR i:= 2 STEP 1 UNTIL n DO  s:= s + a[i];
.skip
    rsum:= s
.skip
END of rsum;
.skip 2
.indent -5
.index ^^LSUM EXTERNAL LONG REAL PROCEDURE
**** LONG REAL PROCEDURE lsum(la,n);
LONG REAL ARRAY la;   INTEGER n;
.fill
.s;Procedure LSUM calculates the sum of the long real
array LA, LA[1]#+#...#+#LA[N] (almost) preserving precision.
Thus if LA[1] = E30, LA[2] = 1 and LA[3] = -E30 the sum will
be correctly calculated to 1.
.nofill
EXTERNAL Procedure required: INTEGER PROCEDURE intrea;
.s;BEGIN   INTEGER i,icell,high,low;   LONG REAL s;
    LONG REAL ARRAY cell[0:63];
.s;    OPTIONS(/A); COMMENT START ARRAY BOUND CHECKING;
    la[n]:= la[n];
.s;    icell:= intrea(la[1])//8R4000000000;;
    OPTIONS(/-A); COMMENT NO ARRAY BOUND CHECKING;
    IF icell < 0 THEN icell:= -icell;
    high:= low:= icell;
    cell[icell]:= la[1];
    FOR i:= 2 STEP 1 UNTIL n DO
    BEGIN   icell:= intrea(la[i])//8R4000000000;
        ! Store LA[I] in CELL [ Abs(exp-part of LA[I]) ];
        ! Thus E+MM and -E+MM will be accumulated in the
        ! same cell;
        IF icell < 0 THEN icell:= -icell;
        IF icell > high THEN high:= icell ELSE
        IF icell < low THEN low:= icell;
        cell[icell]:= cell[icell] + la[i];
    END loop;
.s;    ! Sum starting with small values;
    FOR i:= low STEP 1 UNTIL high DO
    s:= s + cell[i];
    lsum:= s
.s;END of lsum;
.p -5,2,8
.index ^^SIGMA2 EXTERNAL REAL PROCEDURE
**** REAL PROCEDURE sigma2(mean,sum,a,n);
.break
NAME mean,sum;   REAL mean,sum;
.break
ARRAY a;   INTEGER n;
.fill
.s;Real procedure SIGMA2 calculates the variance, mean value and sum
of a REAL ARRAY A, from A[1] to A[N].
Array A must be declared before calling SIGMA2 and have a lower
bound <= 1 and a upper bound >= N.
Results are returned in -
.nofill
.skip
SIGMA2		Variance
MEAN		Mean value
SUM		Sum
.s;IF n > 0 THEN
BEGIN   REAL s,s2,x;   INTEGER i;
.skip
    OPTIONS(/A); COMMENT START ARRAY BOUND CHECKING;
    s:= a[1];   a[n]:= a[n];;
    OPTIONS(/-A); COMMENT NO ARRAY BOUND CHECKING;
    s2:= s_^2;
    FOR i:= 2 STEP 1 UNTIL n DO
    BEGIN   x:= a[i];
	s:= s + x;
	s2:= s2 + x_^2;
    END;
.skip
    x:= 1/n;
    sigma2:= (s2 - s_^2*x)*x;
    mean:= s*x;
    sum:= s;
END of sigma2;
.p -5,2,8;.index ^^SIGMEAN EXTERNAL PROCEDURE
**** PROCEDURE sigmean(sigma2,mean,k,xk1);
NAME sigma2,mean,k;   REAL sigma2,mean,xk1;   INTEGER k;
.fill
.s;Procedure SIGMEAN calculates new sigma2 (variance) and mean value
for a statistical material where the following properties are known -
.skip
.nofill
Old variance				SIGMA2
Old mean value				MEAN
Number of observations made before	K
Value of new observation		XK1
.skip
At return the following values are available -
.skip
New variance				SIGMA2
New mean value				MEAN
Number of observations (=K+1)		K
.skip
An example:
.skip
! BEGIN
! EXTERNAL PROCEDURE sigmean;
! REAL sigma2,mean;
! INTEGER k;
! ....
! k:= 0;
! mean:= sigma2:= 0;
! ...
! WHILE ... DO
! BEGIN
!    ... x:= <new observed value>;
!    sigmean(sigma2,mean,k,x);
! END loop;
! ...
.fill
.skip
Note that some precision will be lost using SIGMEAN, compared with
the result of calculating the variance and mean value from all
the observations. However, since SIGMEAN calculates the variance and
mean value recursively, there is no need to save all the earlier
observations in an array.
.s;.nf;BEGIN   REAL oldsigma2,oldmean,ik1,z;   INTEGER oldk,k1;
.skip
    oldsigma2:= sigma2;
    oldmean:= mean;
    oldk:= k;
    k:= k1:= oldk + 1;
    ik1:= 1.0/k1;
    z:= (oldmean-xk1)*ik1;
    mean:= xk1 + oldk*z;
    sigma2:= oldk*(oldsigma2*ik1 + z_^2);
END of sigmean;
.p -5,3,15
.index ^^SORT PROCEDURES
.index ^^SORTTA EXTERNAL PROCEDURE
.skip
.fill
.if notready
The sorting procedures SORTTA, SORTTD, SORTIA, SORTID, SORTRA, SORTRD, SORTLA, SORTLD
may be coded as one external assembly module accepting any kind of
TEXT, [LONG] REAL or INTEGER one-dimensional array.
.endif notready
.skip 2
.indent -5
.nofill
**** PROCEDURE sortta (arr,n);
TEXT ARRAY arr;   INTEGER n;
.fill
.s;Procedure SORTTA will sort the contents
of the TEXT array in ASCENDING order.
Author: Algorithm 271 CACM 11-65, 5-66.
Modified by: Mats Ohlin, FOA 1, S-104 50 STOCKHOLM 80, SWEDEN.
.s;.nofill
BEGIN   INTEGER i,k,q,m,p;   TEXT t,x;
  INTEGER ARRAY ut,lz [1:Ln(Abs(n)+2)/0.69314718];
.skip
.nofill
  OPTIONS(/A); COMMENT START ARRAY BOUND CHECKING;
  IF arr[1] > arr[n] THEN
  BEGIN ; OPTIONS(/-A);
    t:- arr[1];
    arr[1]:- arr[n];   arr[n]:- t
  END test and swap;
.skip
  i:= m := 1;
  WHILE m > 0 DO
  BEGIN
    IF n-i > 1 THEN
    BEGIN
      p:= (n+i)//2;    t:- arr[p];
      arr[p]:- arr[i];   q:= n;   k:= i;
      FOR k:= k+1 WHILE k <= q DO
      BEGIN
        IF arr[k] > t THEN
        BEGIN
          WHILE q >= k DO
          BEGIN
            IF arr[q] < t THEN
            BEGIN
              x:- arr[k];   arr[k]:- arr[q];
              arr[q]:- x;   q:= q-1;
              GO TO l;
            END;
            q:= q-1;
          END Q;
        END;
        l:
      END K;
      arr[i]:- arr[q];
      arr[q]:- t;
      IF 2*q>i+n THEN
      BEGIN
        lz[m]:= i;   ut[m]:= q-1;
        i:= q+1;
      END ELSE
      BEGIN
        lz[m]:= q+1;   ut[m]:= n;
        n:= q-1;
      END;
      m:= m+1;
    END ELSE
    BEGIN
      IF (
      IF i < n THEN arr[i] > arr[n] ELSE FALSE
      ) THEN
      BEGIN
        x:- arr[i];   arr[i]:- arr[n];
        arr[n]:- x
      END;
      m:= m-1;
      IF m > 0 THEN
      BEGIN   i:= lz[m];   n:= ut[m]   END;
    END
  END m > 0 loop;
END SORTTEXT IN ASCENDING ORDER;
.skip 2
.indent -5
.index ^^SORTTD EXTERNAL PROCEDURE
**** PROCEDURE sorttd (arr,n);
TEXT ARRAY arr;   INTEGER n;
.fill
.s;Procedure SORTTD will sort the contents
of the TEXT array in DESCENDING order.
Author: Algorithm 271 CACM 11-65, 5-66.
Modified by: Mats Ohlin, FOA 1, S-104 50 STOCKHOM 80, SWEDEN.
Date: 75-09-19
;
.nofill
.s;BEGIN   INTEGER i,k,q,m,p;   TEXT t,x;
  INTEGER ARRAY ut,lz [1:Ln(Abs(n)+2)/0.69314718];
.skip
.nofill
  OPTIONS(/A); COMMENT START ARRAY BOUND CHECKING;
  IF arr[1] < arr[n] THEN
  BEGIN ; OPTIONS(/-A);
    t:- arr[1];
    arr[1]:- arr[n];   arr[n]:- t
  END test and swap;
.skip
  i:= m := 1;
  WHILE m > 0 DO
  BEGIN
    IF n-i > 1 THEN
    BEGIN
      p:= (n+i)//2;    t:- arr[p];
      arr[p]:- arr[i];   q:= n;   k:= i;
      FOR k:= k+1 WHILE k <= q DO
      BEGIN
        IF arr[k] < t THEN
        BEGIN
          WHILE q >= k DO
          BEGIN
            IF arr[q] > t THEN
            BEGIN
              x:- arr[k];   arr[k]:- arr[q];
              arr[q]:- x;   q:= q-1;
              GO TO l;
            END;
            q:= q-1;
          END Q;
        END;
        l:
      END K;
      arr[i]:- arr[q];
      arr[q]:- t;
      IF 2*q>i+n THEN
      BEGIN
        lz[m]:= i;   ut[m]:= q-1;
        i:= q+1;
      END ELSE
      BEGIN
        lz[m]:= q+1;   ut[m]:= n;
        n:= q-1;
      END;
      m:= m+1;
    END ELSE
    BEGIN
      IF (
      IF i < n THEN arr[i] < arr[n] ELSE FALSE
      ) THEN
      BEGIN
        x:- arr[i];   arr[i]:- arr[n];
        arr[n]:- x
      END;
      m:= m-1;
      IF m > 0 THEN
      BEGIN   i:= lz[m];   n:= ut[m]   END;
    END
  END m > 0 loop;
END SORTTEXT IN DESCENDING ORDER;
.f;.p -5,2,10;**** PROCEDURE sortdn(arr,i1,n,key);
.index ^^Sorting a 2-dimensional integer array, SORTDN procedure
.index ^^SORTDN EXTERNAL PROCEDURE for sorting 2-dim integer array
.index ^^Directory sorting, SORTDN procedure
.index ^^UFD sorting, SORTDN procedure
.index ^^SFD sorting, SORTDN procedure
.br;INTEGER ARRAY arr; INTEGER i1,n,key;
.s;SORTDN sorts (a section of) the 2-dimensional array ARR[2,nmax].
The segment ARR[*,I1] to ARR[*,N] is sorted according to KEY in
ascending order.
KEY determines which column to regard as primary sorting key, and
whether to sort also on the secondary key, thus:
.br;KEY = 0: Sort first on ARR[1,*], then ARR[2,*].
.br;KEY = 1: Only sort on ARR[1,*].
.br;KEY = 2: Reverse of KEY = 1.
.br;KEY = 3: Reverse of KEY = 0.
.br;KEY < 0 or KEY > 3: as KEY = 0.
.br;ARR[1,i] and ARR[2,i] are always moved as a unit (2 words).
SORTDN is a modification of SORTIA (q.v.), which is a modification
by Mats Ohlin, FOA, of Algorithm 271 CACM 11-65, 5-66.
The SORTDN modification was made by Lars Enderin, FOA, for the purpose
of sorting UFD and SFD directory files under TOPS-10.
.skip 2
.p -5,2,8
**** REAL PROCEDURE scalestep(pmax,pmin,ptics);
.index ^^SCALESTEP EXTERNAL REAL PROCEDURE
.br
NAME pmax,pmin,ptics;   REAL pmax,pmin;   INTEGER ptics;
.skip
Procedure SCALESTEP calculates values suitable for axis design.
PMAX is input max (rough) value and at return increased
justified max value.
PMIN ditto decreased min value.
PTICS is number of increments along axis (Result parm.)
SCALESTEP is size of axis increment.
.skip
REAL PROCEDURE scalestep(pmax,pmin,ptics);
NAME pmax,pmin,ptics;   REAL pmax,pmin;   INTEGER ptics;
BEGIN
    REAL max,min,width,d;
    INTEGER n0,n1,pow;
.skip
    max:= pmax;   min:= pmin;
.skip
    width:= Abs(max - min);
    IF width NE 0 THEN
    BEGIN
.skip
	WHILE width > 10 DO
	BEGIN    width:= width*0.1;   pow:= pow + 1   END;
	WHILE width <= 1 DO
	BEGIN   width:= width*10;   pow:= pow - 1   END;
.skip

	! Normalize width ;
	IF width NE Entier(width) THEN
	width:=
	IF width > 8    THEN 10 ELSE
	IF width > 1.5  THEN Entier(width+1) ELSE
	IF width > 1.25 THEN 1.5 ELSE 1.25;
.skip
	! Calculate normalized increment ;
	d:=
	IF width >= 8.0 THEN 2 ELSE
	IF width > 3.5  THEN 1 ELSE
	IF width > 1.6  THEN 0.5 ELSE 0.25;
.skip
	! Now scale normalized increment d ;
	WHILE pow > 0 DO
	BEGIN   d:= d*10;    pow:= pow - 1   END;
	WHILE pow < 0 DO
	BEGIN   d:= d*0.1;   pow:= pow + 1   END;
.skip
	! Calculate number of increments ;
	n1:= Entier(max/d);
	IF n1*d < max THEN n1:= n1 + 1;
	n0:= Entier(min/d);
.skip
	ptics:= n1 - n0;
.skip
	pmax:= n1*d;   pmin:= n0*d;
.skip
	scalestep:= d;
.skip
    END width NE 0;
.skip
END of scalestep;
.p -5,2,8
.f;**** BOOLEAN PROCEDURE iashift(a,destindex,fromindex,length,zero);
.index ^^IASHIFT EXTERNAL BOOLEAN PROCEDURE
INTEGER ARRAY a;   INTEGER destindex,fromindex,length;
BOOLEAN zero;
.skip
IASHIFT moves LENGTH elements of the INTEGER ARRAY A,
starting at FROMINDEX, to DESTINDEX.
FROMINDEX must be >= DESTINDEX.
If ZERO is TRUE, then remaining elements to the right of
DESTINDEX+LENGTH-1 will be zeroed. Thus, IASHIFT(A,1,1,0,TRUE) will
make all elements in the array A[1:xx] zero.
.br;IASHIFT will return TRUE if the operation was successful -
illegal parameters will cause IASHIFT to return FALSE.
.s
Assuming accessibility of the lower and upper bounds of the array
the code would be:
.skip
.nf
IF destindex >= a.lower AND destindex <= a.upper AND
fromindex >= destindex AND fromindex+length <= a.upper+1 THEN
BEGIN   INTEGER i;
    IF destindex NE fromindex THEN
    FOR i:= 1 STEP 1 UNTIL length DO
    BEGIN   a[destindex]:= a[fromindex];
        destindex:= destindex + 1;
        fromindex:= fromindex + 1;
    END i loop ELSE
    destindex:= destindex + 1;
.sk
    IF zero THEN
    ! Zero the rest of a.
    ! Destindex now = next after last moved element;
    FOR i:= destindex STEP 1 UNTIL a.upper DO
    a[i]:= 0;
    iashift:= TRUE
END of iashift;
.p -5,2,6
.f;**** INTEGER PROCEDURE imax(i1,i2);   INTEGER i1,i2;
.index ^^IMAX EXTERNAL INTEGER PROCEDURE
.nf;COMMENT IMAX will replace the calling code by inline code;
imax:= IF i1 > i2 THEN i1 ELSE i2;
.p -5,2,6
.f;**** INTEGER PROCEDURE imin(i1,i2);   INTEGER i1,i2;
.index ^^IMIN EXTERNAL INTEGER PROCEDURE
.nf;COMMENT IMIN will replace the calling code by inline code;
imin:= IF i1 < i2 THEN i1 ELSE i2;
.f
.subtitle 5.6 RANDOM NUMBER GENERATION ETC.
.p -5,4,28
.index ^^RANDOM NUMBER GENERATION ETC.
5.6 RANDOM NUMBER GENERATION ETC.
.p -5,2,8
**** PROCEDURE SCRAMBLE(ia,bottom,top,u);
.index ^^SCRAMBLE EXTERNAL PROCEDURE
NAME u;
INTEGER ARRAY ia; INTEGER bottom, top, u;
.fill
.s;The INTEGER ARRAY ia is permuted randomly in the interval
bottom, top. The parameter u is the random number seed.
.p -5,2,8
**** CLASS PERGEN(a,n);   INTEGER ARRAY a;   INTEGER n;
.index ^^PERGEN EXTERNAL CLASS
.skip
CLASS PERGEN generates all the possible permutations
of the contents in INTEGER ARRAY a[1:N], one at a time.
.break
Use:
.break
REF (pergen) pg;
.break
pg:- NEW pergen(a,n);
.break
WHILE pg.cycles < 2 DO
.break
BEGIN   Call(pg);  ! use new permutation  END;
.skip
Note that N Must be >= 2.
Also observe that permutations are generated systematically and
that the order will be REVERSED when one N! cycle is completed.
Thus for N = 2 then result will be (if A[1]=1, A[2]=2 initially):
.break
(1 2) (2 1) (2 1) (1 2) (1 2) (2 1) etc.
.break
The permutations will be generated in such manner that
the last elements of A will change most slowly.
The attribute CYCLES will indicate to which cycle the NEXT
permutation will belong (after next Call that is).
.skip
Ref:"Generation of permutation sequences", A.D. Woodall,
The Computer Journal vol 20, No 4 1977 p 346.
.break
Modified by: Mats Ohlin, FOA, Stockholm, Sweden.
.skip
For random permutations see procedure SCRAMBLE.
.skip
External procedure required: IMAX
.skip
.nf
    CLASS pergen(a,n);  INTEGER ARRAY a;   INTEGER n;
    BEGIN
        INTEGER p,mp,swpt,i,w,cycles;
        INTEGER ARRAY m,km[2:imax(3,n)],
                        ret[2:imax(2,n)];
.skip
        IF n < 2 THEN
        BEGIN
            Outtext("%PERGEN - 2nd parm N must be >= 2");
            Outimage;
        END ELSE
        BEGIN
.skip
            OPTIONS(/A);
            a[1]:= a[1];  a[n]:= a[n];
            km[n]:= ret[n]:= km[2]:= ret[2];;
            OPTIONS(/-A);
.skip
            FOR i:= 4 STEP 2 UNTIL n DO
            BEGIN   p:= i-1;
                km[i]:= p;   km[p]:= 2-i;
            END i loop;
.skip
            GO TO run;
            start:   Detach;   run:
            cycles:= cycles + 1;
.skip
            FOR i:= 2 STEP 1 UNTIL n DO ret[i]:= i+1;
            FOR i:= 4 STEP 2 UNTIL n DO
            BEGIN   m[i]:= i-1;   m[i-1]:= 2-i
            END i loop;
            IF Mod(n,2) NE 0 THEN m[n]:= 1-n;
.skip
            loop:   p:= ret[2];
.skip
            IF p > 3 THEN ret[2]:= 3;
            Detach;
            w:= a[1];  a[1]:= a[2];  a[2]:= w;
            IF p > n THEN GO TO start;
.skip
            mp:= m[p];
            IF mp < 0 THEN
            BEGIN  swpt:=  1;  mp:= mp+1  END ELSE
            BEGIN  swpt:= mp;  mp:= mp-1  END;
.skip
            IF mp = 0 THEN
            BEGIN
                m[p]:= km[p];
                ret[p-1]:= ret[p];   ret[p]:= p+1
            END ELSE m[p]:= mp;
.skip
            Detach;
            w:= a[p];  a[p]:= a[swpt];  a[swpt]:= w;
            GO TO loop;
        END n >= 2
    END of pergen;
.f;.p -5,2,8
**** REAL PROCEDURE RANDOM(a,b); REAL a,b;
.index ^^RANDOM EXTERNAL REAL PROCEDURE
.skip
Returns an uniformly distributed value in the interval (a,b)
(c.f. FORTRAN routine random).
.p -5,2,8
**** INTEGER PROCEDURE UNIQUE
.index ^^UNIQUE EXTERNAL INTEGER PROCEDURE
.nf;.s;
UNIQUE will return increasing integer numbers.
The returned value will increase with one each jiffy
(1/50 or 1/60 second).
The returned value is a number in which  bits 1-11 contain
the day number since 1977-01-01 (mod 4096) and bits 12-35
contain time of day in jiffies.
The sequence will restart (from zero) every 4096th day
(11 years and 81 days).
.s;EXTERNAL PROCEDURE required: INTEGER PROCEDURE gettab;
.s;BEGIN
! Take daynumber after 1977-01-01, put it into bits 0-11
! and add no. of jiffies (always < 2_^23);
! 262144 = 2_^18     8388608 = 2_^23;
unique:=
##Mod(gettab(9,43)//262144-43144,4096)*8388608
##+ gettab(9,8);
END of unique;
.f;.p -5,2,8
****#INTEGER PROCEDURE nextrandom(n,u);
.index ^^NEXTRANDOM EXTERNAL PROCEDURE
.break
INTEGER n,u;
.fill
.s;Returns the N:th successor to U in the random number
sequence used by the random generator in the DECsystem-10 SIMULA
system. N may be negative. (Ref: SIMULA Newsletter Vol 5(2), may 1977)
.subtitle 5.7 SIMULA VERSIONS OF SYSTEM CLASSES
.page
5.7 SIMULA VERSIONS OF SYSTEM CLASSES
.p -5,2,8
****#ZIMSET and ZIMULATION
.index ^^ZIMSET EXTERNAL CLASS (SIMSET)
.index ^^ZIMULATION EXTERNAL CLASS (SIMULATION)
.skip
ZIMSET and ZIMULATION are two SIMULA classes which
include simple tracing facilities. They may be used for educational
as well as debugging purposes.
.skip
For complete documentation, see FOA Report C10055-M3(E5),
October 1976, distributed as ZIMULA.MAN.
.skip
A small example:
.skip
.nofill
BEGIN
    EXTERNAL PROCEDURE abort;
    EXTERNAL TEXT PROCEDURE upcase, conc, puttime,
    putfloat, today, daytime;
    EXTERNAL CLASS zimset,zimulation;
.skip
    zimulation BEGIN
.skip
	process CLASS a; Passivate;
.skip
	traceon("Trace.Log","*");
	! Start trace on TRACE.LOG;
.skip
	setparms('M',0);
	! Time format: Minutes, no decimal seconds;
	activat(NEW a,"DELAY",5,NONE);
	! ACTIVATE NEW a DELAY 5;
	activat(NEW a,"AT",8,NONE);
	! ACTIVATE NEW a AT 8;
	hold(2);
	sqslist;
	reactivat(current,"AT",10,NONE);
	! REACTIVATE Current AT 10;
	prior__:= TRUE;   activat(NEW a,"AFTER",0,NEW a);
	! ACTIVATE NEW a AFTER NEW a PRIOR;
.skip
    END zimulation
.skip
END of program
.skip
.skip
will produce the following output on TRACE.LOG:
.lm 0
.skip
*** Trace generated 1976-10-13 at 12:20:35 ***  Trace Codes: All
.skip
        00:00.00 (  2)        will be Delayed  to       00:05.00
                 (  3)        will be ACT. AT           00:08.00
                 Main Program Held       00:02.00 to    00:02.00
.skip
:---- Scheduled Processes ----
:         Evtime    Title
:       00:02.00    Main Program
:       00:05.00    (  2)
:       00:08.00    (  3)
:---- End of SQS List --------
.skip
        00:02.00 Main Program will be ACT. AT           00:10.00
                 Main Program was REACT. from           00:02.00
        00:05.00 (  2)        Passivated
        00:08.00 (  3)        Passivated
?       00:10.00 (  4)        Pass. due to ACT. AFTER Idle (  5)
.lm 5
.subtitle 6.#SWEDISH LANGUAGE TEXT HANDLING AND INPUT/OUTPUT
.paper size 55,65;.lm 5;.fill;.nojustify;.page
.index ^^SWEDISH LANGUAGE TEXT HANDLING AND INPUT/OUTPUT
.i -5;6.##SWEDISH LANGUAGE TEXT HANDLING AND INPUT/OUTPUT
.i -1    ;-----------------------------------------------
.f;.i -5;
.if notready
.s;NOTE: Some of these routines are not yet written. See the
list in chapter 0.2, which indicates which routines are
not available.
.endif notready
.p 0,1,8;The difference between English and Swedish text handling is
that the national Swedish letters
$(=AA), _#(=AE), @(=OE) (in lower case }(=aa), {(=ae), `(=oe)) are regarded as letters.
.br;In addition, underline (__) is regarded as part of an identifier (like
a digit in this context).
.skip 1
This table gives the names of Swedish procedures corresponding
to English procedure described above.
.skip
.nofill
.tab stops 15
ENGLISH	SWEDISH
.skip 1
.left margin 0
**** LETTER	BOKSTAV
.index ^^BOKSTAV EXTERNAL BOOLEAN PROCEDURE
**** LOWCASE	LITENBOKSTAV
.index ^^LITENBOKSTAV EXTERNAL TEXT PROCEDURE
**** MENU	MENY
.index ^^MENY EXTERNAL BOOLEAN PROCEDURE
**** UPCASE	STORBOKSTAV
.index ^^STORBOKSTAV EXTERNAL TEXT PROCEDURE
**** GETITEM	TAGORD
.index ^^TAGORD EXTERNAL TEXT PROCEDURE
**** INITEM	INORD
.index ^^INORD EXTERNAL TEXT PROCEDURE
.if notready
**** GETTYPE	TAGTYP
.index ^^TAGTYP EXTERNAL INTEGER PROCEDURE
.endif notready
.ts 13,21,29,37,45,53
.st 7. UTILITIES SPECIFIC TO DECSYSTEM-10
.ps 55,65;.lm 5;.f;.nj;.page
.i -5;7.##UTILITIES SPECIFIC TO DECSYSTEM-10
.i -1;----------------------------------
.p 0,2,15;The utilities in this section are intended for specialized use.
If you want to write portable programs, you should avoid them, since
special hardware or software features are explicitly used, e.g_. a 36-bit
word is assumed.
.p -5,2,15;**** INTEGER PROCEDURE absadr;
.INDEX ^^ABSADR EXTERNAL INTEGER PROCEDURE, address of a variable
.INDEX ^^Address of a variable, absolute
.INDEX ^^Unrestricted access to core, ABSADR procedure
.s;Takes a variable of any type as parameter.
Illegal parameters will give a returned value = 0.
.br;- If the variable is a SIMPLE variable (not an array) of type INTEGER,
REAL, LONG REAL, CHARACTER or BOOLEAN, the address of the first word of
the value is returned.
.br;- If it is a REF variable, a copy of the value
is returned, i e the address of the object or the value of NONE
(an illegal address).
.br;- ABSADR of a TEXT variable returns a standard byte pointer to the
character BEFORE the first character (7-bit byte) of the text value.
If t="ABC", LOADBYTE(ABSADR(t),1)=Rank('A'). See LOADBYTE, STOREBYTE, ADJPTR.
.br;- ABSADR of an ARRAY is the address of the array object.
.br;See [LH2] appendix B for the format of class instances (objects) and arrays.
This procedure is intended for highly implementation- and machine-dependent
applications. Be very careful not to cause a garbage collection between
computation of an absolute address and its use!
.p -5,2,8;**** INTEGER PROCEDURE adjptr(bp,n);
.br;INTEGER bp,n;
.INDEX ^^Character byte pointer manipulation
.INDEX ^^ADJPTR EXTERNAL INTEGER PROCEDURE (adjust byte pointer)
.INDEX ^^Byte pointer manipulation, ADJPTR procedure
.s;Adjusts the standard byte pointer BP by N bytes using the ADJBP instruction
(KL-10/20 processors only, not KA-10 or KI-10). See hardware documentation.
.p -5,2,8;**** INTEGER PROCEDURE andint(x,y);
.br;INTEGER x,y;
.INDEX ^^ANDINT procedure (bitwise AND between 36-bit words)
.INDEX ^^Bit manipulation, ANDINT procedure
.s;Performs bitwise AND function of X,Y.
Example: ANDINT(2R1010111,2R1001110)=2R1000110.
.p -5,2,8;**** CLASS atrstr;
.index ^^ATRSTR EXTERNAL CLASS, attribute file structure
.index ^^Attribute file structure, ATRSTR class
.s;ATRSTR implements a data structure and procedures which map the
structure of an attribute file for an external class or procedure.
A structure is set up by calling the load procedures of the
various component classes, taking information from an ATR file.
If the file is a library file, the modules can be found and mapped
one after the other. Subclasses of ATRSTR can be used e.g_. to
display the structure as pseudo-SIMULA code (see SIMATR).
.p -5,2,15;**** INTEGER PROCEDURE bitfield(w,firstbit,len);
.index ^^BITFIELD EXTERNAL INTEGER PROCEDURE
.index ^^Unpacking a field from a 36-bit word, BITFIELD procedure
.index ^^Extracting a field from a 36-bit word, BITFIELD procedure
.index ^^Byte handling, BITFIELD procedure
.br;INTEGER w,firstbit,len;
.s;Returns the byte of word W starting at FIRSTBIT,
(0#<=#FIRSTBIT#<=#35) of length L bits, where L=Abs(LEN).
L>=0 AND L<36 AND FIRSTBIT+L<=36 must hold.
.br;Special option: If LEN#<#0, the first bit is regarded as a sign bit and
extended.
.s;Examples: Assume w#=#8r123456#701234. Then bitfield(w,9,12)#=#8r4567, and
bitfield(w,9,-12)=8r777777#774567. The prefix 8r means octal radix.
.p -5,2,8;**** BOOLEAN PROCEDURE bitget(w,n);
.index ^^BITGET EXTERNAL INTEGER PROCEDURE
.INDEX ^^BOOLEAN data stored as bit strings
.INDEX ^^Bit manipulation, BITGET procedure
.br;INTEGER w,n;
.s;TRUE if bit 36-n in w is 1;
.p -5,2,8;**** PROCEDURE bitput(w,n,b);
.index ^^BITPUT EXTERNAL INTEGER PROCEDURE
.INDEX ^^Bit manipulation, BITPUT procedure
.br;INTEGER w,n; BOOLEAN b;
.s;Bit 36-n of w := IF b THEN 1 ELSE 0;
.p -5,2,15;**** INTEGER PROCEDURE boolfunc(f,x,y);
.index ^^BOOLFUNC EXTERNAL INTEGER PROCEDURE
.INDEX ^^Bit manipulation, BOOLFUNC procedure
.br;INTEGER f,x,y;
.s;Computes one of the 16 possible Boolean functions of two variables.
The operation is performed on corresponding bits in X and Y. The
function is defined by F (0<=F<=15, taken modulo 16 if not in range).
.nf;The following functions are defined:
F    x  0101
     y  0011
-----------------------------------
0       0000    FALSE
1       0001    x AND y
2       0010    (NOT x) AND y
3       0011    y
4       0100    x AND (NOT y)
5       0101    x XOR y
6       0110    x OR y
7       0111    x OR y
8       1000    NOT (x OR y) "NOR"
9       1001    x EQV y
10      1010    NOT x
11      1011    x IMP y  (NOT x OR y)
12      1100    x OR (NOT y)
13      1101    NOT (x OR y)
14      1110    NOT (x AND y) "NAND"
15      1111    TRUE
-----------------------------------
.f;Example: BOOLFUNC(4,5,3)=4 (actually, BOOLFUNC(n,5,3)=n always).
.f;.p -5,2,8;**** INTEGER PROCEDURE callmic(micfile,savfile);
.index ^^CALLMIC EXTERNAL INTEGER PROCEDURE
.index ^^MIC control from a SIMULA program, CALLMIC procedure
.br;VALUE micfile,savfile;   TEXT micfile,savfile;
.s;PROCEDURE CALLMIC will enable the SIMULA programmer to do
almost anything from his (her) SIMULA program.
The use of this procedure depends on the existence of
the Hatfield MIC system residing on the SYS_: area.
.s;The procedure CALLMIC is used in the following manner -
.s;The user first creates a file MIC.TMP containing ordinary DEC-10
commands like .DELETE *.BAK
.br;	.RUN ABC
.br;	.COJOB=A.MIC parm1
.br;	.DO ABCMIC
.br;etc.
.s;The call CALLMIC("MIC.TMP","SAV.TMP");
will then use MIC.TMP for a MIC run.
.br;The files MICFILE,SAVFILE will - if possible - be deleted at return.
.br;If the file name for the MIC file contains a protection code
with 1st digit equal to 2 (i.e. "MIC.TMP<277>"), then the MIC
execution will be silent.
Note, however, that CALLMIC will be unable to delete
the file afterwards.
(The message "? MACRO FILE NOT FOUND." will follow at the end of
the SIMULA program. Please ignore that message.)
Alternatively the user may start the MIC
file with: .SILENCE
.s;If the 2nd parameter =/= NOTEXT the MIC session will end by
returning to the point of CALLMIC call: CALLMIC will save
current program in file SAVFILE and end the MIC session
with .RUN "SAVFILE".
.s;Otherwise, if SAVFILE == NOTEXT, no return to the calling
program will occur.
.s;!!!!	The same restrictions as for SAVE are valid. Thus:
.br;!!!!	Only Sysin and Sysout may be open.
.br;!!!!	Sysin and Sysout must be the user's TTY.
.s;Note that you may close Outfiles before calling CALLMIC
and then open again with "file.ext/access:append".
Infiles are more difficult to handle - you may keep count
of how many lines you have read before closing and then
read past the part already read after opening again.
Directfiles give no problems here of course - just
save current Location, close and open again after
return from CALLMIC.
.s;A small user example:
.s;.nofill
!BEGIN
!    EXTERNAL PROCEDURE run;
!    EXTERNAL BOOLEAN PROCEDURE scratchfile,tmpout;
!    EXTERNAL INTEGER PROCEDURE save,callmic;
!    EXTERNAL TEXT PROCEDURE inline,conc,tmpnam;
!    INTEGER rc;
!    TEXT micfile,savfile;
.s;!    micfile:- inline("Mic file name:",Sysin);
!    IF micfile == NOTEXT THEN micfile:- Copy("Mic.tmp");
!    savfile:- inline("Sav file:",Sysin);
.s;!    Outtext("End with extra CR");
!    Outimage;
!    INSPECT NEW Outfile(micfile) DO
!    BEGIN
!	Open(Sysin.Image);
!	! Note the neat way of copying input lines
!	! from Sysin to MICFILE.;
!	WHILE inline("Command:",Sysin).Strip =/= NOTEXT DO
!	Outimage;
!	Close
!    END micfile creation;
.s;!    rc:= callmic(micfile,savfile);
!    Outtext("Return code:");
!    Outint(rc,5);
!  Outimage;
.s;!END of program
.s;EXTERNAL PROCEDURES required:
BOOLEAN PROCEDURE scratchfile;	PROCEDURE run;
INTEGER PROCEDURE save;	TEXT PROCEDURE tmpnam,conc,tmpout;
.s 2
IF micfile =/= NOTEXT THEN
BEGIN   INTEGER returncode;   TEXT cmdfile;
.s;    tmpout("MIC",conc("/",micfile));
.s;    IF savfile =/= NOTEXT THEN
    BEGIN
	INSPECT
	NEW Outfile(conc(micfile,"/ACCESS:APPEND")) DO
	BEGIN   Open(Blanks(40));
	    Outtext(".REVIVE .RUN ");
	    Outtext(savfile);   Close
	END add sav file name;
	returncode:= save(savfile,TRUE);
	IF returncode = 0 THEN
	run("SYS:MIC",2) ELSE
	IF returncode < 0 THEN
	BEGIN   Outtext("? Save failed with filename:");
	    Outtext(savfile);   Outimage
	END ELSE
	scratchfile(savfile);
    END savfile =/= notext ELSE run("SYS:MIC",2);
.s;    scratchfile(micfile);
    scratchfile(tmpnam("MIC"));
    scratchfile(cmdfile);
    stop:   callmic:= returncode;
END of callmic;
.p -5,2,10;.nf;**** TEXT PROCEDURE checkextension(t,defaultextension);
.index ^^CHECKEXTENSION EXTERNAL TEXT PROCEDURE
VALUE defaultextension;   TEXT t,defaultextension;
.f;.s;CHECKEXTENSION may be used to add a default extension
to file specifications not containing a dot ('.').
I.e.
.nf;! T:- Copy("A");!   T:- checkextension(T,".SIM");
! will give T the value "A.SIM", while
! T:- Copy("A.");!   T:- checkextension(T,".SIM");
! will leave T unaltered.
! T:- Copy("LPT:");!   T:- checkextension(T,".SIM");
! will leave T unaltered.
! T:- Copy("LPT: A");!   T:- checkextension(T,".SIM");
! will give T the value "LPT: A.SIM".
_;
.br;EXTERNAL PROCEDURES required:
.br;CHARACTER PROCEDURE findtrigger;
.br;TEXT PROCEDURE conc,rest;
.s;IF t =/= NOTEXT THEN
BEGIN   t.Setpos(1);
	IF findtrigger(t,Copy(":")) NE ':' OR
	rest(t).Strip =/= NOTEXT THEN
	BEGIN   t.Setpos(1);
	    IF findtrigger(t,Copy(".")) NE '.' THEN
	    t:- conc(t,defaultextension) ELSE t.Setpos(1);
	END;
	checkextension:- t
END of checkextension;
.f
.p -5,2,15;**** INTEGER PROCEDURE depbyte(val,w,firstbit,len);
.index ^^DEPBYTE EXTERNAL PROCEDURE
.index ^^Byte handling, DEPBYTE procedure
.index ^^Bit manipulation, DEPBYTE procededure
.index ^^Change partial word, DEPBYTE procedure
.br;INTEGER val,w,firstbit,len;
.s;Returns the value of W with the modification:
.br;The byte starting at FIRSTBIT (0-35) of length LEN bits is replaced
by VAL.
LEN>=0 AND LEN<=36 AND FIRSTBIT+LEN<=36 must hold.
Note: The last LEN bits of VAL will be used, the other bits will be
ignored.
.f;.p -5,2,8;**** CLASS dirhnd
.index ^^DIRHND EXTERNAL CLASS
.index ^^UFD-file handling
.index ^^SFD-file handling
.INDEX ^^TOPS-10 directory file handling, DIRHND class
.index ^^File directory handling, DIRHND class
.s;DIRHND contains data structures which can be loaded with information
from TOPS-10 directory files (UFD and SFD files). The procedure
LOAD_SELECTED_FILENAMES can be used to read this information, selecting
certain file names according to a wild card pattern (see MATCH6, WILDSIX).
LOAD_SELECTED_FILENAMES is an attribute of CLASS DIRECTORY_PATH,
which is declared inside DIRHND and contains information defining the
directory file.
The directory information is placed in objects of class DIRECTORY_BLOCK,
which are reached via objects of FILENAMELIST class
SIXBIT_FILENAMELIST.
DIRHND is only rudimentary at present and CANNOT BE USED on
DECsystem-20 (TOPS-20).
.p -5,2,15;**** PROCEDURE echo(fileref,mode); REF(Infile)fileref; INTEGER mode;
.index ^^ECHO EXTERNAL PROCEDURE
.index ^^Character input, echo control of
.index ^^Input of characters from terminal, control of echoing
.index ^^Terminal character input, control of echoing
.s;Provided fileref refers to a TTY file, different values of mode have the
following effects:
.br;mode=0 resets the mode to normal.
.br;mode=1 sets special editor mode.
.br;mode=2 suppresses echoing on the terminal completely.
.br;mode=4 causes all characters to echo exactly as typed.
.br;Combinations are possible where meaningful, i e 5=4+1.
.br;No effect on other files.
.p -5,2,15;**** INTEGER PROCEDURE filcopy(source,dest);
.index ^^FILCOPY EXTERNAL INTEGER PROCEDURE
.index ^^Disk-to-disk copy, FILCOPY procedure
.index ^^Copying of disk files, FILCOPY procedure
.br;REF(Infile)source;  TEXT dest;
.s;Copies the SOURCE file to the (new) file specified by the
text DEST, which is a normal DECsystem-10 (or -20) file specification
acceptable to the SIMULA run time system.
A NEW Outfile(dest) is created, and the contents of source are copied
to the new file buffer by buffer (using TOPS-10 I/O, thus the PA1050
compatibility must be used under TOPS-20).
.br;!!! ONLY DISK FILES are handled !!!
.br;FILCOPY copies the file without changing the creation date as
ordinary SIMULA code would do, and does it rather efficiently
without using Image. The disk space allocation is taken from the
source file lookup data, minimizing fragmentation.
If a long file is copied, it may be useful to allocate more than 2 standard
buffers for each file (/BUFFERS switch).
.s;FILCOPY returns -1 on success, 0 otherwise (or 2 if one of the files
is not a disk file).
.p -5,2,15;**** INTEGER PROCEDURE flokup(f);
.index ^^FLOKUP EXTERNAL INTEGER PROCEDURE
.index ^^File lookup, FLOKUP procedure
.br;INTEGER f;
.S;F contains the address of a control block suitable for the FILOP_.
UUO (See Monitor Calls). The .FOLEB field must contain a pointer to
a lookup block (ordinary 4-word block or an extended lookup block).
FLOKUP looks up the file given by the lookup block and also determines
the exact path of the file (placed in the PATH_. block pointed to by
the .FOPAT field).
On entry, the FILOP_. block must contain i/o channel number in
_.FOFNC(F), SIXBIT device name in .FODEV(F), i/o mode in .FOIOS(F),
addresses of PATH_. and lookup blocks in .FOPAT(F), .FOLEB(F).
The lookup block must contain information (path, filename and extension
in sixbit) for finding the file.
If the file can be found, the value of FLOKUP=F and the various blocks
are updated, otherwise the value FLOKUP=0 is returned.
.br;WARNING: FLOKUP should only be used in special cases when the
ordinary SIMULA i/o procedures are inadequate.
.p -5,2,15;**** TEXT PROCEDURE filspc(fileref,format);
.index ^^FILSPC EXTERNAL TEXT PROCEDURE
.index ^^File specification string, FILSPC procedure
.br;REF(FILE)fileref; INTEGER format;
.s;Returns a string specifying a file:
.br;in TOPS-10: dev:file.ext[path]<prot>
.br;in TOPS-20: str:<directory>file.ext;Pnnnnnn
.br;FORMAT is an integer which specifies the fields to be included in the resulting
string. FORMAT is basically treated as a packed integer array,
where most elements are 3 bits wide.
Each 3-bit integer controls one field of the output string.
The value of a controlling integer can be:
.br;0: Suppress the field. 1: Always output the field.
.br;2: Suppress the field if it is the system default.
.br;The following octal values would be used to always output the corresponding
fields:
.nf;
8R 100000 000000 (2_^33) Output DEVICE (File structure)
8R 010000 000000 (2_^30) Directory name in TOPS-20, ppn (+SFD) path in TOPS-10
8R 001000 000000 (2_^27) File name (value=2 illegal)
8R 000100 000000 (2_^24) File type (extension) (value=2 illegal)
8R 000010 000000 (2_^21) File generation number (not implemented)
8R 000001 000000 (2_^18) Protection
8R 000000 040000 (2_^14, one bit) Temporary file (only in TOPS-20)
The remaining field control bits used are:
.f;
8R 000000 000001 (2_^0) Punctuate All Fields, e g DEV:NAME.EXT[p,pn,sfd1,sfd2]
The format is adapted from the control word for the JFNS JSYS in TOPS-20
(see the Monitor Calls manual for TOPS-20) to make it easy to modify when
and if full TOPS-20 support will be included in the SIMULA system.
FORMAT=0 or omitted is equivalent to 8R#221110#000001 -
.br;#	dev:name.ext[proj,prog,sfd1,...] (TOPS-10)
.br;#	dev:<directory>name.typ.gen;T	 (TOPS-20)
.br;with dev: omitted if it is DSK, <directory> omitted if it is the connected
directory,  [proj,...] omitted if it is the default path.
.br;Requires the external module FILEST (entry .FILST).
.p -5,2,15;****#INTEGER PROCEDURE gettab(table,index);
.br;INTEGER table,index;
.index ^^ GETTAB EXTERNAL PROCEDURE
.index ^^Monitor tables, GETTAB procedure
.br;Executes GETTAB ac, where ac is [index,,table]. See Monitor Calls Manual.
.p -5,2,15;**** TEXT PROCEDURE idrx50(w); INTEGER w;
.index ^^IDRX50 EXTERNAL TEXT PROCEDURE
.index ^^RADIX50 to ASCII conversion, IDRX50 procedure
.index ^^Conversion from RADIX50 to ASCII, IDRX50 procedure
.s;Converts bits 4-35 of W to a RADIX50 identifier text (Length=6).
Bits 0-3 are
.br;1) stored in idrx50.Main.Sub(1,1) directly,
.br;2) Converted to octal (after appending 2 zero bits to the right) in
idrx50.Main.Sub(2,3), where the last char is blank.
.br;The following relation holds:
.br;	idrx50.Main.Sub(5,6) == idrx50.
.br;Example: Octal 123456701234 is converted to "?10 OQ5H%3",
where ? stands for Char(8r10//4) = Char(2) (=_^B).
.p -5,2,15;****#TEXT PROCEDURE idsixbit(id6a,id6b);
.br;INTEGER id6a,id6b;
.index ^^Character format transformation from ASCII to SIXBIT
.index ^^Text transformation from ASCII to SIXBIT
.index ^^IDSIXBIT EXTERNAL TEXT PROCEDURE
.index ^^SIXBIT to ASCII conversion, IDSIXBIT procedure
.index ^^Conversion from SIXBIT to ASCII, IDSIXBIT procedure
.s;Converts the two words id6a,id6b to a 12-character text (ASCII).
The result is Strip of this identifier.
If only 6 or fewer characters are relevant, use zero as second parameter.
.p -5,2,15;**** INTEGER PROCEDURE intrea(x); REAL x;
.index ^^REAL to INTEGER conversion, INTREA procedure
.index ^^INTREA EXTERNAL PROCEDURE
.index ^^Type conversion, INTREA procedure
.index ^^Bit manipulation, INTREA procedure
.s;Provides type conversion REAL to INTEGER.
The real x is interpreted as an integer quantity with the same bit
pattern. Use with care - highly machine dependent!
.p -5,2,15;**** INTEGER PROCEDURE jobstatus(f);
.index ^^JOBSTATUS EXTERNAL INTEGER PROCEDURE
.index ^^Job control, JOBSTATUS procedure
.index ^^Subjob control, JOBSTATUS procedure
.index ^^PTY handling, JOBSTATUS procedure
.br;REF(Infile)f;
.s;Returns the job status for a TTY or PTY associated with the file object F.
See PTYCHECK for interpretation of the value returned.
.p -5,2,15;**** INTEGER PROCEDURE loadbyte(bp,incr);
.index ^^LOADBYTE EXTERNAL INTEGER PROCEDURE
.INDEX ^^Byte manipulation, LOADBYTE procedure
.index ^^Unchecked memory access, LOADBYTE procedure
.index ^^Bit manipulation, LOADBYTE
.index ^^Memory access without SIMULA checks, LOADBYTE
.index ^^Access to memory without checking, LOADBYTE
.br;INTEGER bp,incr;
.s;Load a byte via the standard byte pointer BP, modified INCR bytes.
If INCR < 0 or INCR > 1, the ADJBP instruction, which is not implemented
on KA-10 or KI-10 processors, is used.
Example: If t:-Copy("ABCDEFGH"), LOADBYTE(ABSADR(t),5) = Rank('F').
LOADBYTE(8R222215#000001,0) gives the address of the prototype of the current
"main" block, i.e_. the prefixed block, class object, procedure instance or
unreduced block which is innermost in the operating chain.
The byte pointer is POINT 18,1(15),18.
.br;**** WARNING: To be used with caution. Highly machine- and implementation dependent.
See STOREBYTE, STOREWORD.
.p -5,2,15;**** INTEGER PROCEDURE loadword(adr);
.index ^^LOADWORD EXTERNAL INTEGER PROCEDURE
.index ^^Unchecked memory access, LOADWORD
.index ^^Memory access without SIMULA checks, LOADWORD
.index ^^Access to memory without checking, LOADWORD
.br;INTEGER adr;
.s;Returns the 36-bit word at address ADR, if valid, otherwise gives
"Illegal memory reference" (possibly "Object NONE").
.br;**** WARNING: To be used with caution. Highly machine- and implementation dependent.
See STOREWORD.
.f;.p -5,2,8;**** INTEGER PROCEDURE match6(id1,id2,mask);
.br;INTEGER id1,id2,mask;
.index ^^MATCH6 EXTERNAL INTEGER PROCEDURE
.index ^^SIXBIT match with "wildcards", MATCH6 procedure
.index ^^Wild card match, MATCH6 procedure
.s;ID1 (without wild card characters '?' or '*') is tested against ID2
with MASK showing wild card positions in ID2 if any.
The result is 1 for an exact match, -1 for a wildcard match,
0 for no match. ID1 and ID2 are in SIXBIT code.
The wildcard character '?' matches any character. '*' is equivalent
to 6 or less '?' characters: "*" => "??????", "AB*" => "AB????".
The wildcard MASK has octal 77 for each '?' in ID2, zeros
in the other positions. See WILDSIX.
.f;.p -5,2,8;**** BOOLEAN PROCEDURE numbered
.index ^^NUMBERED EXTERNAL BOOLEAN PROCEDURE
.index ^^Line-numbered file, input of
.index ^^Number on input line
.s;The BOOLEAN PROCEDURE numbered should always be called immediately
after inimage. It will return TRUE if the last input line was numbered.
The internal flag will be reset by numbered and may be
changed by each inimage, even on other files. For output of line-numbered
files, see the information in
the DECsystem-10 SIMULA Language Handbook part II about
the file creation switch /NUMBERED.
.p -5,2,15;**** TEXT PROCEDURE octal(t,n);
.index ^^OCTAL EXTERNAL TEXT PROCEDURE
.INDEX ^^Conversion from binary to octal, OCTAL procedure
.index ^^Binary to octal conversion, OCTAL procedure
.br;TEXT t; INTEGER n;
.s;Returns an octal representation (digits 0-7) of the bit pattern in N.
T is used as workspace. If T.Length < 12, only the low-order part of
N is converted (truncated to the left). OCTAL.Length = Min(12,T.Length).
OCTAL.Main == T.Main. OCTAL.Pos points to the first non-zero digit.
Example: t:-Blanks(10); OCTAL(t,-345)="7777777247";
OCTAL(345)="0000000531", Pos=8, thus REST(OCTAL(...))="531".
.p 0,2,15;CONTROLLING SUBJOBS (PTY HANDLING)
.index ^^Job control
.index ^^Subjob control
.index ^^PTY handling
.p 0,1,5;Sometimes it is useful to be able to control a subjob from a SIMULA
program. The subjob can do some tasks in parallel with the controlling job or
perform some services which could not be handled by the controlling job
without interrupting it, perhaps with loss of data and time.
A subjob is controlled by means of a PTY (pseudo-teletype), which is implemented
by monitor software to act as controlling terminal for the subjob. A PTY is
handled like a terminal using buffered i/o. The following procedures are coded
to aid handling of PTY's in a SIMULA program:
.br;- PTYFIL defines an Outfile object to be used for sending commands to the
subjob. The output from the subjob goes to the Infile object which is a parameter
to PTYFIL.
.br;- PTYINIMAGE is used to get the output from the subjob. The ordinary Inimage
procedure for Infiles cannot be used because it would loop when there is no
input available, or when the job output does not end with a break character.
.br;- PTYCHECK can be used to wait until the subjob becomes interactive,
i.e_. has output available or can accept input.
.br;- JOBSTATUS can be used to check the status of the subjob without waiting.
.br;- INPUTWAIT can be used to wait for activity on PTY's as well as TTY's.
.br;- Actions to control a subjob:
.br;1) Creation of a NEW Infile("PTY:xxx") (specific PTY if desired).
.br;2) ptyout:-PTYFIL(ptyin), where ptyin is the Infile above.
.br;3) ptyin.Open(Blanks(Sysin.Length)) for example.
ptyout.Open(Blanks(Sysout.Length)).
.br;4) Ordinary Outfile operations (Outchar, Outtext, Outimage, Breakoutimage)
are used for sending commands to the subjob. Note that no password is required
if you LOGIN on the same ppn as the main job.
Check if the job can accept commands (JOBSTATUS, PTYCHECK, INPUTWAIT) before
sending any.
.br;5) Check for job output by PTYCHECK, JOBSTATUS, INPUTWAIT and use
PTYINIMAGE to read the output.
.br;6) Before closing the two PTY files, log out the job, otherwise it will
become detached when the channel is RELEASEd. The ordinary SIMULA Close procedure
has been modified to work with PTY.
.br;****WARNING**** PTY handling has not been extensively checked. Proper
operation is not guaranteed!
See Monitor Calls for details of PTY handling. Additional functions may be
implemented by the XCALLI procedure, see below.
.p -5,2,15;**** INTEGER PROCEDURE ptycheck(ptyin,timelimit);
.index ^^PTYCHECK EXTERNAL INTEGER PROCEDURE
.index ^^Job control, PTYCHECK procedure
.index ^^Subjob control, PTYCHECK procedure
.index ^^PTY handling, PTYCHECK procedure
.br;REF(Infile)ptyin; REAL timelimit;
.s;Returns job status (according to JOBSTS UUO) if PTY can accept input
or has output within the time limit, otherwise zero.
.nf;Interpretation of returned value:
JB.UJA	8R400000 000000	(negative) Job number is assigned.
JB.ULI	8R200000 000000 Job is logged in.
JB.UML	8R100000 000000 TTY is at monitor level.
JB.UOA	8R040000 000000	TTY output is available.
JB.UDI	8R020000 000000	TTY at user level in input wait,
			or at monitor level and can
			accept a command.
JB.UJC	8R010000 000000 JACCT is set. In particular,
			_^C_^C will not work.
JB.UJN	8R000000 777777	Job number or zero.
If 0<timelimit<0.001, ptycheck does not wait. If timelimit <=0, it waits
indefinitely.
.f;
.p -5,2,8;**** REF(Outfile) PROCEDURE ptyfil(ptyinf);
.index ^^PTYFIL EXTERNAL INTEGER PROCEDURE
.index ^^Job control, PTYFIL procedure
.index ^^Subjob control, PTYFIL procedure
.index ^^PTY handling, PTYFIL procedure
.br;REF(Infile)ptyinf;
.s;Provided PTYINF is an Infile on device PTY,
an Outfile will be opened on the same channel (the same PTY).
The result of PTYFIL is a reference to that Outfile object.
.p -5,2,15;**** INTEGER PROCEDURE ptyinimage(ptyin);
.index ^^PTYINIMAGE EXTERNAL INTEGER PROCEDURE
.index ^^Job control, PTYINIMAGE procedure
.index ^^Subjob control, PTYINIMAGE procedure
.index ^^PTY handling, PTYINIMAGE procedure
.br;REF(Infile) ptyin;
.s;Performs Inimage for a PTY Infile. Does not need a break character to
stop input. The result is the break character combination:
7 (_^G, BELL), 10 (LF), 11 (VT), 12 (FF), 13 (CR without following LF),
26 (^Z), 27 (ESC).
CRLF is two characters = 128*13+10=1674.
Special codes:
.nf;0 - No break character (null found),
-1 for an empty buffer (no input available),
-2 for no more space in Image, without having found break character
-3 for other error (to be elaborated?).
.s;The file must be open and be associated with a pseudo-tty.
NOTE!  Image must be an initial subtext of Image.Main, i.e.
  Image.Main.Sub(1,Image.Length) == Image.
PTYINIMAGE sets Image=Image.Strip, except if Image.Strip==NOTEXT.
In that case Image = " " and Image.Pos=2.
.f
.f;.p -5,2,10;****#INTEGER PROCEDURE rename(fs1,fs2,force);
.br;NAME fs1,fs2,force;
BOOLEAN force;
TEXT or REF(FILE) fs1;
TEXT fs2;
.index ^^RENAME EXTERNAL INTEGER PROCEDURE
.index ^^Renaming a file, RENAME procedure
.index ^^Deleting a file, RENAME procedure
.index ^^Scratching a file, RENAME procedure
.index ^^File renaming or deletion, RENAME procedure
.s;FS1 is either a file specification text or a reference to a file object.
FS2 is a (partial) file specification. Missing fields are taken from FS1.
Information from FS2 is substituted in FS1 and a RENAME UUO is executed.
If FS2==NOTEXT, the file defined by FS1 is deleted.
If FORCE==TRUE, a RENAME changing only the protection is tried first, then
a full RENAME.
The result is -1 if RENAME worked, error code if not.
Common error codes:
.nf;
ERFNF% 0	File not found (refers to first file)
ERIPP% 1	Illegal path (ppn or full sfd path)
ERPRT% 2	Protection failure
ERAEF% 4	Already existing filename
.s;Special error codes:
notdsk 1000	FS1 device is not disk
reoper 1001	Could not reopen FS1
fs2err 1002	Error in FS2
deverr 1003	Cannot change device (FS2 dev not same as FS1)
.s;.f;Other error codes are listed in the DECsystem-10 Monitor Calls manual.
.p -5,2,15;**** INTEGER PROCEDURE rdx50(id,code);
.index ^^RDX50 EXTERNAL PROCEDURE
.INDEX ^^Radix50 conversion, RDX50 procedure
.index ^^REL file information, RDX50 procedure
.br;TEXT id; INTEGER code;
.s;COMMENT
.br;Converts id to "RADIX50" code. At most 6 characters allowed.
Only letters (treated as upper case), digits and " .$%" allowed.
CODE must be 0 or > 3 and <= 8R74.
.s;EXTERNAL procedures required:
.br;INTEGER PROCEDURE absadr, storebyte;
.br;INTEGER PROCEDURE bitfield;
_;
.p 0,1,25;.lt 24
TEXT t;  INTEGER i,j;  CHARACTER c;
t:- IF id.Length > 6 THEN id.Sub(1,6) ELSE id;
WHILE t.More DO
BEGIN
    c:= t.Getchar; i:= i * 8R50;
    IF Letter(c) THEN
    BEGIN i:= i + Rank(c) - 8R66;
	IF c >= 'a' THEN i:= i - 8R40;
    END ELSE
    IF Digit (c) THEN i:= i + Rank(c) - 8R57 ELSE
    IF c = '.' THEN i:= i + 8R45 ELSE
    IF c = '$' THEN i:= i + 8R46 ELSE
    IF c = '%' THEN i:= i + 8R47 ELSE
    IF NOT c = ' ' THEN GOTO out;
END;
FOR j:= t.Length - 5 STEP 1 UNTIL 0 DO i:= i * 8R50;
IF NOT code = 0 THEN
BEGIN
    code:= bitfield(code,30,4);
    storebyte(code,8R400400000000 + absadr(i),0);
END;
rdx50:= i;
out:
END rdx50;
.el
.p -5,2,15;**** INTEGER PROCEDURE reaint(x); REAL x;
.index ^^INTEGER to REAL conversion, REAINT procedure
.index ^^REAINT EXTERNAL PROCEDURE
.index ^^Type conversion, REAINT procedure
.index ^^Bit manipulation, REAINT procedure
.s;Provides type conversion INTEGER to REAL.
The integer x is interpreted as an real quantity with the same bit
pattern. Use with care - highly machine dependent!
.p -5,2,10;****#BOOLEAN PROCEDURE rescan;
.index ^^RESCAN EXTERNAL BOOLEAN PROCEDURE
.index ^^Command input to SIMULA programs, RESCAN procedure
.br;A SIMULA program is normally started by some monitor command.
RESCAN backs up the TTY input buffer, if possible, so that the invoking
command can be reread.
If the command line can be reread, RESCAN returns TRUE, else FALSE.
The next input (of a line or a character) from the controlling TTY
(normally SYSIN) will return the command line which started the SIMULA
program, e g:
.br;	RUN prog-<parameters>
.br;The monitor command scanner allows command lines which contain extra
information not expected by the monitor itself. The extra information should be
preceded by a character which is not in the command syntax, like '-', '('.
.s;RESCAN must be called BEFORE the first input from the terminal.
If RESCAN is to be used, file specifications cannot be taken from the terminal.
Any error dialogue before RESCAN is called will render it useless.
Also, you cannot expect RESCAN to work if you start the program directly
after loading by an EXECUTE or DEBUG command.
If you do not have the program in executable form, you should use
LOAD, then START <some info>.
Programs using RESCAN should always provide an alternative way of getting the
information.
.br;Example (from SIMED):
.nf;
EXTERNAL BOOLEAN PROCEDURE rescan;
EXTERNAL TEXT PROCEDURE scanto,rest,inline;
TEXT initcommand,t;
IF rescan THEN
BEGIN Inimage;
#  t:-Sysin.Image.Strip;
#  IF t=/=NOTEXT THEN t:-Copy(t);
#  scanto(t,'-'); ! t.Pos after '-' or at end of command line;
#  initcommand:- rest(t);
END scanning command line;
#...
TEXT command;
command:- IF initcommand =/= NOTEXT THEN initcommand
#         ELSE inline("*",Sysin);
#...
The command R SIMED-X.SIM[100,101]
will yield initcommand = "X.SIM[100,101]", and
just R SIMED will yield initcommand == NOTEXT, causing a
prompting "*" to be output to show that a command is expected.
.p -5,2,5;****#SIMATR PROGRAM
.f;.s;Displays ATR file information. This improved version is written
.index ^^Structure of a SIMULA program, output of
.index ^^SIMATR program for displaying attribute files
.index ^^ATR file structure, SIMATR program
.index ^^Attribute file structure, display by SIMATR program
in SIMULA. It displays
the SIMULA skeleton of the separately compiled module together with
unique entry names (also for other required external modules).
The external classes DIRHND and ATRSTR are required to load SIMATR,
a well as a number of external (LIBSIM) procedures.
.p -5,2,15;**** INTEGER PROCEDURE sixbit(t);
.index ^^SIXBIT EXTERNAL INTEGER PROCEDURE
.index ^^Conversion from ASCII to SIXBIT, SIXBIT procedure
.index ^^ASCII to SIXBIT conversion, SIXBIT procedure
.br;TEXT t;
.s;Converts at most 6 characters from the ASCII text T to SIXBIT, i.e_.
the code used in the TOPS-10 monitor for names of devices, files, commands.
Each character in SIXBIT is 6 bits, thus only 64 different characters can be
represented, half as many as in ASCII. Lowercase letters are treated as upper
case, and control characters (Char(0) - Char(31)) cannot be represented.
SIXBIT translates the first 6 characters of T to sixbit code by subtracting
32 from each character value < 96 and 64 from the others. Negative values are
made zero (space in sixbit code). The result is an integer, left justified,
which could be used as a sixbit quantity e.g_. with some XCALLI functions.
The inverse function is IDSIXBIT, q.v_.
See also OCTAL for a way of representing bit patterns as text strings.
.f;.p -5,2,8;**** INTEGER PROCEDURE sxrx50(w); INTEGER w;
.index ^^SXRX50 EXTERNAL INTEGER PROCEDURE
.index ^^RADIX50 to SIXBIT code, SXRX50 procedure
.index ^^SIXBIT from RADIX50, SXRX50 procedure
.s;Converts bits 4-35 of W to a RADIX50 identifier expressed
in SIXBIT code (Length=6).
Example: Octal 123456701234 is converted to SIXBIT "OQ5H%3".
Bits 0-3 are ignored.
.f;.p -5,2,10;****INTEGER PROCEDURE storebyte(b,bp,incr);
.index ^^STOREBYTE EXTERNAL INTEGER PROCEDURE
.index ^^Byte handling, STOREBYTE
.index ^^Unchecked memory access, STOREBYTE
.index ^^Bit manipulation, STOREBYTE
.index ^^Memory access without SIMULA checks, STOREBYTE
.index ^^Access to memory without checking, STOREBYTE
.br;INTEGER b,bp,incr;
.s;Using the byte pointer BP (careful if index and indirection fields are not
zero) store the byte B (last bits according to byte size) by a DPB or IDPB
instruction. If INCR=0 use DPB, if =1 use IDPB,
otherwise modify by ADJBP (only possible on KL-10/20 systems).
See LOADBYTE.
.p -5,2,10;****INTEGER PROCEDURE storeword(w,adr);
.index ^^STOREWORD EXTERNAL INTEGER PROCEDURE
.index ^^Unchecked memory access, STOREWORD
.index ^^Memory access without SIMULA checks, STOREWORD
.index ^^Access to memory without checking, STOREWORD
.br;INTEGER w,adr;
.s;Stores the 36-bit word W at address (ADR) in core.
For convenience, the result of the function is the stored value.
Note that indirect addressing is used, which means that the effective address
is modified by any index register specified in bits 14-17 and indirection will
be used if bit 13 is 1. This is dangerous since you cannot control the
contents of ac's in general.
Use this procedure ONLY if you know EXACTLY what you are doing!
LOADWORD is the complement of STOREWORD.
.p -5,2,10;****#TEXT PROCEDURE tmpin(nam,delete);
.br;VALUE nam; TEXT nam; BOOLEAN delete;
.index ^^TMPCOR input, TMPIN procedure
.index ^^TMPIN EXTERNAL TEXT PROCEDURE
.index ^^Intra-job communication, TMPIN procedure
.index ^^Communication between programs, TMPIN procedure
.index ^^Receiving information from another program, TMPIN procedure
.index ^^Getting information from another program, TMPIN procedure
.br;Uses the TMPCOR UUO to read the core file NAM into a new text object.
If a core file is not found, a file with name "TMPNAM(NAM)" (see below)
is tried instead (read in dump mode if found).
.br;If DELETE is TRUE, the file is deleted after reading.
.br;Returns NOTEXT if the file was not found, Blanks(1) if found but empty.
.br;In the latter case Pos=2 also, otherwise 1.
Information to be read by TMPIN may be created using TMPOUT (see below).
.p -5,2,12;**** TEXT PROCEDURE tmpnam(nam);
.br;VALUE nam; TEXT nam;
.index ^^TMPNAM EXTERNAL TEXT PROCEDURE
.s;TMPNAM takes one parameter NAM. The parameter may
be a text constant, variable or expression
whose first three characters (or fewer than 3 if NAM.Length is
less) are used when forming a temporary file name which is the value of TMPNAM.
The name has the form "jjjnam.TMP", where jjj is the current job number in
decimal notation, and nam are the first three or fewer characters of the parameter.
.s;File names of this form are used for command files to
standard CUSP's, such as SIMULA, PIP, LINK-10 and should also be useful
for internal scratch files in a SIMULA program. See the RUN procedure for
examples.
.f.p -5,2,10;****#BOOLEAN PROCEDURE tmpout(nam,txt);
.br;NAME nam; TEXT nam,txt;
.index ^^TMPCOR output, TMPOUT procedure
.index ^^TMPOUT EXTERNAL BOOLEAN PROCEDURE
.index ^^Intra-job communication, TMPOUT procedure
.index ^^Communication between programs, TMPOUT procedure
.index ^^Sending information to another program, TMPOUT procedure
.br;Uses the TMPCOR UUO to write the core file NAM from TXT.
If TMPCOR fails, a real file named "TMPNAM(NAM)" (see TMPNAM procedure) is
opened instead, and TXT is written in dump mode.
.br;Returns FALSE if the file could not be written, TRUE on success.
No carriage return-line feed will be supplied - must be in TXT if needed.
The text should start and end on a word boundary.
.p -5,2,15;**** INTEGER PROCEDURE trmop(funcod, iox, val);
.index ^^TRMOP EXTERNAL INTEGER PROCEDURE
.index ^^Terminal communication, TRMOP procedure
.index ^^TTY (.SET TTY) performed from a SIMULA program
.index ^^SET TTY performed from a SIMULA program
.index ^^TAB TTY bit setting from a SIMULA program
.index ^^ECHO TTY bit setting from a SIMULA program
.index ^^CRLF TTY bit setting from a SIMULA program
.index ^^ALTMODE TTY bit setting from a SIMULA program
.index ^^NO (FORM, CRLF, GAG, TAB etc.) TTY bit setting
.index ^^GAG TTY bit setting from a SIMULA program
.index ^^FILL TTY bit setting from a SIMULA program
.index ^^FORM TTY bit setting from a SIMULA program
.br;INTEGER funcod, val; REF (Outfile) iox;
.s;TRMOP allows the SIMULA program to test and change the
values of certain status items associated with a terminal connected
to the SIMULA program via a file object.
The program can thus achieve the equivalents of the
monitor commands .TTY NO ECHO, .TTY LC etc.
.p 0,1,5;FUNCOD is the four-digit octal code for the function to be performed.
.s;A first digit = 0 signifies a special function (usually a generalization of
the TTCALL UUO for the job-controlling terminal).
.s;If the first digit is 1, a read function is performed, i.#e_. the current
value of the field is returned as function value.
.s;If the first digit is 2, the corresponding value is set to the value given
by VAL, and the old value is returned as function value.
.s;The effect of other values of the first digit is installation dependent.
.s;If the requested function cannot be performed, the value of the TRMOP
function is -1.
.s;IOX is an outfile referring to the TTY involved.
IOX==NONE refers to the terminal controlling the job.
.s;VAL is the new value for the status item.
Redundant except for set function (FUNCOD=8R2xxx).
.s;TRMOP returns the old value of the status item when relevant.
.s;Special case: for FUNCOD = 1 or 2, a skip return is mapped as the function
value 1, non-skip return as 0.
.p 0,1,5
Example I: "TRMOP(8R1003,sysout,0)" returns 1 if the previous
setting was "TTY NO LC", returns 0 if the previous setting was
"TTY LC". (TTY NO LC means that the monitor converts all lower
case letters to upper case in transmissions from the conversational
terminal.)
.p 0,1,5
Example II: "TRMOP(8R2003,sysout,1)" is equivalent to
the monitor command "TTY NO LC".
.p 0,1,5
All the status items which can be interrogated or set by TRMOP are listed in
the DECsystem-10 Software Notebooks, "DECsystem-10 monitor
calls", (DEC-10-OMCMA-B-D), Section 11.2.4.
Here is an excerpt of the most useful items:
.p 0,1,5
.tab stops 13
.nofill
FUNCOD	value
8R1003	1 = NO LC (lower case)
8R1005	0 = NO TAB (tabs converted to multiple spaces)
8R1006	0 = NO FORM
8R1007	1 = NO ECHO (printable characters not echoed)
8R1010	1 = NO CRLF (monitor inserts no extra CR-LFs)
8R1011	Horizontal position of carriage
8R1012	Carriage width (TTY WIDTH) = Create <CR><LF> at given
        position in line
8R1013	1 = NO GAG (accepts external messages)
8R1017	TTY FILL (filler class index, governs number of fill
########chars after FF and CR)
8R1024	Number of lines output on this page
8R1026	0 = ASCII codes 175 and 176 converted to altmode
8R1035  Create <CR><LF> at first space after given position
        in line
.f
.nf
.p -5,2,15;**** INTEGER PROCEDURE ttyline(ttyn); TEXT ttyn;
.index ^^TTYLINE external procedure
.index ^^TTY line number in DEC-10 network, TTYLINE procedure
.index ^^Network, TTYLINE procedure
! Required external procedures: ;
EXTERNAL INTEGER PROCEDURE xcalli, sixbit;
EXTERNAL TEXT PROCEDURE scanto, idsixbit;
BEGIN
! Accepts tty name or number (octal format).
! Returns node*2^18+line if network is in effect,
! just line no if not, or zero on error.
;

CHARACTER c;
TEXT t;
INTEGER sixname, n;

t:- ttyn;
IF t =/= NOTEXT THEN
BEGIN c:= t.Getchar;
    IF Letter(c) THEN
    BEGIN
	sixname:= sixbit(t);
	sixname:= xcalli(8R64,sixname,TRUE,0);	! DEVNAM;
	t:- idsixbit(sixname,0);
	IF t.Sub(1,3) NE "TTY" THEN GOTO error;
	ttyn:- t.Strip;
    END letter ELSE
    IF Digit(c) THEN
    BEGIN ttyn:- Copy("TTY   "); ttyn.Setpos(4);
	GOTO pc;
	WHILE t.More AND ttyn.More DO
	BEGIN 
	    c:= t.Getchar;
	pc: ttyn.Putchar(c);
	END;
    END digit;
    ttyn.Setpos(1);
    ttyline:= xcalli(8R165,sixbit(ttyn),TRUE,0);	! GTNTN.;
END;
error:
;
END;
.nf;.p -5,2,15;**** TEXT PROCEDURE ttynumber(node,lineno);
.index ^^TTYNUMBER external procedure
.index ^^TTY number in DEC-10 network, TTYNUMBER procedure
.index ^^Network, TTYNUMBER procedure
! Required external procedures: ;
EXTERNAL INTEGER PROCEDURE xcalli;
EXTERNAL TEXT PROCEDURE idsixbit;
INTEGER node, lineno;
BEGIN
! Returns TTY number as octal ASCII text.
! Also returns full TTY device name as ttynumber.Main
! Example: TTY75: ttynumber = "75".
!  ttynumber.Main = "TTY75:". Thus ttynumber.Main can be used directly
!  as file specification for the TTY.
;

    INTEGER sixname;
    sixname:= xcalli(8R166,node*8R1000000+lineno,TRUE,0); ! GTXTN.;
    IF sixname NE 0 THEN
    BEGIN TEXT t; t:- idsixbit(sixname,0);
	t:- t.Main.Sub(1,t.Length+1);
	t.Setpos(t.Length); t.Putchar(':');
	ttynumber:- t.Sub(4,t.Length-4);
    END;
END;
.fill
.p -5,2,9
FILED - FOR INPUTTING AND OUTPUTTING DEC-10/20 TEXT FILES:
.skip
     By Jacob Palme, Swedish National Defense Research Institute,
     S-104 50 Stockholm 80, Sweden.
.skip
     This program contains a class FILED (which can be separately
     compiled) to input and output DEC-10/20 ASCII-7-formatted text
     files in SIMULA. The program can handle both unnumbered and
     line numbered text files. For numbered files, the program will
     ensure that the output file has the line number format
     required by other DEC-10/20 text handling programs like
    SOS. Lines without line numbers will be numbered.
.skip
     The good facilities for text handling make SIMULA a
     useful language for text handling programs like editors,
     programming language translators, compilers, pre-compilers etc.
.skip
     However, reading and writing text files on the DEC-10,
     especially line numbered files, is rather tricky in SIMULA. By
     using this program, you avoid those problems.
.skip
     The program can be found in a file with the name FILED.SIM on
     the SIMULA distribution tape. At the QZ computing center, you
     may find the file FILED.SIM on DSKE:[13,134].
.f;.p -5,2,10;****#INTEGER PROCEDURE xcalli(n,arg,errnoskip,errvalue);
.index ^^XCALLI EXTERNAL INTEGER PROCEDURE
.index ^^Monitor calls from SIMULA, XCALLI procedure
.index ^^CALLI UUO executed directly from SIMULA, XCALLI procedure
.index ^^Communication with monitor, XCALLI (CALLI UUO)
.br;INTEGER n,arg,errvalue;
BOOLEAN errnoskip;
.s;Executes CALLI AC1,N - where AC1 is loaded from ARG.
ERRVALUE is returned if the CALLI does not skip,
and ERRNOSKIP is TRUE.
See the Monitor Calls manual for CALLI UUO functions.
In TOPS-10, most of the monitor interface is handled by CALLI.
Examples: XCALLI(8R30,0,FALSE,0)=job number,
XCALLI(8R24,0,FALSE,0)=ppn (proj*2_^18+prog),
XCALLI(8R31,10,FALSE,0) will cause job to SLEEP 10 seconds,
XCALLI(8R41,m*2_^18+n,TRUE,0) will perform GETTAB(m,n) and return
value of item or zero on failure.
.br;For more esoteric functions, you may have to provide an argument list
pointed to by ABSADR(first word of list). Example:
.br;INTEGER rundev,runfile,runext,run3,runppn,runarg;
rundev:=SIXBIT("SYS"); runfil:=SIXBIT("SIMULA");
XCALLI(8R35,ABSADR(rundev),TRUE,0); EXIT(0);
.br;Will start SIMULA in command mode or exit to monitor on failure.
.s;XCALLI should be used with great caution. It is provided as a convenience
where safer methods of achieving the desired results are too cumbersome
or impossible. By using XCALLI, you may not need to write a MACRO-10 procedure
for a very small task, and experimenting is easier.
Be very careful not to cause any garbage collection between computation of an
absolute address and its use!
.f;.p -5,2,8;**** INTEGER PROCEDURE wildsix(id,mask,k);
.br;NAME mask; INTEGER mask, k; TEXT id;
.index ^^WILDSIX EXTERNAL INTEGER PROCEDURE
.index ^^Conversion from ASCII to SIXBIT, WILDSIX procedure
.index ^^ASCII to SIXBIT conversion, WILDSIX procedure
.s;Convert at most K (K <= 6) characters from ID to SIXBIT,
taking special notice of "wild cards" as follows:
If a '?' is found, the corresponding position in MASK (byte size 6)
will be made = 8R77. If an asterisk ('*') is found, the rest of
the characters up to number K (1<=K<=6) will be treated as '?'.
The result is the SIXBIT code of ID (initial K characters).
See PROCEDURE SIXBIT.
.BR;Example: ID="AB??", K=6 will give wildsix=8R414237370000,
MASK=8R000077770000.
.subtitle APPENDIX A - REALTIME - A SCHEDULER FOR TERMINAL PROCESSES
.f;.page
APPENDIX A - REALTIME - A SCHEDULER FOR TERMINAL PROCESSES
.skip 2
(The programs described in this appendix do not work on
a DECsystem-20 at the time when this is written, April 1977.)
.skip 5
CONTENTS
.index ^^REALTIME EXTERNAL SIMULATION CLASS
.lm 21;.P -6,2,3;A.1## REALTIME - A SCHEDULER FOR TERMINAL PROCESSES
.lm 21;.P -6,0,3;A.2## PROCEDURES WAITFORINPUT, INPUTCHECK AND HOLD(0).
.lm 21;.P -6,0,3;A.3## PROCEDURES CLOCKTIME, SYNCHRONIZE AND DESYNCHRONIZE.
.lm 21;.P -6,0,3;A.4## STRUCTURE OF THE CLASS REALTIME
.lm 21;.P -6,0,3;A.5## APPLICATION EXAMPLES.
.SKIP
.lm 28;.P -8,0,3;A.5.1.1 SIMULTANEOUS, UNINTERFERED DIALOGUE BETWEEN
THE COMPUTER AND SEVERAL REAL TERMINALS
.lm 28;.P -8,0,3;A.5.1.2 A COMPLETE PROGRAM USING THE CLASS REALTIME.
.SKIP
.lm 28;.P -8,0,3;A.5.2## DATA BASE SYSTEM, SEVERAL TERMINALS
.lm 28;.P -8,0,3;A.5.3## LIMITED RESPONSE TIME FOR THE TERMINAL OPERATOR.
.lm 28;.P -8,0,3;A.5.4## A CONVERSATIONAL TIME-SHARING SYSTEM.
.lm 28;.P -8,0,3;A.5.5## COORDINATED CONTROL OF SIMULTANEOUS REAL PROCESSES.
.lm 28;.P -8,0,3;A.5.6## SIMULTANEOUS DIALOGUE AND EXECUTION.
.page
.f;.lm 5;This documentation is based on FOA P Report C 8394 (June 1974):
"Making SIMULA into a Programming Language for Real Time" by Jacob Palme.
(Published in Management Informatics, Vol.#4, No.#4, August 1975,
pp.#129-138.)
.tp 15
.skip 2
The simplest kind of real time application is the execution of
a conversational program running under a time-sharing system with
one external user talking to the program through a terminal such
as a display unit or a typewriter terminal.
.skip 1
This simple interaction can already be easily programmed
in SIMULA.
The time-sharing operating system will handle all
the real time problems for the SIMULA program.
.skip 1
But as soon as we want more than one real process to communicate
simultaneously with the SIMULA program, more advanced
real time capabilities are required.
.skip 1
Examples:
.skip 1
#-#We may want to write a simulation program which communicates with real
components, e.g_. human participants.
.skip 1
#-#We want to let several users from separate terminals simultaneously
access a data base, both fetching and storing information in it.
One master program has to coordinate the data base accesses so that
two users do not simultaneously try to update the same record.
We might want to write this program in SIMULA.
.p -5,4,20
A.1.3 Procedures WAITFORINPUT, INPUTCHECK and HOLD(0).
.skip 1
The execution of a SIMULA process is only interrupted where explicit
statements like "HOLD" or "PASSIVATE" cause control to transfer from
the process to the scheduler. A common error when programming real time
programs is that one parallel process uses partly updated data, produced
by another parallel process. For small in-core updates,
a programmer in SIMULA can avoid this
error by only putting statements like "HOLD" and "PASSIVATE" at places
in the source program where data updates are complete.
.skip 1
For more complex updates, a special process can be written
to access the critical data, and other processes requesting updates
can be queued to the special process.
When a SIMULA process executes a statement like "HOLD" or "PASSIVATE",
then control goes to the
SIMULA scheduler, which then transfers control to another process.
.skip 1
"HOLD(A)" stops execution of the current process
but asks the SIMULA scheduler to restart it after A time units. If A
is zero, then the current process is stopped and placed at the end of
a queue of currently active processes. If a number of processes successively
make "HOLD(0.0)" they will thus get access to the CPU
in a round robin fashion.
.skip 1
A SIMULA programmer can thus ensure fast response to external interrupts
by not doing too much computations between successive "HOLDS".
.skip 1
"PASSIVATE" stops the current process indefinitely, it must be activated
again from some other process.
.skip 1
Processes waiting for
external interrupts are put into a special queue
with the procedure call "WAITFORINPUT".
The "SIMULATION CLASS REALTIME" contains a special version of
"HOLD" and an alternative version of "PASSIVATE" called "TERMINAL__PASSIVATE"
and these procedures first scan this special
queue to see if data has arrived from the input device associated
with the terminal processes.
.skip 1
If a process is found for which data has
arrived on the associated input device, then the SIMULA scheduler
activates this process immediately.
.skip 1
The event created by the first
external interrupt found
is thus placed in front of other currently
active processes in the sequencing set.
This, however, is not done at the time of the interrupt, the placing
is done at the time
of the next activation of the scheduler after the interrupt.
.skip 1
Inside a terminalprocess, a call "WAITFORINPUT" will thus tell the
system to make this process passive, but to reactivate it as soon
as new data has arrived on the input device associated with the process.
.skip 1
A new BOOLEAN standard procedure INPUTCHECK is also
introduced. INPUTCHECK is TRUE if and only
if data is available (i.e. has arrived from the terminal device) for
reading with INIMAGE.
.p -5,3,15
A.3 Procedures CLOCKTIME, SYNCHRONIZE and DESYNCHRONIZE.
.skip 1
.index synchronize
.index desynchronize
.index hibernate
.index wait
For real time applications, we may also want to synchronize simulated
time with real time. For this there are three new standard procedures:
.skip 1
REAL PROCEDURE clocktime; COMMENT gives time in seconds since the beginning
of the current day;
.skip 1
PROCEDURE synchronize(timeunit); REAL timeunit; COMMENT this procedure
starts synchronization of real and simulated time;
.skip 1
PROCEDURE desynchronize; COMMENT and this stops synchronization;
.skip 1
Of course perfect synchronization of real and simulated
time is not possible since the speed of the computer itself is not infinite.
The package tries to synchronize, and never allows simulated time to
become more than a fraction of a second greater than real time.
.skip
Synchronization consumes some additional cpu time.
.skip 1
If the scheduler finds that the
next process to be scheduled has a too large simulated time, then the
SIMULA scheduler lets the SIMULA program go to sleep for the
necessary time interval. Any interrupts caused by input will however
start the SIMULA program again.
.skip 1
The parameter "timeunit" to the procedure "synchronize" is there
since the time unit may not be the same in the simulation as in the
real world. "timeunit" is the size of the simulation time unit in seconds.
Thus, if simulated time is measured in seconds, "timeunit" should be 1.0.
If simulated time is measured in hours, "timeunit" should be 60*60.
.page
.indent -5
A.4 Structure of the class REALTIME
.skip
.nofill;.nojustify
OPTIONS(/E);
EXTERNAL BOOLEAN PROCEDURE inputcheck;
EXTERNAL PROCEDURE sleep, abort;
EXTERNAL INTEGER PROCEDURE inputwait;
EXTERNAL REAL PROCEDURE clocktime;
simulation CLASS realtime;
NOT HIDDEN PROTECTED synchronize, desynchronize,
terminal__passivate,
hold, terminalprocess;
NOT HIDDEN process, current, time, passivate, wait,
main, linkage, link, head;
BEGIN
.skip
  PROCEDURE synchronize(timeunit); REAL timeunit;
  COMMENT this procedure starts synchronization of real and
  simulated time;
  BEGIN ... END;
.skip
  PROCEDURE desynchronize;
  COMMENT This procedure ends synchronization of real and
  simulated time;
  BEGIN ... END;
.skip
  PROCEDURE terminal__passivate;
  COMMENT special version of passivate for a
  terminalprocess;
  BEGIN ... END;
.skip
  PROCEDURE wait(q); REF (head) q;
  COMMENT special version of wait for a terminalprocess;
  BEGIN ... END;
.skip
  PROCEDURE hold(delaytime); REAL delaytime;
  COMMENT special version of hold for terminalprocesses.
  hold(0.0) gives round robin process scheduling;
  BEGIN ... END;
.skip
  process CLASS terminalprocess(fromterminal);
  REF (infile) fromterminal;
  NOT HIDDEN PROTECTED fromterminal, waitforinput;
  NOT HIDDEN evtime, nextev, into;
  BEGIN
.skip
    PROCEDURE waitforinput;
    COMMENT this process waits until inimage is
    possible to make for some file in the input__array;
    BEGIN ... END;
.skip
  END of terminalprocess;
.skip
END of class realtime;
.p -5,4,20
A.5 Application examples.
.fill
.skip 1
In this section you can see how the new concepts can be
used. Some examples will be given
 of real time programs written in
SIMULA using the new concepts.
.skip 1
The programs are not always complete. Three dots indicate places
where something has been left out.
.nofill
.p -5,4,10
A.5.1.1 Simultaneous, uninterfered dialogue between
.index conversational terminal
the computer and several real terminals.
.skip 1
.fill
One master terminal reads file specifications for the other
terminals and starts up one copy of the SIMULA CLASS "terminal"
for each of the other terminals. Each of these "terminalprocesses"
will open the connection to its real terminal, and then go into
a loop of (a) waiting for input and (b) producing answers.
.skip 1
Each of these terminal loops will go on independently of the other,
and the SIMULA scheduler will distribute control between the
"terminalprocesses".
.skip 1
.nofill
.test page 18
terminalprocess CLASS terminal(toterminal);
REF (outfile) toterminal;
BEGIN
  INSPECT fromterminal DO
  INSPECT toterminal DO
  BEGIN
.left margin 10
PROCEDURE open__terminal__connections; ...
PROCEDURE read__the__input__and__produce__an__answer; ...
.skip 1
WHILE TRUE DO
BEGIN
.left margin 12
waitforinput;
read__the__input__and__produce__an__answer;
.left margin 10
END;
.left margin 7
END;
.left margin 5
END;
.skip 1
.test page 10
ACTIVATE NEW terminal(sysin,sysout);
ACTIVATE NEW terminal(NEW infile("TTY2:"),
                      NEW outfile("TTY2:"));
ACTIVATE NEW terminal.....
.....
passivate;
.p -5,2,10
A.5.1.2 A complete program using the CLASS REALTIME.
.skip
Here follows a complete, small program using the CLASS
REALTIME.
At each terminal, the program returns the input
received at that terminal. If the input at a terminal
is a legal TTY device specification, that terminal
is connected to the program.
.nofill
BEGIN
  EXTERNAL BOOLEAN PROCEDURE inputcheck;
  EXTERNAL PROCEDURE sleep, abort;
  EXTERNAL INTEGER PROCEDURE inputwait;
  EXTERNAL REAL PROCEDURE clocktime;
  EXTERNAL CLASS realtime;
  EXTERNAL REF (infile) PROCEDURE findinfile;
  EXTERNAL REF (outfile) PROCEDURE findoutfile;
.p 0,1,28
  realtime BEGIN
.skip
    terminalprocess CLASS terminal(toterminal);
    REF (outfile) toterminal;
    BEGIN
      TEXT stripimage;
      INSPECT fromterminal DO INSPECT toterminal DO
      WHILE fromterminal.image.sub(1,2) NE "/*" DO
      BEGIN
        waitforinput; inimage;
        stripimage:- fromterminal.image.strip;
        IF stripimage =/= NOTEXT THEN
        BEGIN
          IF stripimage.sub(stripimage.length,1)
          = ":" THEN
          BEGIN COMMENT Connect another terminal;
            IF connect(stripimage) THEN
            outtext("NEW LINE OPEN. ") ELSE
            outtext("NOT ABLE TO OPEN THAT LINE. ");
          END;
        END;
        outtext("I received: '");
        outtext(stripimage); outtext("'");
        outimage;
      END;
      toterminal.close; fromterminal.close;
    END;
.p 0,2,20
    BOOLEAN PROCEDURE connect(filespec);
    VALUE filespec; TEXT filespec;
    INSPECT findinfile(filespec) DO
    BEGIN
      open(blanks(80));
      INSPECT findoutfile(filespec) DO
      BEGIN
        open(blanks(80));
        connect:= TRUE;
        outtext(
        "THIS TERMINAL IS NOW CONNECTED!");
        outimage;
        ACTIVATE NEW terminal
        (THIS infile, THIS outfile);
      END
      OTHERWISE close;
    END;
.p 0,2,5
    ACTIVATE NEW terminal(sysin, sysout);
    passivate;
  END of realtime prefixed block;
END of the whole program;
.nofill
.p -5,2,10
A.5.2 Data base system, several terminals
.index multi-terminal
.index access protection
use the same data base.
.skip 1
.fill
This is a very simple example of a data  base system with several
conversational terminals which independently put requests (questions
or updates) to a data base. The actual data base
accesses must be done for only one request at a time to avoid errors
when one terminal tries to read what another terminal is updating.
.skip 1
The SIMULA program contains one  process  for each terminal and
one  process  for the data base.
.skip 1
The terminal  processes  wait
for input from their respective terminals. When a data base request
has been received, the terminal  process  is put into a queue
of data base requests.
.skip 1
The data base  process  takes one terminal
 process  at a time from this queue and processes the data base
request. Thereafter, the data base process ACTIVATEs the terminal
process again. When ACTIVATEd, this terminal process writes the
answer to its terminal and waits for new requests from it.
.nofill
.skip 1
.test page 22
realtime BEGIN
REF (head) request__queue;
REF (data__base) the__data__base;
.skip 1
terminalprocess CLASS terminal(toterminal);
REF (outfile) toterminal;
BEGIN
   INSPECT fromterminal DO
   INSPECT toterminal DO
   BEGIN
.left margin 11
PROCEDURE open__terminal__line; ...
PROCEDURE read__and__prepare__data__base__request; ...
PROCEDURE write__the__answer__to__the__request; ...
.skip 1
WHILE TRUE DO
BEGIN
.left margin 14
waitforinput;
read__and__prepare__data__base__request;
ACTIVATE the__data__base DELAY 0;
wait(request__queue);
write__the__answer__to__the__request;
.left margin 11
END;
.left margin 8
END;
.left margin 5
END;
.skip 1
.test page 18
process CLASS data__base;
BEGIN
   INSPECT NEW
   directfile(data__base__file__specifications) DO
   BEGIN
.left margin 11
PROCEDURE open__data__base__file; ...
PROCEDURE put__the__request__to__the__data__base; ...
.skip 1
open__data__base__file;
WHILE TRUE DO
INSPECT request__queue.first WHEN terminal DO
BEGIN
.left margin 14
out; COMMENT to remove the terminal from the request queue;
put__the__request__to__the__data__base;
ACTIVATE THIS terminal;
.left margin 11
END OTHERWISE passivate;
.left margin 8
END;
.left margin 5
END;
.nofill
.p -5,2,10
A.5.3 Limited response time for the terminal operator.
.index reaction time
.skip 1
.fill
This is a very simple example of a program which is coordinated
with the time in the real world. A question is given
to a terminal operator and the program waits for an answer.
The program should take different action depending on whether
the answer is received within 60 seconds or not.
.skip 1
To do this, the new standard procedure SYNCHRONIZE is used
to synchronize real time with the simulated
time in SIMULA.
.skip 1
.nofill
.test page 20
terminalprocess CLASS terminal(toterminal);
REF (outfile) toterminal;
BEGIN
   INSPECT fromterminal DO
   INSPECT toterminal DO
   BEGIN
.left margin 11
REAL questiontime;
PROCEDURE write__question__to__the__terminal; ...
PROCEDURE process__fast__answer; ...
PROCEDURE process__slow__answer; ...
.skip 1
synchronize(1.0);
write__question__to__the__terminal;
questiontime:= time;
waitforinput;
IF time - questiontime < 60.0 THEN
process__fast__answer ELSE
process__slow__answer;
.left margin 8
END;
.left margin 5
END;
.nofill
.p -5,4,10
A.5.4 A conversational time-sharing system.
.index conversational system
.skip 1
.fill
The conversational time-sharing system in this example could be
an interpreter for a language like APL or FOCAL or AID.
.skip 1
Highest
priority is given to those input commands which are to be performed
directly. Lower priority is given to input commands requesting the
execution of a stored program. When several stored programs
are in execution at the same time, CPU power is distributed
between them in a round robin fashion letting each program perform
one statement in the stored program before continuing to the next
program.
.skip 1
.nofill
.test page 30
terminalprocess CLASS terminal(toterminal);
REF (outfile) toterminal;
BEGIN
   INSPECT fromterminal DO
   INSPECT toterminal DO
   BEGIN
.left margin 11
PROCEDURE open__terminal__connections; ...
PROCEDURE read__the__input__and__produce__an__answer;
BEGIN
.left margin 14
BOOLEAN more__statements, execute__command;
PROCEDURE read__and__interpret__an__input__line; ...
PROCEDURE execute__the__next__stored__program__statement; ...
PROCEDURE perform__the__command__from__the__input__line; ...
read__and__interpret__an__input__line;
IF NOT execute__command THEN
perform__the__command__from__the__input__line ELSE
WHILE more__statements DO
BEGIN
.left margin 17
HOLD(0); COMMENT to transfer control to another process;
execute__the__next__stored__program__statement;
.left margin 14
END;
.left margin 11
END;
.skip 1
WHILE TRUE DO
BEGIN
.left margin 14
waitforinput;
read__the__input__and__produce__an__answer;
.left margin 11
END;
.left margin 8
END;
.left margin 5
END;
.skip 2
.fill
.p -5,3,14
A.5.5 Coordinated control of simultaneous real processes.
.skip 1
.index semaphore
.index parallel processes in the real world
.index process control
When a real time computer program communicates with several simultaneous
processes in the real world, the computer program may want to control
itself or the real-world processes depending on the results in the various
processes.
.skip 1
Example 1: A simulation program may want to continue the simulation when
all the terminals have replied to certain questions.
.skip 1
Example 2: A process control program may monitor several real-world
processes, and
initiate other real-world actions when previous processes are ready.
.skip 1
This is similar to PERT-networks in planning, where certain
actions must wait for other actions to finish.
.skip 1
To illustrate this, a simple example assumes a robot with three
arms. A process "put nail in board" is initiated. This process initiates
three simultaneous processes, the first arm gets a hammer, the second arm gets
a nail, and the third arm gets a board. When all these three processes
are finished, the hammer is used to push the nail into the board.
.skip 1
In other languages, special constructs like "fork" and "join"
are used to create parallel processes and then continue when all
the processes are ready. But the same thing
is very simple to program in SIMULA, and in
SIMULA we do not have to wait until a process is completely finished,
we can also easily start a later process when still running
processes have reached certain states.
.skip 1
.test page 27
.nofill
terminalprocess CLASS arm(toterminal);
REF (outfile) toterminal;
BEGIN
.left margin 8
INSPECT fromterminal DO
INSPECT toterminal DO
BEGIN
.left margin 11
TEXT order; BOOLEAN ready; REF (process) master;
PROCEDURE perform__order; ...
WHILE TRUE DO
BEGIN
.left margin 14
terminal__passivate;
ready:= FALSE; perform__order; ready:= TRUE;
ACTIVATE master DELAY 0;
.left margin 11
END;
.left margin 8
END;
.left margin 5
END;
.skip 1
process CLASS put__nail__in__board(arm1, arm2, arm3);
REF (arm) arm1, arm2, arm3;
BEGIN
.left margin 8
arm1.order:- copy("find hammer"); arm1.master:- current;
arm2.order:- copy("find nail"); arm2.master:- current;
arm3.order:- copy("find board"); arm3.master:- current;
ACTIVATE arm1 DELAY 0;
ACTIVATE arm2 DELAY 0;
ACTIVATE arm3 DELAY 0;
terminal__passivate;
WHILE NOT (arm1.ready AND arm2.ready AND arm3.ready)
DO terminal__passivate;
arm1.order:- copy("swing hammer");
ACTIVATE arm1 DELAY 0;
 ...
.left margin 5
END;
.p -5,2,15
A.5.6 Simultaneous dialogue and execution.
.index status query
.index monitoring
.skip 1
.fill
On many occasions, you may want a program to execute and
talk to the user at the same time. You may for example want to allow
the user to ask the computer how far the execution has
reached. This is especially useful for time-consuming executions,
where the user may get impatient and may
want to know if the delay is caused by machine error, erroneous data
to the program, by a heavy load on the machine or just by a
time-consuming execution in general.
.skip 1
One can then write a program with two processes, one process for
talking to the user and another process for the time-consuming
execution.
.skip 1
.nofill
.test page 22
terminalprocess CLASS userdialogue(toterminal);
REF (outfile) toterminal;
BEGIN
.left margin 8
INSPECT fromterminal DO
INSPECT toterminal DO
BEGIN
.left margin 11
ACTIVATE NEW cpuactivity DELAY 0;
WHILE TRUE DO
BEGIN
.left margin 14
outline("CPU activity has begun. If you want to");
outline("know what is happening, then type");
outline("""?"" on your terminal");
waitforinput; inimage;
tell__the__user__what__is__happening;
.left margin 11
END;
.left margin 8
END;
.left margin 5
END;
.skip 1
.subtitle APPENDIX B - CONTROLLED ERROR HANDLING
.page
APPENDIX B - CONTROLLED ERROR HANDLING
.s;By Stefan Arnborg August 1975, Modified October 1975
.s;.nf;CONTENTS
.s;.lm 10
B.1 PROBLEM
.s;B.2 SOLUTIONS
.s;B.3 CHOICE OF SOLUTION FOR SIMULA
.s;B.4 PROPOSAL
.s;B.5 DISCUSSION
.lm 5
.f;.skip 2
The procedures MASKERROR, SENSEERROR, JUMPERROR and RESETERROR
described below have not yet been implemented,
and no promise is made about if or when to do so.
.index ^^Arnborg, Stefan
.p -5,2,2
B.1##Problem.
.p 0,1,5
Dependable software must be prepared to detect and diagnose
.index ^^Recovery after error
errors in input data. For complex problems error handling will
take a significant part of the programming effort. Programmed
error handling is a means to achieve error handling without
having to reprogram in SIMULA checks actually made by the
programming system and the hardware.
The absence of this facility has been used as one
.index ^^PL/1 programming language
argument for using PL/1 rather than SIMULA at FOA.
.p -5,2,8
B.2##Solutions.
.p 0,1,5
Programmed error handling in other programming systems and
environments usually falls in one of three classes:
.p 0,1,5
A##Implicit action.
.p 0,1,5
In CDC Algol an error may cause a jump to a preset label.
In the Knuth proposal for I/O in Algol 60, errors may 
cause predefined procedures to be called.
In PL/1 an error may cause a previously set ON-unit to be
.index ^^ON condition in PL/1
activated.
.p 0,1,5
B##Error returns.
.p 0,1,5
.index ^^FORTRAN programming language
.index ^^READ errors
.index ^^WRITE errors
.index ^^Data transmission errors
.index ^^Input-Output errors
.index ^^Transmission of data, errors
The READ/WRITE statements of many FORTRAN implementations permit
error and end-of-file exit labels to be passed as parameters.
Many general-purpose algorithms in ACM collected algorithms
have parameters returning error codes or error exit label parameters.
.p 0,1,5
C##Raising flags.
.index ^^Error flags
.index ^^Flags, marking errors
.index ^^DBMS error condition
.p 0,1,5
In the CODASYL DBMS proposal, an error condition raises flags
that can be inspected by the program.
.p -5,2,8
B.3##Choice of solution for SIMULA.
.p 0,1,5
The following requirements on a solution are rather obvious:
.left margin 10
.p -5,1,9
i)###Existing programs should not be affected unless the user wants
to take advantage of the facility.
.p -5,1,8
ii)##It must be easily implemented on existing systems.
.p -5,1,8
iii) It must be well defined and easy to use.
.p -5,1,8
iv)##It must be compatible with the overall language philosophy.
.p -5,1,8
v)###In particular, it must be as implementation independent as possible.
.left margin 5
.p 0,1,5
Method A seems to satisfy i) and v) but contradicts the other requirements.
In particular, it requires much programming effort (at least in the IBM 360 and
DEC 10 implementations) to be able to enter a user program point from anywhere in
the run-time system. However, an implicit jump is easier to implement than an implicit procedure
call. It has the slight drawback that it is difficult to know
where the error occurred and to proceed after corrections, because bookkeeping operations like
e.g. file positioning may get out of phase.
It is also not agreed that implicit actions are consistent with good
programming methodology.

.p 0,1,5
Method B contradicts i) or ii) and iv) depending on whether the additional
parameters are made compulsory or optional. Moreover, it takes care only
of errors in system procedures.
.p 0,1,5
Method C complies with all requirements to a reasonable degree. However,
it requires a program to continue after an error has occurred and this
continued execution will maybe not be entirely implementation independent.
It can be seen as a method to achieve an orderly failure rather than a
means to implement a complicated polyalgorithm.
It is easy to implement recovery procedures of differing levels of detail
as in the example:
.p 0,1,16
.nofill
.index ^^Error recovery
BEGIN initialize__sequence__of__batches;
  WHILE more__batches DO
  BEGIN
    process__batch:
    WHILE more__records DO
    BEGIN process__record:
      WHILE more__fields DO
      BEGIN process__field;
        recovery1;
      END;
      recovery2;
    END;
    recovery3;
  END;
END;
.fill
.p 0,1,5
At each of the recovery points it is possible to prevent upward
updates from an erroneous field, record or batch.
.p -5,2,8
B.4##Proposal.
.p 0,1,5
It is suggested that the following text be inserted into the
SDG publications:
.p 0,1,5
"Programmed Error Handling.
.p 0,1,5
The programmed error handling facilities of SIMULA make it
possible to achieve, in a SIMULA program, an orderly handling
of certain errors occurring during execution as a result of
incorrect or unexpected inputs to the program.
Errors are classified into the following categories:
.p 0,1,5
.left margin 9
.p -4,1,13
.index ^^Underflow error
.index ^^Floating point error
1###Underflow in floating point computation
.indent -4
.index ^^Overflow error
.index ^^Division by zero error
2###Overflow in computation or division by zero
.indent -4
.index ^^I/O transmission error
3###I/O transmission error
.indent -4
4###End of file error
.indent -4
.index ^^Edit overflow error
5###Edit overflow
.indent -4
.index ^^De-editing procedure error
6###Incorrect text contents for de-editing procedure
.indent -4
7###Array index out of range
.index ^^Array index range error
.index ^^Range error for array index
.indent -4
.index ^^Mathematical function error
8###Incorrect parameter to mathematical function
.indent -4
9###Time limit - as defined by a previous call to TIMELIMIT - exceeded.
.indent -4
10##All the errors listed above.
.indent -4
999999#Remaining errors that can be intercepted in an implementation.
.left margin 5
.p 0,1,5
The errors above are not all errors that can result from incorrect
data but only those that will occur as a direct and
immediate consequence of invalid data. Second order errors result
from following an incorrect path of the program because of
invalid data: those errors are not handled.
.p 0,1,5
The following system procedures are available for error handling:
.p 0,1,5
[Addition by Jacob Palme 1976-03]
Possibly we could allow an implementation to add an implementation
dependent number of extra error codes, between 11 and 999998.
The error code 999999 would then be equivalent to all such
error codes, which means that programs using only error codes
1-8 will still be machine independent and programs using error
codes 9, 10 and 999999 will be reasonably machine independent,
while programs using extra error codes between 11 and 999998 will
at their own risk be machine dependent.
.p 0,1,5
.index ^^MASKERROR procedure
.indent -5
**** PROCEDURE MASKERROR(CODE,COUNT);   INTEGER CODE,COUNT;
.s;Execution of MASKERROR permits COUNT errors of category
CODE to occur without intervention by the run time system.
The effect of continuing after an error is dependent on the kind of error:
(On certain computers, the architecture may make these default
effects impossible. If so, they may do otherwise.)
.break
.ls
.le;Result of operation is zero.
.le;Result of operation is zero.
.le;The image fetched will contain the record as transmitted,
if possible. Otherwise a blank image will be fetched.
.le;The image will be set to blanks. ENDFILE will still be
TRUE if sensed.
.le;The field of the operation will contain asterisks.
.le;The result will be zero.
.le;The first acceptable index (i e the lower bound) will be used.
Note that on some implementations the first ELEMENT (lower bound everywhere!)
may have to be used.
.le;The result of the function will be zero.
.le;No action, job continues.
.els
.break
11-999999.#Implementation dependent.
.skip
A new call to MASKERROR resets the
previous error count (as returned by SENSEERROR).
.p 0,1,5
If an implementation enters dialog or debug mode in case of an error
of a category mentioned above, this facility will be suppressed by a
call to MASKERROR for the category.
.p 0,1,5
When the program starts, categories 1 and 5 are automatically masked
by the SIMULA system
with a large
value on COUNT.
.p 0,2,5
.index ^^JUMPERROR procedure
.indent -5
**** PROCEDURE JUMPERROR(CODE,L);   INTEGER CODE;   LABEL L;
.s;Execution of JUMPERROR directs the run time system
to make an implicit jump to L if an error of category CODE
occurs. The sequence of operations is interrupted so that no
effect of the illegal operation remains when L is entered, nor will
it be possible to find out exactly which operation caused
the error, except indirectly from the contents of program
variables.
.skip
The label L must be in the outermost block of the main program
(recovery for the otherwise possible ILLEGAL GOTO may be very
difficult or impossible to implement). From this follows that
JUMPERROR cannot be called in a separately compiled module.
A call to jumperror for other labels than in the outermost block
should cause an error interrupt.
.skip
Both MASKERROR and JUMPERROR can be called for an error
category, but the last call has effect.
.p 0,1,5
Dialogue and debug mode recoveries are suppressed by JUMPERROR as
by MASKERROR.
.p 0,2,5
.index ^^Reseterror procedure
.indent -5
**** PROCEDURE RESETERROR(CODE);   INTEGER CODE;
.s;Execution of RESETERROR inhibits the effect of previous
calls to MASKERROR or JUMPERROR for the category CODE. Subsequent errors are intercepted and diagnosed.
.p 0,2,5
.index ^^SENSEERROR procedure
.indent -5
**** INTEGER PROCEDURE SENSEERROR(CODE);   INTEGER CODE;
.s;A call to SENSEERROR returns the number of errors of category CODE
that have occurred. If CODE is zero,
the total number of errors is returned. SENSEERROR does not reset
the error counts.
.p -5,2,8
B.5##Discussion.
.p 0,1,5
This proposal was modified at in October 75 after the SDG meeting.
The proposal can be modified in several areas to accomplish
a different balance between implementability and implementation
independence:
.p 0,1,5
The error categories can be made finer or coarser,
in particular the existence of categories 11-999999 is debatable;
.break
Default settings can be altered;
.break
One may redefine results of undefined operations;
.break
One may specify the error categories by reference
to the sections in the Common Base or Algol report where
the error is described;
.break
It is possible to use different system procedures instead of
having the non-natural assignment of codes to error categories;
.break
These questions are best solved (if the proposal is accepted)
in the Simula Development Group.
.subtitle APPENDIX C - INDEX
.left margin 5;.fill;.nojustify;.page
.indent -5
APPENDIX C - INDEX
.indent -5
------------------
.left margin 3
.skip
.print index

