The_Cedar_Manual_Version_4.2_Jun83 The Cedar Manual Version 4.2 Jun83

User Manual: Pdf The_Cedar_Manual_Version_4.2_Jun83

Open the PDF directly: View PDF PDF.
Page Count: 400

DownloadThe_Cedar_Manual_Version_4.2_Jun83 The Cedar Manual Version 4.2 Jun83
Open PDF In BrowserView PDF
The Cedar Manual
Version 4.2
Release as
Came from
Last edited

[lndigo]Documentation>Manual.df
[lndigo]Manual>Manual.df
By Jim Hor'1ing on June 8, 1983 6:45 pm

Abstract: Cedar is a new computing environment developed by CSL and ISL for use on
D-machines-Dorados, Dolphins, and Dandelions. This collection of documents describes Release
4.2 of Cedar, June 1983. It consists of a number of sections that have been separately written,
filed, updated, and checked. They may not be entirely consistent-the authors would appreciate
being informed of inconsistencies, either internal to the documentation, or between the
documentation and the system. Because various part of the system are still under intensive
development, any hardcopy documentation is probably out of date. Each of the major components
begins with a title sheet that lists the file name of its working ("came from") version, which may
be more up-to-date. In the following table of contents, items marked with • are short summaries;
you should obtain loose copies for quick reference.

XEROX

Xerox Corporation
Palo Alto Research Center
3333 Coyote Hill Road
Palo Alto, California 94304

DRAFT - For Internal Xerox Use Only - DRAFT

2

THE CEDAR MANUAL

Contents
Introduction to Cedar
The Briefing Blurb
The Tioga Editor
How To Use Walnut
The Cedar Language
Cedar
Cedar
Cedar
Cedar
Cedar

Language Overview
Safe Language Syntax·
Language Syntax
Language Reference Summary Sheets*
Language Reference Manual [Bound Separately]

(CLRMSafeGram.press)
(CLRMSumm.press)

Cedar Programming
Annotated Cedar Examples
Stylizing Cedar Programs
Cedar Program Style Sheet*

(StyleSheet.press)

Component Manuals (sorted alphabetically by title)
BugBane.tioga
DFFiles.tioga
DoradoBooting.press
LupineUsersGuide.press
NewStuff.tioga
ReleaseProcedures.bravo
TSetterDoc.tioga
UserExec.tioga
UserProfileDoc.tioga
ViewerDoc.tioga
Component Library
Documented Interfaces
Cedar Catalog

CEDAR 4.2

Cedar 4.2 Documentation (Preliminary)
L·a.st edited by: Jim Donahue June 1, 1983 11:06 am, Jim Horning May 23, 1983 1:43 pm
This database gives a very preliminary version of online l:1ocumentation for Cedar, It consists
of several Whiteboards, each of which contains references to other Whiteboards and to various
files that contain important information about the system. Or, to browse around in it, just MIDDLE
click the icon for the manual and its various pieces (do the same to any of the icons on any
~Nhiteboard to see its contents), Also, check out the Brl'ejz'ngBlurb below for the scoop on PARC
and Cedar (com lemerlts of L le Ramshaw
Manual
.df

"-===;'l""
.......
Ced~r:;

"1:==::::::;",
l""
'.
CLRM,DF

::

'.
.'.'

Examples

:."
.'

_.

:;

,or

::

""
"
"
I_._ _.......r.r.
.. ::

"':

__.......r.o:..::

.,.

'.

...._.. t:::=::;"l..
Interf aceOo

,or

iII===~'"
cedarStyle 1~

"~~"
pa""'.
General
"

'.

"

.0'

:'.
'''...
'''...

.or

SlJbManuais

.Dr

""
"""
"
""

::

::

''..
''.'..
'.
r.r.
••::'.

I_._ _.......

It::

I'"

To find out more about the structure of Cedar, browse the ?oNhiteboards given below-they
provide information about the basic operation of Cedar, the Cedar L·anguage, the major components
of the Cedar system (things you'll end up using all the time), the most widely used Cedar tools
(like the mail system. the file tool, etc.) and the important pro~ramming interfaces of Cedar, Also,
read the Introductz'on referenced below-it gives important general information about Cedar.

'.

IntrodlJctior
,tioga

'"""'..
"'".
"
'.
"''..
"

.,',

LJ

I

Language

I

components

0

EJ
Tools

1:::==:::;':'': .
"
.'
·,. ",'rText
:: References ::
·, .tioga ;: .tioga ::
,
""
·
.'
r.r.
••.
.
,

Tile Brie,fz'ng Blurb

The truth about PARe and Cedar (from Lyle Ramshaw)
-- everythin~ you want to know about the local environment
(including some hints for gracious living)

glossary
.tioga

I~ere

=>
V.lcmder why some tool is acting
strangely? This may give you some

"00::==::::;'":.
....

.'

UserProtile·
Doc

::
::

:!

.tioga

.'.:

"
---~ ',

..

"
"

,"

,

"
"
I
"!'

""

,'

USER P.P..OFILE OPTIONS

Interfaces

I_._ _.......

"

.:
1.1•

WHITEBO.4RD INSTRUCTIONS:

=>

LEFT
move entity
CTRL LEFT
deler,e enrjty
MIDDLE
open icon
SHIFT MIDDLE
expand icon
RIGHT
grow text box

=>
=>
=>
=>

ard
,tioga

~c
__e_da__r_B_a_S_iC_S__________________________~IEJeaar

EJ

There are a number of files that you need to know about to understand how
Cedar will behave when it runs on your machine: these include your user profile,
the catalogue of registered commands and. the basic DF files that provide the
common components of the system (like the compiler, binder, the Viewers packa~e,
etc.). Also below are references to the latest release message and how to boot a

USflr profile injo

User Exec injo

Documentation, default settings
and DF file

iC==:::;'1:: '1!l==::1::
User Profile '::
Doc
::
,tioga::

User
.Profile

::
It

....._ _....:;0;,,:,:

Tools

::
::
::

::
!,

,.::

Documentation, default
commands and DF file

IJserE~ec­

utilities

UserProfile

.'.'.'
.'.'.'.'
.'.'.'.'.:
....._ _...r.r;
••
user£lIec
,tioga

::

.Of

.

"-==:::;'1:'
I'"'.'

I'"'"-=~"'.

::
'.
'.'.

''..
'.
....._ _...r.r;•••'.'.

Registered·
Commands
.catalogue

·f

···
····
..··'

iC=::;'l"'.'.
.dt

'.
...._ _...Ir.r:
••!:

cedarClient ::
.d1

CedarClient.cU is the COllection of the basic Cedar components; you will
find it useful as a roadmap for all of the other DF files that are used in Cedar.
CedarClientFat.df includes more components and also the sources for a
number of the important interfaces (bringover 180 CedarClient,df will only
bringover the .bed files for the interfaces, which makes it hard to start building
programs although you can compile them.)

To read mail, edit
documents and print things
(the references to
documentation are on the

:.:.:.:.',.'.'.
···········~r·'·
:.

..
.::::!CA:::::::
',',
.:,',',',', '.'
:::
',',',',','

~~ ••,t

',','

:.

,II,' :.:

.'
':'

!:.:.:t:;,::.:.:::.:.:.:!:.~

.'

.
DoradoBooting
.press

····
··
..····
'

"-==::1:'
'iA.'
All the news that:s fit to

··
··
··
·

.'

"'

:;"

~I •• ,I
•
','.'

Cedar4
,1.msg

cedarClient
f'at
.dt

.

,',',',',', ','

One of the handy things to know
about (even if you're using a public
machine) is some of the magic behind
Dorado bootine- -- here's the SCOO1). {in

.'.'

':"

.,",',','. '.'
... ....'. .:.:.:.:.:.
,',',',',',
.:':.:':.:.
'.'
','
,',',

,,'.',',',',
,

.'.'.'::.'

....._ _....r.o;
•• ':

:,_~'l!!""""III

:.:.:.:.:!~,...

Dorado bootz'ng

C€dar 4.1 Rel€ase Message

'..
'

'.'.'.

"-==::1.'
'iA.'

Basic DF files

Handy tools

'''...
'.'.

user£~ec

.'.'
.'.'.'
.'
.'.'.'.'.'
.....:

..._--,

WHITEBOARD INSTRUCTIONS:

=>

LEFT
m.ove entity
CTRL LEFT
delete entity
MIDDLE
open icon
SHIFT MIDDLE
expand icon
RIGHT
grow text box

=>
=>
=>
=>

Cedar Language

EJ

The Cedar programming language is an extension of Mesa~ it is described in the Overview
ctocument given below, See the Components and Interfaces whiteboards for some of the most
commonly used Cedar interfaces, The CLRM DF file c:ontains ,press versions of the most
recent language documentation,
"""-:::==:::;'1""
I""-O... erIJiew

!:

.tioga

Components

"
L]

Interfaoes

CLRM.DF

::
""

11
""
"

'.
'.

'.
''..

'.
"

'.
'--_ _....r.o:
.."::

..::
"

Examples Documentation
Examples of the use of Cedar can be found in several places. The CedarExamples DF
file contains a CedarDocuments tioga file that includes five examples, inclUding parts of the
Cedar system itself, Additionally, the information packet that Greg gave you has some
more examples using several of the important packages in the system.
""
"'.
"""
'.
,OF
'.
""
"
....._ _....r.o:".,""

cedarElCamples

'.

iZ1cludes

".-==::::1"
......
"'.

Ced.arEsamples
in .... h~ ,tioga

-==:;'1""

L--

List.SortRe1
,mesa

""

"

:'
:;r

I""--

onlineMergE
inclllrle~ Sor-tRe1lmp
.mesa

"
"

.'.'.'"

':"

..::

.:"

....._ _...,jJ;';,,',

i

iIJ::=:::;'"""
Fun
""
,mesa

'.....-:::==;'1,.

""
:'"
""

'.
"

''..

""

'.'.
' -_ _ _r.r:.,I,""

udes

ir. eludes

'.
"-=~"
simple::

I""--

Esample
,mesa

::

:'::

"':
' -_ _ _r.r:
•• '."

"

"

::
::
"
::

.'.:"

"
' -_ _-..Ir.r.,.1 .

1

ludes

,..

"r'~=:;"1:'.'
s.amplerool ::
.mes.a
::"
""
"
""
"
.:
' -_ _.....70.,·.

WHITEBOARD INSTRUCTIONS:

=>

LEFT
move entity
CTRL LEFT
delete entlty
MIDDLE
open icon
SHIFT MIDDLE
expand icon
RIGHT
grow text box

=>
=>
=>
=>

~_lm_p_o__rt_a_n_t__C_e_d_a_r__C_o_m_p_o__ne__n_ts______________~I

EJedsr

The components of Cedar that you are lik.ely to use most frequently include:
Vie......ers (the Cedar windo...... manager),
Tioga (the Cedar editor),
the UserExec.
Cypress (the database system),
For each of these components, 'Ne give the DF file containing all of the
sources and references to .:)ther whiteboards with further information on the
interfaces the 'components provide,

"-=:::::::1"
.......
'.
"
Viewers
,
=>

=>

~=c=e=d=a=r==p=r=o=g=r=a=m==ln=t=e=r=f=a=c=e=s============~__~EJedar
Below, we give pointer to some of the major Cedar interfaces (again, more of
them can be found by perusing the release messages and the other information in
the Components whiteboard), The most frequently used Cedar interfaces include
IO and FileIO, Rope, and the various UserExec and Viewer interfaces (the
Viewer interfaces are described in the 'Viewer w·hiteboard), The InterfaceDoc DF
file gives more complete references,

EJD

Components

"~==:;"I""
a--

UserEseo:Utilities

Interfao:eDo

.Dr

::

::

""
"
"""
"
....._ _....,..-;.1""
"~==:;"1,'
a-"
Rope
"""
,press
"

.Ti.opes
A Rope is (nominally) an immutable I)bject containg a sequence of
characters indexed starting at 0 for Size characters, The representation

allows certain operations to be performed without copying all of the
characters at the expense of adding additional nodes to the object, (The
Rope documentation is a ,press file, so use the Tsetter to print it.)

""
""
""
...._ _....Ir.r.,I',"':

"
"-=~"
Rope
::
~

.mes.at

::

""
"
""
""
...._ _....Ir..-;
•• ::

WHITEBOARD
INSTRUCTIONS:
LEFT =) move entity
ctrl LEFT =) delete entity
MIDDLE =) open icon
shift MIDDLE =) expand icon
RIGHT => grow text box

Introduction to Cedar
Version 4.2
Release as
Came from

By
Last edited

[lndigo]lntroduction.tioga, .press
Jim Morris, Mark Brown, et a/.
By Scott McGregor on October 12, 1982 9:57 am
By Jim Horning on December 20, 1982 6: 12 pm
By Ed Taft on June 1, 1983 11:33 am
By Warren Teitelman on June 2,1983 11:18 am

Abstract: This memo is a sort of operators' manual for acquiring and using Cedar. It explains
the minimum you need to to know about most things, depending upon other documents for the
full story.
This memo is probably out of date if it is in hardcopy form. It is intended to document Release
4.2 of Cedar, June 1983, but some sections still reflect earlier releases.

[If you are reading this document on·line, try using the Tioga Levels and Lines menus
(if you can) to initially browse the top few levels of its structure before reading it

st raight th rough.]

XEROX

Xerox Corporation
Palo Alto Research Center
3333 Coyote Hill Road
Palo Alto, California 94304

DRAFT - For Internal Xerox Use Only - DRAFT

INTRODUCTION TO CEDAR

Introduction to Cedar: Contents
O. Introduction
1. The Cedar World

1.0 Credentials
1.1 Screen Management and Input
1.2 User Exec
1.3 Files
1.4 User Profile
1.5 Walnut
1.6 Maintain
l. 7 SeLting up your disk

1.8 General Failure Modes
2. Programming in Cedar

2.1 Running programs
2.2 System Models
2.3 BugBane and CoPilot
3. References

3. I General References
3.2 Cedar Language References

CEDAR 4.2

2

INTRODl:CTION TO CEDAR

3

o. Introduction
Cedar has a small. close-knit user community and it is changing very fast. Much useful information
is not written down or appears in informal messages. To learn about using the system you must take
some lessons from someone: get them to show you how to stan a D-machine, how to use the mouse,
etc. To work effectively you must keep in touch with what is going on. If you are using Cedar put your
name on the CedarUsers mailing list (See the section 1.6 for instructions on how to do it.) If you would
like to panicipate in or listen to design discussions. put your name on CedarDiscussion. If you are just
generally interested in what is going on try CedarInterest. Questions and bug reports should be sent to
CedarSupport-currently John Maxwell. Questions about a particular section this memo can be addressed
to the person(s) listed at the beginning of that section. Questions about specific packages and problems
should be addressed to the maintainers listed in the Catalog, with copies to CedarSupport: but, if you're
not sure whom to ask. the following people have a general knowledge of how to use the system: Atkinson.
Brown, Morris. Levin. Maxwell•. McGregor, Paxton. Rovner, Satterthwaite. Schmidt.
Typographical conventions employed herein:
Names of keys appear in capital letters in a small. alternate font; e.g.• SHIFT. ESC. RETURN
~is sometimes used for RETURN.
Things that are typed or displayed on the screen appear in an alternate font; e.g., compile faa
When we describe fancy interactions in which a system completes commands. what you actually
type is underlined; e.g., OthelloDorado.eb_

CEDAR 4.2

INTRODUCTION TO CEDAR

4

1. The Cedar World
To use Cedar you must first find a Dorado or Dolphin.
Cedar will usually be found in its idle state, displaying the words "Type Key" in the cursor. After
pressing a key on the keyboard. you will be asked to supply your name and password.
To awaken a slumbering Dorado press its boot button three times and wait for something to appear
on the screen (a minute or so).
To start Cedar on a wakened Dorado hold down the c (for Cedar) key and boot the machine by
pressing the boot button three times.
To tum on a Dolphin press the start button on its maintenance panel and wait for something to
appear on the screen (a couple of minutes).
To start Cedar on an awakened Dolphin hold down the P (for Pilot) key and boot the machine by
pressing the boot button once.
If Cedar is properly installed on the machine the cursor will tum into a cedar tree, and you will be
prompted for a name and password or just a password: if you don't know what to type, get help. If the
version number at the top of the screen is larger than 4.2, check for a newer version of this memo. If it
is smaller, get the new release using the instructions in section 1.7.2. If the screen says Othello ...• typing
Rollback or Boot Client may get you to Cedar. Otherwise. you have no Cedar world: consult section
1.7 on how to get your disk set up.
1.0 Credentials

Roy Levin

Cedar expects its user to be an individual registered with Grapevine. Whenever you enter the Cedar
world. you will be asked to supply your Grapevine RName and password Once you have been
authenticated. Cedar will remember your credentials until you either (1) push the boot button. (2) boot
a non-Cedar partition (e.g., an Alto partition). or (3) push the "Idle" button in the extreme upper right
comer of the screen. If you are not registered with Grapevine. contact your local support staff.
The precise fonn in which Cedar asks for your credentials depends upon the way in which the
credentials were originally installed. Public machines and some personal machines (at their owners'
option) have "unprotected" disks, meaning that Cedar will pennit any individual recognized by Grapevine
to log in. Other personal machines, however, have "protected" disks, meaning that Cedar will only allow
a specific individual to log in. To change from a protected disk to an unprotected one or vice versa, use
Othello's "Install Credentials" command
1.1 Screen Management and Input

Scott McGregor

The basis for screen management is the Viewer. In general. a viewer manifests itself as a rectangular
area on the screen. Some viewers simply display text. others are virtual buttons that invoke procedures
when clicked. We use the verb click to describe the acts of positioning the mouse-controlled cursor over
a viewer then depressing and releasing a mouse button. usually the left one. Middle click means to
depress the middle button. right click means to depress the right button. etc. In the past mouse buttons were
imagined to be red. yellow, and blue scanmng from left to right, so you will occasionally see that terminology.

Across the top of the screen is a small message area where various comments about the system's
status and behavior will appear. If the message is especially important. the message window will flash to
call the your attention to it. The large middle part of the screen is divided into two columns for displaying
tools and documents. Most tools and documents will initially appear as icon3-small pictures at the
bottom of the screen. You can open an icon to see its contents by middle clicking it; holding down the
SHIFT key while clicking makes it consume the whole column. Left clicking an icon selects it. making it
the recipient of type-in from the keyboard. Icon keyboard commands include:

CEDAR 4.2

INTRODUCTION TO CEDAR

5

Move the icon to the color display (assuming you have the hardware).
Delete the icon.
DEL
Move the icon to the left column.
L
M
Move the icon to another column.
o
Open the icon (like middle clicking).
SHIFT·Q
Open the icon full size (like SHIFT middle clicking).
R
Move the icon to the right column.
C

Open viewers display a menu of commands across the top when you move the cursor into the
caption (the black band at the top containing the name of the viewer). The commands are as follows:
Destroy
Make the viewer disappear.
Adjust
Change the size of the viewer or size of the column (see below).
Top
Move the viewer to the top of the column.
<..
Move the viewer to the left column.
.. )
Move the viewer to the right column.
Oose all other viewers in the column.
Grow
Make the viewer iconic.
Close
Middle clicking in the caption menu always invokes the Grow command. and Right clicking always
invokes Close. This allows you to invoke these frequently used operations without having to position
the mouse as accurately.
The height of a viewer in a column is computed from a set of hints. some determined by programs
and some indicated by the user. The program which created the viewer can specify a desired height
(such as in the EditTool and Watch viewers) or the program can request that the viewer receive a "fair
share" of the available space (as in Tioga text viewers). The user may override these program hints by
clicking the Adjust caption menu command. entering a mode where a new height hint may be specified
with the mouse. Moving the cursor out of the original column changes the mode to allow the user to
specify a new column height and width. At any time while in adjust mode. simultaneously depressing
two mouse buttons cancels the adjust command.
Some menu items and button will be displayed with a strikeout bar through the text These are
known as guarded commands, implying that command, if inadvertantly triggered, might cause -loss of
your current state. To invoke a guarded command click once to remove the guard and then again to
trigger (within a few seconds or the guard will reappear).
In order to type something into a viewer. you must first establish the input focus by clicking
somewhere inside it. (If the viewer is a typescript viewer. i.e. one in which you and the system alternately
insert characters, as opposed to a Tioga document, you should make sure that you click the mouse in
the white space below the last character.) Left clicking in a text area positions the blinking caret that
indicates where your typed characters will appear. A sequence of text characters may be selected by left
clicking the first character and right clicking the last: they will appear video reversed, i.e., white on black.
Those characters then become the current selection which various buttons (e.g., Open) treat as an input
parameter. Whatever you type replaces the current selection when it is video reversed. There are many
other things to learn about selection described in the Tioga manual [01]. Tioga is generally similar to
Laurel [02].
There are some buttons at the right end of the message area. You can boot any of your system
volumes (e.g., Alto. Client. Othello) by clicking Boot to bring up a set of guarded buttons. The New
button creates a new text viewer that you can type new text into; typing a file name followed by IF will
load a file into it. The Open button creates a new text viewer for the file named by the current selection.
Clicking Idle causes the screen to tum black and display a dancing "Type Key" cursor. This is the
preferred way of ending a session without actually leaving the Cedar world; various volatile structures

CEDAR 4.2

INTRODUCTION TO CEDAR

6

will be made secure on the disk. If you subsequently hit a key, you will be asked to login, after which
the screen will be restored to its state at the time that Idle was invoked. The Fly button will display a
set of nine desktops, anyone of which you can examine by left clicking. All of your icons are transferred
[0 the new desktop.
The checkpoint facility allows you to save the effect of a long set-up computation such as the one
that occurs after an installation of a release. Ann and click the Checkpoint button at the top of the
screen and wait for a while (about four minutes on a Dolphin). Don't worry that the cursor won't move
with the mouse. Then, whenever you start your Cedar world or click the Rollback button, you will find
yourself in this state. It is important to understand that rolling back only restores the state of the virtual
memory. It does not undo changes made to files or the directory. Thus you should create checkpoints
only when the system is in a quiescent state with no open files: otherwise, strange things might happen
after a rollback. If you want to overwrite a bcd (either by compiling or file transfer) that was loaded
prior to a checkpoint you should boot the Client volume and create a new checkpoint. Don't make
checkpoints on public Dorados unless you know how to restore the standard one when you are done.
1.2 User Exec

Warren Teitelman

Note: The following is summarized and extracted from the documentation of Cedar UserExec, [014],
which also appears as as a separate section of the Cedar Manual. For more complete discussion, and lots
of examples, refer to this documentation. which can also be found on your disk as the file UserExec.tioga.

General Comments
The Cedar executive is called the UserExec. It is an amalgam of the Alto Exec, a Cedar Language
interpreter, and a debugger-backed up by optional automatic error correction facilities similar to
InterLisp's DWIM. For example, the UserExec can be used to load and run bcds, list. copy, rename,
and delete files, evaluate Cedar Language expressions, catch breaks and signals, and display the state of
a process that has been stopped by a break or signal.
The user interacts with a particular UserExec (you can have several around. even executing, at the
same time) through a special viewer called a WorkArea. Each WorkArea has a name, typically a single
letter. which is displayed as part of its caption. Each WorkArea also has a mode, which is either Executive
or Interpreter, also displayed as part of its caption. To "talk" to a particular UserExec, simply establish
the input focus by clicking in the bottom portion of the corresponding viewer, and then start typing.
Since the WorkArea is a viewer, all of the viewer facilities are available for manipulating the
WorkArea (see section 1.1). In particular. it can be grown, adjusted, scrolled, moved, closed (the UserExec
will continue running andlor outputting characters. you just won't see them until you reopen the viewer),
opened, split. or even destroyed (which will abort any operation that is executing the next time it tries
to do input or output). Furthennore, since the viewer views a Tioga typescript, all of the Tioga editing
and selection mechanisms can be used with respect to the command line that you are composing: you
can edit this line to your hearts content. and when you terminate the command, it will look exactly like
you typed in the edited line.
New UserExecs and their corresponding WorkAreas can be created via the New menu button which
appears in the first line of each UserExec menu. This works even when a particular WorkArea seems to
have "died". Existing UserExecs can be destroyed via the Destroy Viewer menu button. !f.1ou destroy
your only Work Area, an Exec button is posted at the top of the screen which you can use to create new
WorkAreas.

Events

CEDAR 4.2

11'iTRODL'CTION TO CEDAR

7

Each user interaction with a UserExec is called an event. At the start of each event. the user is
prompted by & followed by the event number. The user then types in a command line consisting of the
name of a registered command. followed by its arguments. if any. and terminated by l. ? CTRL·X. or
ESC. The UserExec then performs the indicated operation. prints the result. and prompts the user for
the next event Typing DEL during the input of a command will abort the input. causing you to be
reprompted. Clicking the Stop menu button (or typing CTRL·DEL) during the exeuction of an event will
cause it to abort the current operation (but sometimes it takes a little while).
Terminating a command line with? signifies a request for additional information. Specifically. ? by
itself prints a list of commands currently registered. ? after a registered command prints a description of
the command, and? after a Cedar expression prints the type of (the value of) the expression. For
example:
&4 walnut?
Walnut
Creates a viewer for sending or retrieving mail.
&5

~

3.2?

is of type REAL
&6 ~ Rope.Cat?
is of type PROC [r1, r2, r3, r4, r5, r6: ROPE ~ NIL] RETURNS [ROPE];
- returns the concatenation of up to six ropes (limit based on eval stack depth)
- BoundsFault occurs if the result gets too large
Terminating a command with CTRL·X means to "expand" the command, but not to execute it. Le.
e.g. perform * expansion. Terminating a command with ESC means to "complete" the command, as far
as possible. but not to execute it.

Registered Commands
The following are some of the more useful registered commands. More commands can be discovered
through the use of?
@
takes a file name as argument Treat the contents of the named file as a command file. i.e.
interpret the text as a sequence of commands. If {file} has no extension. look for a file of
the form {file}.commands or {file}.cm.
~
Treat the remainder of the input line as a mesa expression to be evaluated. Evaluate the
expression and print its value. If the expression is terminated with ? print the type of its
value. rather than the value. If the expression is terminated with !. print the value showing
the referents of all REFs and POINTERs to an unlimited depth.
Note: many users prefer to do interpretation of expressions in Interpreter WorkAreas or Action
WorkAreas (see below). in which case the ~ is automatically provided at the beginning of each
command line. and to use Executive WorkAreas for "executive" type of operations such as running
programs and manipulating files.
Bind Bind a list of configurations. See discussion of Compile menu button below.
Bringover
Retrieve files using a specified df file (see 1.3.2)
ChangeAreaMode
change an Executive WorkArea to an Interpreter WorkArea and
vice versa.
Compile
Compile a list of modules.
Copy
Copy contents of one or more files to another. Syntax is Copy new ~ 0ld1
0ld2 ... oldn.
Date
Type today's date and time.
Delete
Delete a list of files.
Fetch Copies remote file(s) to corresponding local file(s).

CEDAR 4.2

INTRODUCTION TO CEDAR

8

Help
List
List By Dates
Login
Rename
Run
SModel
TSetter
documents

Provide more complete explanation of UserExec in a separate viewer.
Print size and creation date for the indicated files.
Print size and creation date for the indicated files, sorted by create date.
Supply user name and password.
Rename a file. Syntax is Rename new ... old.
Load and Start the named programs.
Store files on remote servers using a specified df file. (see seetion 1.3.2)
Create a typesetter viewer for specified server, and use it to print named

User

Type the name of the logged-in user.
For sending or retrieving mail.

Walnut

For convenience, a number of commonly used registered commands can also be invoked via menu
buttons that appear in the first line of the menu of each WorkArea. If it isn't obvious what these menu
buttons do, consult [014].
Interpreter WorkAreas

When typing to an Interpreter WorkArea. the user is always prompted with ann ... , where nn is the
event number. What the user types following the ... is treated as an expression to be evaluated in the
current context and default global context, if any, for the WorkArea. The value of the expression will be
assigned to the variable whose name precedes the .... i.e. ann. This value can be referenced in later
expressions. As mentioned earlier, if? is typed following an expression, the type of the expression, plus
other explanatory infonnation, is printed.
The following is taken from an actual session with an Interpreter WorkArea. The italicized text at
the right is added commentary not printed by UserExec.
&2 ... Rope.Cat["Ce", "dar"lJ. Note that Rope is the interface. not the implementation.
"Cedar"
&3 ... LlST[l, 3.2, &lJ.
(tl, t3.2, "Cedar")
&4 ... &31

is of type LORA: TYPE

& evaluates to the previous result (&2 in this case.)

What type of list did the interpreter produce?

= LIST OF REF ANY

&5 ... &3.firstt?
is of type INT
&6 ... &3.resUirstt?
is of type REAL
&7 ... ListJ.
default global context changed to: Listlmpl

{global Frame: Listlmpl}
&8 ... Appendd[Reverse[&3],&31h
Appendd .} Append? Yes
("Cedar", t3.2, tl, tl, f3.2, "Cedar")

Note that Reverse is now interpreted as List.Reverse.
Spelling correction.

For more detailed information about exactly what subset of Cedar language expressions the interpreter
can handle see section 2.3.
Action WorkAreas

CEDAR 4.2

[NTRODL'CfION TO CEDAR

9

Actions occur when a program raises a signal or error that is not caught or encounters a breakpoint.
Whenever an action occurs. the corresponding process is stopped so that it can be examined. and control
transfers to a different WorkArea called an Action WorkArea. or ActionArea for short. An ActionArea
is an Interpreter WorkArea whose default context is the context of the action. The user can then walk
the stack and evaluate expressions. The user can also choose to ignore the action for the time being and
type some other command in a different WorkArea. If the user does not wish to pursue the cause of the
action at all. the simplest way to make it "go away" is to click Abort. For complete discussion of Action
Areas and ActionArea Commands. see [014].
Using the History facility

Each WorkArea has associated with it a history of all of the events that have taken place in that
WorkArea. The user can examine this history via the History registered command. reexecute a particular
event or events using the Redo command. or substitute new parameters (text strings) into a particular
event or events and then reexecute them via the Use command.
Confinnalion

Occasionally the UserExec will attempt to correct an error: e.g. a misspelled file name, an invalid
selector. syntax error, etc. In this situation. two new menu buttons, Yes and No, will be posted in the
menu for the corresponding WorkArea. Depending on the settings in the user's profile (see UserProfile.doc),
some errors will be corrected automatically, but in other cases, confirmation will be requested. When/if
the user is asked to confirm (depending on the settings in the user's profile. some errors may be corrected automatically),
the user can confirm using these buttons. or by typing Y or N. If the user has typed ahead before the
need for confirmation was detected. the typeahead will be retained. and the user must confirm using the
Yes and No buttons.

1.3 Files
All of the material you are working on, including programs, is stored in files. Each different document
you handle will be stored on its own file. The file system is somewhat complicated by the fact that it
spans a network and developed in an evolutionary fashion.
1.3.1 Local and Remote Files

Ed Taft

A file on your local disk is identified by its name. which is a string of letters (upper and lower case
can be used interchangeably), digits, and any of the punctuation characters + - . $. By convention. a
simple file name has two parts. which are called the main name and the extension: they are separated by
a period. For example. "Introduction.tioga" is a file name, with main name "Introduction" and extension
"tioga". File names cannot include blanks, or any punctuation characters except the ones just mentioned.
It is important to name your files in some systematic way. using the main name to identify it, and
the extension to tell what kind of file it is. Unless there is a good reason to do otherwise, it is best to
use one of the standard extensions given below.
Here is a list of extensions commonly encountered:
.bcd
Cedar object program
.config
system configuration. input to binder
.em
command file for the User Exec or other programs
.doc
Tioga document (old convention)
.df
list of dated files for use in moving files between machines
.mesa
Cedar or Mesa source code

CEDAR 4.2

I NTRO DuCfION TO CEDAR

.model
.press
.tioga

10

system model
Press-format file, suitable for printing
Tioga document

The system doesn't care whether you capitalize letters in file names or not (Le., ALPHA, alpha. and
aLpHa refer to the same file), but it is a good idea to use capitalization to make names more readable.
This is especially useful when a name consists of more than one word, since blanks are not allowed in
file names: e.g., TripReport or MasterList A file name with the form X$ is taken to be an older, backup
version of X. Many subsystems will save the previous version under such a name.

File servers are large repositories for files. A file server's disk typically has hundreds of times the
capacity of your local disk. Besides providing back-up for your local disk, they are the only reasonable
places to put files you wish others to see or want to access yourself from different machines. The only
reasonable way to do business is to keep your personal files backed up on a remote server. You should
not rest easily unless the latest versions of all your important files are on a remote server somewhere.
In general, the name of file in network has the form
[Server]SubOirectories)name.extension !version
This form is sometimes called the foil path name. The server is the name of the machine. Indigo,
Ivy, and MAXC are the local servers; the first two are instances of IPS-the interim file system. The
directory is the name of a project or person. Each user who has an account on a file server has his own
directory, named by his user name. Files within a directory may be organized into sub-directories (except
on MAXc). For example. the file named
init>
Initdf

AltoSuppon.cm

CEDAR 4.2

[NTRODliCTION TO CEDAR

11

Cedar. em
DO. em
DORelease2.5.1.cm
Dorado.em
DoradoRelease2.5.1.em
RunPilot.bcd
Directory [indigoj
[nitdf
22-Mar-82 9:47:24 PST
AltoSupport.em!1
18-Mar-82 14:57:23 PST
Cedar.em!1
22-Mar-82
10:38:37 PST
DO.em!2
22-Mar-82
10:55:02
PST
DORelease25.1.cm!3
22-Mar-82
12:33:35
PST
Dorado.em!3
22-Mar-82 10:11:30 PST
DoradoRelease2.5.1.cm!l
2-Feb-82 23:37:34 PST
RunPilot.bcd! 1
Directory [indigoj.

1.3.3 The File Tool

Larry Stewan

The File Tool-its iconic form looks like a file cabinet-is used for listing files on various machines
and transferring them. Its topmost section provides various fields for you to type in things and a few
mode buttons; click the field name and the cursor will move to its entry. The * notation can be used in
the first three fields to designate groups of files.
Directory designates a remote server and subdirectories; e.g., [Indigo]. The * notation
can be used to designate multiple places.

CEDAR 4.2

I
I

INTRODUCTION TO CEDAR

12

Filename(s) is a sequence of files to be transferred or listed; subdirectories may be included; e.g.,
Docs)Intro.press. Remote file names are derived by concatenating Directory with these names.
The * notation can be used to designate multiple files. Entering @X will cause the contents
of file X to be used.
Local refers to local file names. It can be used if you wish to rename a single file as it is being
transferred. On a retrieve it names the destination file; on a store it names the source. The *
notation can be used to designate mUltiple files. Entering @X will cause the contents of file
X to be used.
OF File is the name of a DF file that fetch may be done through. See DFGet.
Connect Name and Password are needed for access to certain directories. You may omit the
password when connecting to a directory belonging to a project of which you are a member.
Update is a button that sets the mode of operation so that a file will be moved only if a version of
it already exists at the destination and has an earlier create date than the file to be moved.
Update)a does the same thing except the file will be moved even if it doesn't exist at the destination:
most people prefer it.
ExportsOnly applies to fetches done through DF files.
Verify sets the mode so that you must confirm each transfer by clicking buttons that will be presented
. to you in the middle s~tion
The second section holds a set of buttons that represent commands.
Retrieve fetches the remote files given by the combination of Directory and Filename(s). If no
focal name is given the short form of the remote one is used.
Store moves files to a remote machine. If no Local entry is present it uses the Filename(s).
Local·List displays information about the local files.
Remote·List displays information (version, size, creation time) about the remote file.
List~Options brings up a set of buttons that change the things printed out by the List commands.
Apply causes the new settings to take effect; Abort resets to the old settings.
Close shuts down the remote connection
DFGet retrieves the files listed in Filename(s) using a DF file to discover their full path names.
Directory is prepended to OF File to define the full path name of the DF file itself.
DFGetBoth is the same as DFGet but fetches the .mesa and .bcd for each name listed in Filename(s).
Local·Delete deletes the local files: it must be armed. Warning: Unlike certain systems, once you
have deleted a file, you cannot get it back. Proceed with caution.
Remote·Delete deletes the remote file: it must be armed.
The third section is an output typescript. The Stop button in the top-most menu can be used to
abort transfers and lists in an orderly way.

1.3.4 Chat and File Space Management

Larry Stewart. Ed Taft

Sooner or latter you will run out of disk space on your IFS or MAXC directory. File space management
activities not supported by the File Tool or DF files can be carried out by connecting to a file server
with Chat Chat uses a viewer to simulate a teletype computer terminal, and thereby enables you to talk
directly to executive programs running in various server machines.
To initiate a conversation with the executive in a server type Chat server ·1 to the User Exec. If all
goes well, you will see. a message from the server's executive and @ at the left margin prompting you
for type-in. If Chat has trouble getting connected, it will tell you its problem after trying for a few
seconds. This usually means that the server is broken: you might try again in a few minutes. To redirect
an existing Chat viewer to a sever type the server name into a window, select the name, and click Login.
If you click Connect rather than Login, you can login by hand: type

CEDAR 4.2

13

INTRODUCTION TO CEDAR

@Login (user) name (password) password
Whatever the server executive is doing, you can force it to stop by typing
may have to type CTRL-C several times in quick succession to get it to stop.

CTRL-C.

On

MAXC,

you

When you are finished talking to the server Executive, type
@Logout
(or Oult if the server is an [FS), Then click Disconnect. If the file server is an IFS, you will be
logged out automatically if you don't type anything for three minutes. This is because IFS can service
only a small number of users (currently nine) at once; the automatic logout is .intended to prevent IFS
from being tied up by users who aren't doing anything useful. Simply closing a chat viewer does not
shut down the connection unless you right click the Close button.
You type commands to IFS and to MAXC in more-or-less the same way (except for those commands
that have different names on the two systems); however, the responses from IFS and M:AXC are usually
somewhat different You may type? at any point to obtain a brief explanation of what you are expected
to type in next. MAXC normally does not display the remainder of abbreviated commands; however, you
can force it to do so by terminating fields you type in with ESC rather than space.
To' delete all old versions of files (Le., all but the highest-numbered version of each me), on IFS
type
@Delete *,
@@Keep (# of versions) 1
@@Confirm (all deletes automatically)
@@on

MAXC

type

@Delver
Delete oldest? Yes
Delete 2nd newest? Yes
File(s):_
It is a good idea to do this fairly frequently, since old versions of files can pile up and waste a lot
of space. To find out how much space you are using on the file server, type
@DskStat
One IFS or MAxc page is equivalent to about four D-machine pages. You will notice that you also
have a disk limit which is the maximum number of pages you are permitted to use on the file server at
one time. If you exceed your disk limit the server won't let you store any more files until you first delete
some existing ones to get you below your disk limit. To get your limit changed. consult your local suppon
staff.
You can direct your attention to some other directory by typing
@Connect (to directory) OtherDir (password) password
You may omit the password when connecting back to your own directory, or when connecting to a
directory belonging to a project of which you are a member.
MAXC provides facilities for archiving files onto magnetic tape, where the cost of storing them is
negligible. You can get an archived file back within one day ..T0 archive one or several mes, type

@Archive File file1 file2 .. ,
(Note that the command name consists of the two words "Archive File"; after that you should type
the names of the files you want to archive.) The files will be archived onto tape within a day or two.

CEDAR 4.2

INTRODUCTION TO CEDAR

14

After this has been done, they will be deleted from the disk automatically, and you will get a message
notifying you that the archiving has been done.
MAXC keeps track of your archived files in an archive directory which you can list exactly like your
regular MAXC directory, using the Interrogate command rather than the Directory command; for example,
@ Interrogate • .bravo

If the listing is of just one file, MAXC will ask you whether or not you want it retrieved from the
tape. If you say Yes, the file will appear on your MAXC directory within a day, and you will get a
message to that effect
Because MAXC'S disk capacity is fairly small relative to the number of users who have MAXC
accounts, the disk occasionally becomes full and it becomes necessary for a forced archive to be performed
in order to make some space available. In a forced archive, all files that haven't been referenced (retrieved.
printed, or whatever) in the past 90 days are written onto tape and deleted. You will be notified when
any of your files are archived for this reason, and the procedure for getting them back is the same as
given above.
1.4 User Profile

Warren Teitelman

A number of components of Cedar permit the user to tailor Cedar's behavior along certain predefined
dimensions via a mechanism called the user profile. Whenever you boot or rollback, your user profile is
consulted to obtain the value for these parameters. This operation is performed by consulting a file whose
name is HowToUseWalnut.press; a copy of this documentation appears as a later
chapter of this manual.
1.6 Maintain

Andrew Birrell

Various administrative tasks associated with mail. authentication and other uses of Grapevine can
be performed with the Maintain command. Bringover and RunAndCall Maintain. Its interface is layered
according to the complexity of the operations various people need to perform. Many users will need
only the level called "normal". This allows you to inspect distribution lists, add or remove yourself from
lists. and change your password. When using Maintain, you must always specify names in full. Thus,
you must say "CSLt.pa", not "CSLt". and "Birrell.pa", not "Birrell",
To look at a distribution list (a "group" in Grapevine terminology), fill in the text field labelled
"Group" and click the "Members" button in the first line labelled "Type". The "Summary" button in
that line will show you the access controls associated with that group (which control who may add or

CEDAR

4.2

15

INTRODUCTION TO CEDAR

remove members). To add yourself to a group, fill in the "Group" field and click "Self' in the line
labelled "Add". Similarly, you can remove yourself with the line labelled "Remove". Not all groups
allow you to add or remove yourself. If you're not allowed to change the group, you should send a
message to the owner of the group asking for the change. For example, you would send a message to
"Owner-CSLt.pa" to ask about "CSLt.pa".
For the sake of security, it is a good idea to change your password occasionally (say, once a year).
To do this. make sure your name is in the text field labelled "Individual". fill in your new password in
the line below, labelled "Argument", then click "Password" in the line labelled "Set". Passwords should
be at least six characters and unpronouncable. If you have an account on MAXC you will need to change
the password there via Chat. type
@Change Password (of directory) name (old password) xxx (new password) yyy

1.7 Setting up your disk

Eric Schmidt, Ed Tart

1.7.1 Gelling to Othello

Othello is a general Pilot utility for setting up disks. There are variety of paths to Othello. On an
arbitrary machine in an arbitrary state hold down as. RETURN. and while booting (on a Dorado, push
the boot button three times in quick succession). This places you in the Network Executive. The type-in
conventions are simple: ? lists the possible commands, as backspaces, DEL cancels the current line. To
start up a program from the NetExec. simply type the name of that program followed by RETURN or
ESC. In fact, you need only type enough of the name to distinguish it from all the others: we shall
underline only that portion your need to type before the RETURN. You are currently on your way to
Othello: type
I

)MesaNetExec

placing you in the Mesa Network Executive which has similar typing conventions. From there type
)OthelioDorado.pb_

or
)OthelloDO.pb _

(For historical reasons Dolphins are sometimes called OO's.)

depending upon whether you are using a Dorado or Dolphin. If you are in the Cedar world already,
you can simply boot Othello with the Boot button at the top of the screen.
When Othello starts. it will ask you to log in. You must supply your Grapevine registered name and
correct password before Othello will permit you to do anything else.
Now that you are in Othello you can use the standard command files described below for initializing
disks, and getting releases. If you want to do non-standard things with Othello see section 4.8 of [05].
Here are a few fine points about starting Othello:
When starting with a new disk which you plan to erase and format. you should say
)Switches: n

to the Mesa Network Executive before starting Othello. This prevents Othello from attempting to
put the existing file system on-line when it starts up. It also permits you to log in as yourself even if
someone else's credentials are installed on the disk; however, all Othello will allow you to do is to erase
the disk-you cannot examine the existing contents of someone else's disk by this means.
On a Dolphin, if you ever want to boot your Cedar system from Othello rather than the boot button.
you must call for the Cedar microcode by typing

CEDAR 4.2

INTRODUCTION TO CEDAR

16

>~tVersions for germ and microcode
Germ: OO.eg_
Microcode: CedarOO.eb

to the Mesa Network Executive before starting Othello.
1.7.2 Getting a New Release

The next section describes how to start with a brand new, unformatted disk. This section assumes
you already have a Cedar world set up, are happy ,with the distribution of space among your volumes,
but would like to upgrade your system to the latest release. (If you want to change the volume structure
read pp. 40-41 of [G5].) If you have just set up your disk, there is no need to perform these operations.
First. you should perform some disk clean-up. There are two possible levels of clean-up: deleting
all the old BCDs and symbols files or erasing the volumes. You should at least do the former if there is
any chance that the new release introduces new versions of things. No end of confusion will result if old
versions of BCD files get mixed in with the new things. Erasing a volume takes longer and requires that
you evacuate and recover personal files, but it promotes compact files, clean directory structures, and
other healthful things. The utility DFDisk [G3] is useful" in figuring out what you need to save. To erase
your Cedar Client volume, get into Othello and type
>Erase
Logical Volume Name: Client
Are you sure? [y or n): 'i

Whether or not you erase, you can get latest release's boot files by typing
>@
Command file: [lndigo]top>OoradoRelease.cm

or
Command file: [Indigo)top>OORelease.cm

New microcode, germ, and boot files will be fetched. On a Dolphin you will be put back into the
Alto world; boot while holding down P. On a Dorado you will be put directly into the Cedar world.
Getting a new release takes under two minutes. so only the most impatient people will want shortcuts
for updating a single item like the microcode. They should read the command file to see how to do it.
1.7.3 Initializing a Disk
You should only do this step on your personal disk or machine: don't do this to a public machine's
disk! This initial setup should work no matter whether your disk is blank, smashed. or already contains
a working version of Cedar. Besides taking time. this initial setting up discards the record of bad pages
each disk has. so you do not want to reformat your disk gratuitously. If you have a functioning Cedar
worm. and just want to get'a new release or clean up your disk. go back to subsection 1.7.2.

To initialize a Dorado that has a new, unformatted disk. type to Othello
>@
Command file: [Indigo ]top>FormatNewPrivateOorado4.cm

It is assumed that you haye an Alto world on .partition 5 of your disk. This command file will take
the other four partitions of the Dorado's disk (1. 2. 3. and 4} and create four Pilot logical volumes: the
Client volume for Cedar. the Debugger volume for CoCedar. the Othello volume for general utility, and
the Booter volume for checkpoints. When the cedar tree cursor appears. go back to section 1.0.

CEDAR 4.2

INTRODUCTION TO CEDAR

17

If for some reason. you want to recreate standard logical volumes on a disk that has already been
formatted with panitions 1. 2. 3. and 4 dedicated to Cedar. use the command file
[Lndigo]Top>MakeDoradoDisk4.cm.
This
command
file
is
identical
to
FormatNewPrivateDorado4.cm except that the physical volume is not reformatted and your list of bad
disk pages is kept.
For Dolphin users. some ground rules:
(1) Your Dolphin should have 768K words of real memory. indicated by 3072 appearing on the
maintenance panel while you are in the Alto world. The hardware maintenance staff will add
memory to your Dolphin upon request. Make sure you have the latest memory controller
upgrade. too.
(2) You should dedicate 3/4 of your disk space to Cedar/Pilot. This assumes that you are using
your Alto panition for just Bravo. SIL. and other nostalgia items. If you don't now have a
small Alto disk partition. here is how to conven: FTP all personal files from your disk to
some safe place. like a file server; Copy Disk from [Indigo]Mesa6-14.bfs to BFSl;
finally. FTP your personal files back.
To initialize a Dolphin Cedar world. type to Othello:
>@

Command file: [lndigo]top>FormatNewPrivateDO.cm
After about fifteen minutes. you should have an initialized Dolphin with 3/4 of its disk space
dedicated to Cedar. You will have three volumes on your machine: the Client volume for Cedar programs.
the Othello volume for general utility. and the Sooter volume for checkpoints. Note that there is no
Debugger on your disk. Use Bug Bane for common bugs and teledebugging for cases Bug Bane can't
handle. A person with a Dorado will be happy to help you teledebug.
P,

After all this you will find yourself back in the Alto world. Boot the machine while holding down
and you should be in the Cedar world. looking at the cedar tree. Go and read section 1.0.

If for some reason. you want to recreate standard logical volumes on a disk that has already been
formatted with 3/4 of the disk dedicated to Cedar. use the command file
[lndigo]Top>MakeDODisk.cm. This command file is identical to FormatNewPrivateDO.cm
except that the physical volume is not reformatted and your list of bad disk pages is kept.
If you want to devote your entire Dorado disk to Cedar (and eliminate the Alto panition entirely)
then use the command file [lndigo]top>FormatNewPrivateDorado5.cm. This will destroy
everything already on the disk. so be sure you !:lave saved anything that you want preserved.
If you wish to configure your disk in other than the standard way (e.g., to use all of a disk for Cedar
on a Dolphin). consult a wizard.
1.7.4 Other Othello commands

If you find that you use Othello a lot. you may want to set things up so that the default action upon
booting the machine is to stan Othello rather than to boot or roll back your Cedar Qient world. This
enables you to get to Othello directly rather than via the long excursion through the MesaNetExec. The
procedure for setting things up this way is:
>Set Physical volume boot files
Logical volume name: Othello
Set physical volume boot file from this logical volume? Yes
Set physical volume pilot microcode from this logical vOiume? Yes
Set physical volume germ from this logical volume? Yes
Are you sure? res
-

CEDAR 4.2

INTRODUCTION TO CEDAR

18

>Set Debugger pointers
for debuggee logical volume: Othello
for debugger logical volume: Debugger
Are you sure? 'yes
From Othello, you can roll back your Client world by saying "RollBack Client"; you can boot your
Client world by saying "Boot Client" followed by two CRs; and you can go directly to the debugger
either by typing CTRL-SWAT (the SWAT key is the unmarked one'next to the right SHIFT key) or by saying
"Boot Debugger" and specifying switches of "w".

1.8 General Failure Modes
You may have the misfonune to encounter a bug in the Cedar system that causes it to crash. There
are various ways to recover from crashes.
If you seem to be stuck and the maintenance panel lights (on a Dorado they actually appear on the
screen) say:
910: This is displayed while booting or world-swapping and does not indicate a failure.
9l2: Version mismatch between the genn and boot file. Consult an expen.
9l5: Cedar tried to transfer control to a world-swap debugger, but there isn't one on your local
disk. See section 2.3.
920: This is displayed while booting or world-swapping and does not indicate a failure.
921: An unrecoverable disk error occurred while booting or world-swapping. Try again; but if the
problem persists you may need to rebuild your file system.
922: An Etherboot of Othello or some other program timed out; try again.
923: Something about your germ or boot file is wrong. try getting a new release of Cedar (per
section 1.7.3)
933: Something about your machine has changed since the Cedar checkpoint andlor Debugger
image was installed on the disk. Most likely either the disk pack was moved to another
machine or the machine's Ethernet address was changed. Boot the Debugger, boot the Client,
and remake the checkpoint
937: Unable to get the time from the Ethernet. most likely due to Ethernet or time server failure.
but possibly due to a hardware problem in your machine. If repeated failures occur, consult
a Wizard.
957: This is a symptom of a hardware problem on Dolphins. Notify the hardware maintainers.
960: Wait for a while. possibly even 20 minutes. Your disk is being garbage-collected. Be patient;
booting merely stans the process over again.
Anything less than 900 typically indicates a microcode or hardware problem. Maintenance panel
codes less than 900 usually occur only on Dolphins. See [06] for a list of Dolphin maintenance panel
codes. On a Dorado. a hardware or microcode-detected error usually halts the machine; the usual
manifestation is that the screen turns completely black or gray with diagonal stripes. Maintenance panel
codes above 900 but not in the above list are usually but not always due to hardware problems also.
If the maintenance panel says 990 (or, on a Dorado. no numbers are visible), but there is no response
to keyboard or mouse input. you need to get control somehow. In general, there are several levels of
fall-back to try. Starting from the least drastic:
O. 00 to a world-swap debugger by typing CTRL·SWAT; the SWAT key is the unmarked one next to
the right SHIFT key. You can look around and then resume without losing anything. If your
machine doesn't have a world-swap debugger installed. this may produce a maintenance panel
code of 915, as described above.
1. Type CTRL·LEFTSHIFT-SWAT to get to a world-swap debugger "delicately". As with the previous

CEDAR 4.2

INTRODUCTION TO CEDAR

19

step. this can produce a maintenance panel code of 915.
2. Click a Stop button or type CTRL·DEL in a viewer. This will sometimes stop a run-away program
and get the system behind the viewer to listen.
3. Perform a rollback (or boot if no checkpoint file exists) using either the Rollback button or the
physical boot button. This loses whatever is in virtual memory and open files.
4a. On Dorados. boot by a three button boot. holding down C. This fetches new microcode from
the net.
4b. On Dolphins. press the start button on the maintenance panel and then perform step 2. The
main difference between a keyboard boot and a maintenance panel boot is that the former
requires the disk to be spun up and the machine already to be in a fairly good state. whereas
the latter will start the machine from an arbitrary state.
If the above methods fail to get your Cedar World up. there are problems with your file system.
5. There are various scavenging procedures available under Othello. described in [OS]: Check Drive.
Scavenge. Physical Volume Scavenge. and DEScavenger. Oet an expert to help you with
these. These might recover the situation without much information loss.
6. Erase your client volume and get a new release. losing all non-backed up files. See section 1.7.3.
7. Initialize your disk and get a new release. See section 1.7.2.

CEDAR ~.2

[NTRODUCTION TO CEDAR

20

2. Programming in Cedar
2.1 Running programs
You might try running the following example program:
-- Test.mesa. last modified by Jim Morris July 8, 1982 12:31 pm
DIRECTORY
10 USING [GetInt, PutF, CreateViewerStreams, int, STREAM].
UserExec USING [CommandProc, RegisterCommand]
Test: CEDAR PROGRAM IMPORTS 10, UserExec = BEGIN
in, out: 10.STREAM:
Compute: UserExec.CommandProc = BEGIN
i, j: INT:
out.PutF["Type me a couple of numbers: ");
i +- in.GetInt(]:
j +- in.GetInt(];
out.PutF["The sum of %g and %g is %g.\n", IO.int[ij. IO.intU]. IO.int[i+m:
END;
[in, out) +- 10.CreateViewerStreams{"Compute.Log"):
UserExec.RegisterCommand["Compute", Compute):
END.
To create this file click New, copy this text into the new file. and store the file as test.mesa (using
the Files sub-menu). You then compile and run it with the following interaction:
&1 compile-test
Loading Compiler.bcd .. .
Compiling: test ...... no errors
End of compilation
&2 Run test
&3 Compute
Now click anywhere inside the new viewer named Compute.Log, and type in two numbers, followed
by a

RETURN.

2.2 System Models

Eric: Scbmidt, Ed Sattertbwaite

As soon as you start dealing with a system of programs you should consider using a system model
to describe I and control them [G7). There are two benefits: the modeller will figure out what you need
to, re-compile automatically, and it will replace modules in a running system so that you needn't always
restart your program after fixing a bug. The following is a trivial system model whose only component
is the test program from above.
-- Trivial.Model, 24-Jun-82 17:53:12 PDT
OPEN @BasicCedar.model:
Trivial: PROC [IOlmpl: [a,
UserExecImpl: UserExec,
Ropelmpl: Rope] RETL'RNS [] [
Bringover: TYPE = = @Bringover.bcd:
Main: COr-.lROL = = @Test.Mesa

.- detour to avoid parser bug

CEDAR 42

INTRODUCTION TO CEDAR

21

The parameters of the procedure Trivial are implementations for the three interfaces 10, UserExec,
and Rope. Those interfaces are types declared in the file BasicCedar.model. When you run this model
the implementations will be supplied from already loaded programs.
To start the modeller type
run model

This will bring up the Modeller viewer. Type trivial in for ModelName and click StartModel to tell
the modeller to read in and analyze the model. A series of messages to appear in the modeller's lower
window, concluding with a line of dashes. Click Begin to start the program. This might cause Test.mesa
to be compiled; you must give it permission to compile (remember to click inside the viewer first) by
typing Y. The program will be loaded, the Compute.Log viewer will appear, and the command Compute
can be invoked from the User Exec. as before.
To change the program to behave differently edit Test.mesa to change the "+" to a "." and "sum"
to "difference". Save the file and click Continue in the Modeller menu. This will cause Test.mesa to be
recompiled and reloaded. Invoke "Compute" from the User Exec again and try the new program. The
modeller may be shut down in an orderly way by clicking StopModel.
Currently, Bug Bane (see 2.3) may get confused about which version of the module you are talking
about. You should use the ResetCache button after each module replacement.

2.3 BugBane

Russ Atkinson

BugBane provides the Cedar debugging facilities, which include a basic interpreter, primitives for
controlling programs by setting breakpoints. proceeding from breakpoints. and other such services. These
facilities are available to the user through the UserExec as described in section 1.2.

Interpreter
The interpreter has access to all names defined in the global frames of loaded programs (including
types) plus all names in a special name space local to the interpreter. These special names all begin with

&.
The interpreter handles a subset of Cedar expressions. The following summary of the subset language
is from the Bug Bane documentation [08]:
constants
. fixed, REAL, ~ope.ROPE, CHAR, BOOL, enumerated
simple variables
evaluated according to search rules below
x.y
x is a RECORD. REF or POll'!iER TO RECORD, global frame
x[y]
x is a SEQUENCE or ARRAY, REF or POINTER TO SEQUENCE or ARRAY
p(args]
P is a PROCEDURE taking given arguments
RT[args]
a RECORD constructor where RT is a RECORD type
LIST[exprs]
evaluates a list of expressions, producing a LIST OF REF ANY
X ~ Y
X and Yare expressions
The interpreter handles expressions containing arithmetic and logical operators (such as + and OR),
and conditional expressions (IF but not SELECT.) Sometimes it is necessary to write parentheses around
an expression to prevent the interpreter from getting confused. In general. you must prefix a procedure
name with the name of its interface or implementation module: e.g., Rope.Cat. However, if you evaluate
an unadorned interface or implementation module name, e.g.. List, unprefixed names on later lines are
interpreted relative to that module.

CEDAR 4.2

I

INTRODUCTION TO CEDAR

22

In looking up a name, the interpreter
Checks to see if the name begins with &: and if so it binds to the named &-variable.
Otherwise, it searches the global default context. if any. The global default context can be set by
interpreting an unadorned module as described above. or via the UserExec command
SetContext.
Otherwise. it searches the current local context, if any. The local context is the sequence of local
frames and associated global frames in the call stack of the stopped process. See discussion
of Action Areas under section 1.2.
'
If this fails. it searches the space of all interface names exported by loaded program modules. If
multiple instances of the same program module have been loaded. only the most recent one
will be seen. Also. the association of interfaces and programs works most of the time. but
may fail.
[f this fails. it tries to match the name with the name of a loaded program module (subject to the
three restrictions just mentioned). This search will not find individual components such as
variables contained in these global frames: such components must be qualified by the module
name.
Since the name lookup process can take a long time. it runs for only a certain time. and then says
that the name is undefined. If you know that a name in question would be found if it searched further.
you should follow the name with !. This will cause the lookup process to try with all its might and all
your time. However. you can always tell the lookup process to stop by typing CTRL·DEL or by clicking
the Stop button in the Work Area menu.

CoPilot
CoPilot is the backstop debugger for Cedar. See [05] for a complete description. [n the very near
future. CoPilot will go away and be replaced by remote debugging in which the debugger is a full Cedar
system. If you find yourself in a situation which seems to require knowledge of CoPilot. you probably
should find a wizard.

CEDAR 4.2

INTRODUCTION TO CEDAR

23

3. References
In general, the following directories are worth browsing:
[Indigo]Documentation>* is the general repository for documentation.
[Indigo]Top>*.df will list pointers to things in the release
[Indigo]* for Pilot stuff. There is a list mapping short file names to path names on
Documentation>APilotFiles.txt
. '
[Indigo]Documentation>Cedar3.sXref.press, .txt is an inverted listing giving the DF file for
every file in the release; it it helpful for finding things.
There are subdirectories of these directories depending on the package or subsystem involved. Use
* liberally when in doubt.
3.1 General References
In the following assume the file is on [lndigo]Documentation) unless a full path name is
explicitly given
[01] Paxton, W., The Tioga Editor. In the Cedar Manual and TiogaDoc.press, .tioga.
The manual for the text editor and manuscript preparation system.
[02] Brotz, D., Laurel Manual, CSL-81-6.
[03] Schmidt, Eric, The DF Files Reference Manual, DFFilesRetMan.press.
[04] Levin, Roy, Cedar Releases: Policies and Procedures, ReleaseProcedures.press/bravo
[OS] SOD, Pilot User's Handbook. On [lrls]Doc) PilotUsersHandbook.press.
You don't need all of it and it's a long document to print; borrow or obtain a hardcopy and look
at pages 47-92 for Cascade documentation if you deal with CoPilot extensively.
[06] Fiala, Ed, [Indigo]MPCodes.*.
[071 Schmidt, E. and Lampson, B.• Cedar System Modelling Reference Manual, ModeIRetMan.Press.
[08] Atkinson, BugBane. [lndigo] BugBane> BugBane.doc. BBV.doc, BugBane.shorts, and
BugBane. wish.
[09] Horning. 1. (ed.), The Cedar Catalog, In the Cedar Manual and Catalog.tioga/press.
A description of programs available for use and study.
[010] Levin. The Release Messages, CedarRelease*.msg.
These messages describe the properties of each new release. They often contain vital pieces of
information about known bugs and how to avoid them. Obviously, the information in older messages
may be out of date.
[011] Ornstein, Dorado User Rules. posted by sign-up sheets opposite CSL coffee room.
[012] Ramshaw. The Alto/Dolphin/Dorado Briefing Blurb, [MAXC]BriefingBlurb.press.
Describes (almost) .everything there was to know about the basic CSL/ISL computer environment
in 1981.
[013] Lampson, B.• Taft, E.• Alto Users Handbook. November. 1978. The basic reference for using the
Alto system.
[014] Teitelman, W., Cedar UserExec. UserExec.tioga, .tioga.press
3.2 Cedar Language References
[Ll] Mitchell, Maybury. and Sweet, Mesa 5.0 Manual, CSL-79-3, April, 1979. The Mesa documentation
is fragmented across this and the next two references. so you need to be familiar with all three.
[L2] SOD, Mesa 6.0 Compiler Update. [Ivy]Doc>Compiler60.press.
[L3] Satterthwaite et ai.. Cedar Mesa 6T5. [lndigo]Lang)Cedar6Ts.press. This is a detailed

CEDAR 4.2

INTRODUCTION TO CEDAR

24

description of the Cedar language, assuming one knows Mesa. Some changes since this document
are enumerated in a shoner document, Documentation)Cedar7Tll.press.
[L4] Homing, J., Cedar Language Overview. Overview. tioga•. press; Lampson. B.. Cedar Lanuguage
Reference Manual. Grammar, and Summary. CLRM.press. CLRMGram.press. CLRMSafeGram.press.
CLRMSumm.press; Mitchell. 1.. Annotated Cedar Examples. CedarExamples.tioga•. press.
[L5] Mitchell. 1. Stylizing Cedar. cedarstyle.doc•. press. Cedar Style Sheet. stylesheet.sil.. press.

CEDAR 4.2

THE BRIEFING BLCRB

Raison

2

d~Etre

The purpose of this document is to help immigrants adapt to the local computing community. By
"the local community". I mean primarily the Computer Science Lab. the Imaging Sciences Lab, and the
Integrated Design Lab of the Xerox Palo Alto Research Center, better known by the acronyms CSL.
ISL. and IDL respectively. Immigrants to other computing communities within Xerox may also find this
document of interest. but I make no guarantees. I shall assume herein that said immigrants know quite
a bit about computer science in general. Hence. I shall concentrate upon discussing the idiosyncratic
characteristics of the local hardware environment. software environment. social environment. linguistic
environment. and the like.
You will doubtless read many documents while you are at Xerox. A common convention observed in many manuals and
memos is that fine points or items of complex technical content peripheral to the main discussion appear in small type. like this
paragraph. You Will soon discover that you cannot resist reading this fine print and that. despite its diminutive stature. it draws
your eyes like a magnet This document has such PllSS!lges as well. just so that you can begm to enjoy ferreting out the diamonds
hidden in the mountain of coal.

There is a great deal of useful information available on-line at Xerox in the form of documents and
source programs. Reading them is often very helpful, but finding them can be a nuisance. Throughout
this document. references to on-line material are indicated by . where n is a citation number in the
bibliography at the end of this document. Standard citations to the open literature appear as [n].
If you are fortunate enough to be reading this document from within Tioga (the Cedar editor), you
should pause at this point to try out the "Def' command. If you were to select the three characters
"" in the preceding paragraph and then click the "Def' command with the middle mouse button,
you would then find yourself looking at the place in this document where "" is defined. that is. where
it appears followed by a colon. You could then get back to this section of the document by clicking the
"PrevPlace" command with any mouse button. The "Def' command is almost as good as an automatic
indexing facility. On another topic, you might try clicking the "FirstLeveIOnly" button (click "Levels"
first if you can't find the "FirstLeveIOnly" button), and then clicking "MoreLevels" a few times. Try
scrolling a bit too. The Tioga "levels" commands are almost as good as an automatic table of contents.
Reading a document from front to back can be mighty boring. Fortunately, this document is so
disorganized that it is not at all clear that it really has a front and a back in any normal sense. You
might as well just browse through and read the parts that look interesting. To help out the browsers in
my reading community, I have more or less abandoned the custom of being careful to define my terms
before I use them. Instead. all the relevant terms, acronyms, and the like have been collected in a
separate Glossary. Some information is contained only in the Glossary, so you may want to skim through
it later (or now, for that matter). The "Def' command in Tioga is particularly helpful when browsing the
Glossary from within Cedar: try selecting the word "Tioga". and then clicking the "Def' button in the
Glossary viewer, for example. While wnnng the Glossary, I assumed that you have a basic knowledge of computer science.
and a modicum of common sense: don't expect to find terms like "computer" and "network" in the Glossary.

1983

EDITION

The Briefing Blurb:
Exploring the Ethernet with Mouse and Keyboard
1983 Edition
By Lyle Ramshaw of PARC/CSL
An immigration document in the tradition of Roy Levin's A Field Guide to Alto-Land.
June 7,1983
Filed on:

[lndigo]. But for our purposes,
suffice it to say that the Alto is a 16-bit minicomputer whose primary claim to fame is that it comes
'
equipped with a bitmap display, a mouse. and an Ethernet interface.
O-Machines
The D-machines are a family of personal computers, each member of which has a name starting
with the letter "0". As long as you don't look too closely, D-machines look a lot alike. In particular.
they are all 16-bit computers with a microprogrammed processor that handles most of the I/O as well
running the user's programs. And they all generally come equipped with a hard disk. a bitmap display,
a keyboard, a mouse. and an Ethernet interface. There are differences of course: in size. in speed, and
in flexibility.

1983 EDITION

THE BRIEFING BLURB

6

The Dolphin (formerly called the DO)

The Dolphin was one of the early D-machines. and there are still some of them around. Dolphins
are housed in the same sized chassis as Altos. You can tell that they aren't Altos because they have
wide screen terminals, and because they don't have a slot on top for a removable disk pack. Instead.
they use a 28MByte Winchester disk drive made by Shugan. Dolphins can talk to both 3 MBit and 10
MBit Ethernets.
The Dandelion

The Dandelion is the D-machine processor that is used in the Star products. It comes in a box
about half the width of an Alto chassis, and roughly the same height and depth. Dandelions are less
flexible than Dolphins, since the microprocessor is shared among the various I/O devices and the
emulator in a fairly rigid round-robin fashion (associated with the terms "clicks" and "rounds"). As a
consequence, it isn't very easy to hang a new [/0 device off of a Dandelion. On the other hand.
Dandelions are both faster and cheaper than Dolphins. Dandelions talk only to 10 MBit Ethernets.
The Dorado

Building large software systems is a demanding chore. It doesn't help any when the hardware upon
which your programming environment is based doesn't have enough horsepower to suppon you
properly-that is. in the manner to which you would like to become accustomed. After some years of
trying to shoehorn large programs into Altos, CSL twisted the arms of its hardware folk and talked them
into building the Dorado, the current high-performance model in the D-machine line. The processor,
the instruction fetch unit, and the memory system of the Dorado have been written up in papers for
your enjoyment [12J. Dorados come equipped with an 80 MByte'removable-pack: disk drive at present;
new models may start showing up soon with a 315 MByte Winchester drive instead. Dorados talk only
to 3 MBit Ethernets at present
A Dorado is roughly three to five times faster than an Alto when emulating an Alto, that is, running
BCPL. A Dorado runs compute-bound Mesa software roughly eight to ten times as fast as an Alto.
Because of the raw power of a Dorado, it is usually the computer of choice for substantial programming
projects. The primary difficulty about Dorados is that there aren't enough of them (and the related fact that
they are rather tricky to build). Some people have their own, but others must share a pool of public machines.
Now, even though the Dorado disk drives have removable packs, it really isn't very convenient to stan.
your session of a public Dorado by mounting your own pack. The biggest difficulty is that you must be
at the processor to change the disk pack. and the processor is a. long way away. Subsidiary difficulties
are that you must power down a Dorado in order to change the disk pack, and that T-80 disk packs are
difficult to label effectively. As a result. when you borrow a Dorado, you generally also want to borrow
at least some of the space on that Dorado's local disk. In order for this sharing to work out well, cenain
social taboos and customs concerning the use of such local disks have emerged. under the general rubric
of "living cleanly". More on this topic anon.
[n a return to the ways of the past, the Dorado processors are rack mounted in a remote, heavily
air-conditioned machine room. [t was initially intended that the Dorado, like the Alto, would live in
your office. To prevent its noise output from driving you crazy, a very massive case was designed.
complete with many pounds of sound-deadening material. But experience indicated that Dorados ran
too hot when inside of these cabinets. and the concept of having Dorado processors in offices was
abandoned. With progress in general and VLSI in panicular, there is hope that some successor to the
Dorado will once again come out of the machine room and into your office.
The Dicentra

1983 EDITION

THE BRIEFING BLliRB

7

The Dicentra is the newest D-machine. Essentially, it consists of the processor of the Dandelion
squeezed onto one Multibus card. It communicates with its memory and with
110 devices over the Multibus. Dicentras will talk to any Ethernet. or any 110 device for that matter.
for which you can supply a Multibus interface card: that's one of the Dicentra's strengths. The initial
application of the Dicentra is as a processor for low cost Internet gateways. The Dicentra and the Dandelion
With the tasking stuff striped out

are named after wildflowers partially because they are outgrowths of an initial design of Butler Lampson's called the Wildflower.

The Daffodil

The Daffodil is a D-machine that doesn't exist yet, but someday may. If so, it will be cheap to
build, since it will use custom integrated circuits. The Daffodil is product-related. Thus, please don't
talk about it too widely. I mention it hear only so that you will know what it is that Chuck Thacker is
talking about
The Dragon

The Dragon is a high-performance processor based on custom integrated circuits that is being
designed in CSL: confusingly enough, though, the Dragon is not really a D-machine. For example, the
Dragon word size is 32 bits rather than 16. The underpinnings of Cedar will be adjusted as necessary
so that Cedar will run on a Dragon; but this will take some doing.
A few comments about Booting

All of the local processors come equipped with a hidden button called the "boot button" that is
used to reinitialize the processor's state. The Alto had just one boot button, hidden behind the keyboard;
pushing it booted the Alto. On Dolphins, the situation is only slightly more complex: there are two
boot buttons, one at the back of the keyboard, and the other on the processor chassis itself. They
perform roughly the same function, but the one on the chassis is a little more potent. On Dorados,
there is a lot more going on. There are really two computers involved. the main Dorado processor and
a separate microcomputer called the baseboard. It is the baseboard computer's job to monitor the power
supplies and temperature and to stage-manage the complex process of powering up and down the main
processor, including the correct initialization of all of its RAM's. The boot button on a Dorado is
actually a way of communicating with this baseboard computer. You encode your request to the
baseboard computer by pushing the boot button repeatedly: each number of pushes means something
different. For details, see Ed Taft's memo on the subject <13>. If the baseboard computer of the Dorado
has gone west for some reason (as occasionally happens), your only hope is to push the real boot button,
a little white button located on the processor chassis itself. far, far away. lust as the boot button on the keyboard
is essentially a one-bit input device for the baseboard computer, the baseboard computer also has a one-bit output device: a green
light located on the processor chassis. Various patterns of flashing of this light mean various things. as detailed in <13>.

There is one more bit of folklore about booting that I can't resist mentioning-every once in a while,
I have to throw in some subtle tidbit to keep the wizards who read this from getting bored. Our subject
this time is the "long push boot". Suppose that you have been working on your Dorado for a while,
and you walk away to go to the bathroom. When you return and reach toward your keyboard, you get
a static shock. You are only mildly annoyed at this until you notice that the cursor is no longer tracking
the mouse, and the machine doesn't seem to hear any of your keystrokes. The screen looks OK, but the
Dorado is ignoring all input What has probably happened is that the microprocessor in your terminal
has b~n knocked out by the static shock. Yes, Virginia! In addition to the Dorado itself. and the
baseboard computer, there is also a microprocessor in your terminal (located in the display housing),
which observes your input actions and sends them on [0 the main processor under a protocol referred
to as "the seven-wire interface". What you want to do now is to reboot the terminal microprocessor
without disturbing the state of the Dorado at all-after all, you were in the process of editing something,

1983

EDITION

THE BRIEFING BLURB

8

and you are now in danger of loosing those edits. What you should do is to depress the boot button
and hold it down for quite a while (more than 2.5 seconds): and then release it This is known as a
"long push boot", and it does just what you want under these conditions: it reboots your terminal
without affecting anything higher up.
MAXC: a blast from the past
Before we leave the topic of hardware completely. I should pause to mention the existence of MAXC
(the name is said to be an acronym for Multiple Access Xerox Computer). Over the years, the folk in
CSL built two MAXC's. Each was a good-:Sized microprogTammed computer that spent its days emulating
a PDP-lO: running TENEX, and timesharing away with the best of them. One of the MAXC's still
survives. the one initially known as MAXC2. and it serves us now primarily as the Internet's interface to the
Arpanet Vestiges of MAXCl still survive as souvenirs in some people's offices. Most of the stuff going between the
Internet and the Arpanet is electronic mail: our mail systems understand about Arpanet recipients, so
there is no need to talk to MAXC directly just to send Arpanet mail. There are a few other computing
tasks that MAXC can perform and that no one has yet had the energy to supply in some other way,
such as archiving files onto magnetic tape. But most folks should be able to spend their time here quite
happily without ever talking direc~y to MAXC.

1983 EDmON

THE BRIEFING BLCRB

9

Local Programming Environments
Various programming environments have grown up around the various pieces of hardware mentioned
above. You can get a software merit badge simply by writing one non-trivial program in each envimoment
Programming on MAXC
Since we were discussing MAXC just a moment ago, let's get it out of the way first From a software
point of view, MAXC is a PDP-I0. Thus, it is programmed either in the assembler Macro-to or else in
one of a variety of higher level languages [14]. Fortunately, there aren't all that many new programs
that have to be written to run on MAXC any more.
BCPL
The first high-level programming language used on the Alto was SCPL, and quite a bit of program
writing was done in that environment over the years. By now, however, essentially no new programming
is being done in SCPL. The language itself will be around for some time to come, since there are BCPL
programs that perform valuable services for us: the print server programs Press and Spruce and the file
server program IFS are three important examples.
Of the better-known computer languages, BCPL is closest to C. The fundamental data type in
BCPL is a sixteen-bit word. There are facilities in the language for building structured data objects
including records and pointers. But there is no type-checking in the language at all. For example, if
faa is a pointer to a record of type node that includes a field named next, that field is referenced in
BCPL by writing
"foo»node.next",
which means "treat faa as a pointer to a node, and extract the next field". In a strongly typed language,
you wouldn't have to mention that faD was a pointer to a node, since the compiler would be keeping
track of the fact thac faD was so declared. The BCPL compiler, however. thinks of faD as a sixteen bit
value, just like any other sixteen bit value. For example, it would be legal in BCPL to write
"(foo+ 7»)node.next", or "foo»otherNode.next".
Some of the strictness of the Mesa approach to type-checking and version matching discussed below may
be a reaction to BCPL's free-wheeling ways of handling these issues. Further details about the BCPL
language and environment can be found elsewhere <14, 15. 16>.
The debugger in the BCPL environment was named "Swat". This name is preserved in the local
dialect as the name of the bottom of the three unmarked keys at the right edge of the keyboard. Various
debuggers may be invoked in various environments by depressing this key, perhaps in conjunction with
the left-hand shift key or the control key. (The right hand shift key won't do; it is too close to the swat
key itself for comfort!)
Mesa
Mesa is a strongly typed. PASCAL-like implementation language designed and built locally. It first
ran on Altos. Herein, I shall call that system Alto/Mesa. Dolphins and Dorados (but not Dandelions)
can run Alto/Mesa by impersonating an Alto at some level. More recent instances of Mesa now run on
all of our D-machines under the Pilot operating system. In passing, I should observe that Pilot is an
operating system written in Mesa by folk in SOD. It.is a heavier-weight operating system than the Alto
as, providing its clients with multiprocessing, virtual memory, and mapped files.
Alto/Mesa programs do not use the Alto

as

1983

at all. mostly because Mesa and BCPL have rather

EDITION

THE BRIEFING BLURB

10

different philosophies about the run-time world in which they exist. So the first thing that a Mesa
program does when running on an Alto is to junta away almost aU of the OS, and set about building a
separate Mesa world. It is a considerable nuisance for Mesa and BCPL programs to communicate, since
their underlying instruction sets are completely different. So, most of the important OS facilities, such
as the file system, had to be re-implemented directly in Mesa. Mesa's memory management strategies
replace the revolutionary tactics of "junta" and "counter-junta" with the relative anarchy of segment
swapping.
A fair amount of software was written in Alto/Mesa. but little new programming is being done in
that environment; that is, Alto/Mesa isn't quite at dead as BCPL. but it is getting there. Perhaps the
crown jewels of Alto/Mesa are the systems Laurel, Grapevine, Mockingbird, and Griffin. You will be
hearing more about the former two in the section on electronic mail; to find out more about the latter
two, check out their entries in the Glossary.
The Pilot version of Mesa is the home to lots of active programming in several locations. First, it
is the system in which the Star product was and is being implemented by OSD. The programmers in
OSD have developed a set of tools for programming in Mesa variously called the "Tools Environment"
or "Tajo". This body of software may soon be marketed under the name "the Mesa Development
Envimoment". In addition, Pilot Mesa is the current base of the Cedar project in CSL and ISL. More
on Cedar later.
.
Although Mesa programs look a lot like PASCAL programs when viewed in the small. Mesa provides
and enforces a modularization concept that allows large programs to be built up out of smaller pieces.
These smaller pieces are compiled separately, and yet the strong type checking of Mesa is enforced even
between different modules. The basic idea is to structure a system by determining certain abstract
collections of facilities that some portions of the system will supply to other portions. Such an abstraction
is called an "interface", and it is codified for the compiler's benefit in a Mesa source file called an
"interface module", An interface module defines certain types, and specifies a collection of procedures
that act on values of those types. Only the procedure headers go into the interface module. not the
procedure bodies (except for [NLINE·s. sad to say). This makes sense, since all the interface module has to do
is to give the compiler enough information so that it can type-check programs that use the abstraction.
Having specified the interface, some lucky hacker then has the job of implementing it-that is. of
writing the procedure bodies that actually do the work. These procedure bodies go into a different type
of module called an "implementation module". An implementation module is said to "export" the
interface that it is implementing; it may also "import" other interfaces that it needs to do its job,
interfaces that some other program will implement.
[n simple systems, each interface is exported by exactly one module. [n such a system, there isn't
much question about who should be supplying which services to whom. In fact, in these simple cases,
the binding. that is, the resolution of imports and exports. can be done on the fly by the loader. But in
more complex cases, there might be several different modules in the system that can supply the same
service under somewhat different conditions. or with somewhat different performance. Then. the job of
describing exactly which modules are to supply which services to which other modules can become rather
subtle. A whole language was devised to describe these subtle cases, called C/Mesa. The Binder is the
program that reads a C/Mesa description. called a conjig, and builds a runnable system by filling imports
request from exports according to the recipe.
The Mesa language is described by a manual [18]. It lies somewhere between a tutorial and a
reference manual. Some people find some portions of it rather obscure: in particular, the discussion of
interfaces and implementations in Chapter 1 is often cited as confusing. To make matters a little worse,
that manual documents Mesa version 5.0; the current Alto/Mesa is version 6.0, and Pilot mesa has
advanced even further, From the point of view of the Mesa language itself, the most important changes
that have occurred since version 5.0 are the introduction of sequences and zones in version 6.0; they
are documented for your reading pleasure <19>. You may also be interested in Jim Morris's comments

1983

EDITION

THE BRIEFING BLeRB

11

on how programs should be structured in Mesa [20].
Smalltalk
Smalltalk was developed by the folk who now call themselves the Software Concepts Group (formerly
known as the Learning Research Group). The Smalltalk language is the purest local embodiment of
"object-oriented" progr~ming:
A computing world is composed of "objects".
The only way to manipulate an object is to be polite. and ask it to manipulate itself. One asks by
sending the object a message. All computing gets done by objects sending messages to other
objects.
Every object is an "instance" of some "class".
The class definition specifies the behavior of all of its instances-that is. it specifies their behavior
in response to the recipt of various messages.
'
Genealogists will recognize that ideas from both Simula and Lisp made their way into Smalltalk,
together with traces of many other languages.
For some years now, the folk in SCG have been working at trying to get the Smalltalk language
and system out into the great wide world. The first public event that came out of this effort was the
August 1981 issue of Byte magazine: it was devoted to Smalltalk-80, including a colorful cover drawing
of the now famous Smalltalk balloon. In addition, the SCG folk are writing several books about
Smalltalk. and they are planning to license the system itself to various outside vendors. The first of the
books, entitled Smallta/k-80: The Language and Its Imp/ementation. emerged from the presses at
Addison-Wesley just recently [21]. Future books will include Small/a/k-80: The Interactive Programming
Environment, and Sma//ta/k-80: Bits of History, Words of Advice.
Interlisp-D
LISP is the standard language of the Artificial Intelligence community. Pure LISP is basically a
computational incarnation of the lambda calculus: but the LISP dialects in common use are richer and
bigger languages than pure LISP. Interlisp is one dialect of LISP, an outgrowth of an earlier language
called BBN-LISP: for more historical details. read the first few pages of the Interlisp Reference Manual
[22]. One of the biggest strengths of Interlisp is the large body of software that has developed to assist
people programming in Interlisp. Consider the many features of Interlisp: an interpreter, a compatible
compiler. sophisticated debugging facilities. a structure-based editor. a DWIM (Do What I Mean) error
correction facility. a programmer's assistant. the CLISP package for Algol-like sYntax. the Masterscope
static program analysis database. and the Transor LISP-to-LISP translator. to name a few.
Interlisp itself has been implemented several times. Interlisp-lO is the widely-used version that runs
on POP-lO's. Interlisp-O is an implementation of Interlisp on the D-machines [23], produced by folk
at PARCo In the process of building Interlisp-D. the boundary between Interlisp and the underlying
virtual machine was moved downward somewhat. to minimize the dependencies of Interlisp on its
software environment: that is. functions that were considered primitive in Interlisp-10 were implemented
in Lisp itself in Interlisp-D. But the principal innovations of Interlisp-D are the extensions that give the
Interlisp user access to the personal machine computing environment: network facilities and high-level
graphics facilities (including a window package) among them.
By the way. Interlisp has the honor of being the first system (to my knowledge) to use the prefix "Inter-", This prefix has
become quite the rage of late: Internet. Interpress. Interscriin-you get the general idea

Cedar

1983 EDmON

THE BRIEFING BLURB

12

Back in 1978. folk in CSL began to consider the question of what programming environment we
would use on the emerging D-machines. A working group was formed to consider the programming
environments that then existed (Lisp. Mesa. and Smalltalk) and to form a catalog of programming
environment capabilities. ranked by both by value and by cost. A somewhat cleaned-up version of the
report of that working group is available as a blue-and-white for your perusal [24]. After pondering the
alternatives for a while. CSL chose to build a new programming environment, based on the Mesa
language. that would be the basis for most of our programming during the next few years. That new
environment is named "Cedar".
Cedar documentation is in a constant state of flux; indeed. it might be said that Cedar as a whole.
not only its documentation. is in a constant state of flux. Much of the documentation for the current
release is accessible through a ".df· file named Manual.df ~25>. Hardcopies of this packet of stuff,
entitled ''The Cedar Manual". are produced from time to time. and distributed to Cedar programmers.
The programming language underlying Cedar is essentially Mesa with garbage collection added.
Now. adding garbage collection actually changes things quite a bit. First of all. it changes programming
style in large systems tremendously. Without garbage collection. you have to enforce some set of
conventions about who owns the storage. When I call you and pass you a string argument, we must
agree whether I am just letting you look at my string, or I am actually turning over ownership of the
string to you. If we don't see eye to eye on this point, either we will end up both owning the string
(and you will aggravate me by changing my string!) or else neither of us will own it (and its storage will
never be reclaimed-a storage leak). Once garbage collection is available, most of these problems go
away: God. in the person of the garbage collector. owns all of the storage; it gets reclaimed when it is
no longer needed. and not before. But there is a price to be paid for this convenience. The garbage
collector takes time to do its work. In addition. all programmers must follow certain rules about using
pointers so as not to confuse the garbage collector about what is garbage and what is not.
Thus. programs in the programming language underlying Cedar look a lot like Mesa programs. but
they aren't really Mesa programs at all. on a deeper level. To avoid confusion. we decided to use the
name "Cedar" to describe the Cedar programming language, as well as the environment built on top of
it. Cedar is really two programming langauges: a restricted subset called the safe language, and the
unrestricted full language. Programmers who stick to the safe language can rest secure in the confidence
that nothing that they can write could possibly confuse the garbage collector. Their bugs will not risk
bringing down the entire environment around them in a rubble of bits. Those who choose to veer
outside of .the safe language had better know what they are doing.
Those who want to know more about Cedar are once again encouraged to dredge up a copy of the
Cedar Manual (25). It includes documentation on how Cedar differs from Mesa. annotated examples
of Cedar programs. manuals for many of Cedar's component parts, a Cedar ·catalog, and lots of other
good stuff. By the way, the most authoritative source for what the current Cedar compiler will do on
funny inputs can be found in a document called the Cedar Language Reference Manual, also known by
the acronym CLRM. This is logically part of the Cedar Manual, but it is currently bound separately,
and only available in draft form. The CLRM suggests a particular design philosophy for building a
polymorphic language that is a superset of the current Cedar, since that is the direction in which the
authors of the CLRM, Butler Lampson and Ed Satterthwaite. would like to nudge the Cedar language.

1983 EDITION

THE BRIEFING BLL"RB

13

Local Software
This section is a once-over-lightly introduction to some of the major software systems that are
available in the Alto and Cedar worlds. First. let me mumble some general words about how such
subsystems are documented. The most commonly used Alto subsystems are documented in a tome called
the Alto User's Handbook. [26]. The less commonly used ones are documented in a catalog entitled
"Alto Subsystems" <27>. In addition. Suzan Jerome wrote a Bravo primer. aimed at non-programmers
(28). In Cedar. the current best sources are the Cedar Manual mentioned above <25>. and a brand new
public database, sitting on Alpine, containing whiteboards of Cedar documentation. Unfortunately. I
won't hear about the latter until Dealer tomorrow, so that [ can't tell you any more about it at the
moment; I'm sorry, but that's life in a rapidly changing world. Wow! I've seen the whiteboards stuff now. and
it's flashy! Maybe this is the last version of the Briefing Blurb that I'll ever have to write.

Filing
When programming in the Alto world. or in current Cedar, you are dealing with two different types
of file systems: local and remote. The local file system sits on your machine's hard disk. Remote file
systems are located on file servers, machines with big disks that are willing to store files for you. Local
file systems have several unpleasant characteristics in comparison with the remote systems: they are
small. and they aren't very reliable. Both of these problems have consequences.
Because local file systems are small, it isn't in general practical to store more than one version of a
tile on the local disk. Thus, in our current local file systems, writing a "new version" of a file really
means writing on top of the old one. Nearly everyone who isn't accustomed to this (particularly PDP-10
hackers) gets burned by it at least once. There is one important exception to this general rule of "no
old versions". however: our text editors maintain one backup copy of each file being edited as a separate
file. whose name ends with a dollar sign. That is, the backup copy of "foo.tioga" is stored in the file
"foo.tioga$". and similarly for Bravo. Note that our remote file servers do maintain multiple versions of
files. Letting old versions of things accumulate is one easy way to overflow your disk usage allocation
on a remote server.
No disk is completely reliable. Our remote file servers have automatic backup facilities that protect
us from catastrophic disk failures. But the local file systems have no such automatic protection. Since
this protection isn't provided automatically, it behooves you to adjust your behavior appropriately: make
sure that, on a regular basis, backup copies of the information on your l~al disk are put in some safe
place. such as on a remote file server where suitable precautions are constantly being taken by wizards
to protect against disk failure. Doing this is one facet of what is meant by the phrase Living Cleanly,
which deserves its own section.
Living Cleanly (also known as "Keeping your bags packed'?

The phrases "living cleanly" and "keeping your bags packed" refer to a particular style of use of
your local file system. In order to understand the cosmic issues involved. we should pause to discuss
the ways in which local and remote file systems have been used over the years.
Back in the Alto days., personal files were usually stored on one's Alto disk pack, while project-related
and other public files were stored on remote servers. Careful folk would occasionally store backup copies
of their personal files on remote servers as well. in case of a head crash. But, as a general rule, one
thought of one's Alto pack as the repository of one's electronic state. This made sharing Altos quite
convenient. since you could tum any physical Alto into "your Alto" just by spinning up your disk pack.
In the glorious world of the Cedar future. all of your personal files as well as all public files will
live on file servers in the network. The disk attached to your personal computer will, from time to time,
contain copies of some of this network information. for performance reasons; but you won't have to do

1983

EDITION

THE BRIEFING BLURB

anything to achieve this, and you won't have to worry about how it is done. From the user's point of
view, all files will act as if they were remote at all times, Indeed. except in a few funny cases, there
won't even be any notion of "local file"; "file" will mean "remote file".
At the moment, we are sitting in an unpleasant trasitional phase somewhere between these two styles
of usage of the local disk: we are attempting to simulate the latter state by means of manual methods
and social pressure. We want you to think of your data as really living out on the file servers. That is
the proper permanent home for your personal files as well as for public files. You will have to bring
copies of these files, both private and public. to your local disk in order to work on them. But. at the
end of each editing session, you should store the new versions of files that you have created back out to
their permanent remote homes. None of this happens automatically at present; you have to make it
happen manually by using various file shuffling tools, such as the "OF files" discussed below. Using
these tools is a hassle, and learning how to use them can be confusing. But. there are four important
benefits to be reaped from adopting a clean living life-style.
First. you' are taking a step towards the glorious future.
Secondly, you are protecting yourself against failures of the local disk. A clean liver only holds
information on her local. disk for the duration of an editing session. This puts a reasonable bound on
the amount of information that she can lose because of a disk crash.
Thirdly, there are various reasons why erasing your local disk is a good idea when updating to a
new release of the Cedar system: sometimes. in fact. it is required. Since clean living folk don't keep
long term state on their local disks, this doesn't bother them in the slightest.
Finally, and perhaps most importantly, clean living is the key to sharing disk space on machines
without removable disks. When you use a public Dolphin or Dorado, you are forced to share its disk
space with the other members of the community. This sharing is predicated on a policy of clean living:
when your session is over, you must store away all of your files on remote file servers. The person who
uses the machine next may need to free up some disk space; if so, she is perfectly entitled to delete
your files without qualm or pause. And you won't mind a bit. it says here, because you have been living
cleanly.
The above paragraph is the "letter of the law" regarding the sharing of public disk space. People
who want to be well regarded should also pay some attention to the "spirit of the law": sharing things
is always more pleasant when everyone acts with a modicum of politeness and care. Don't delete the
previous user's files if she was called away by some disaster and didn't have a chance to clean up. Try
not to delete the standard system files. such as the Compiler, that sit in the local file system. since
whoever follows you will be justifiably aggravated by their absence. Even more important. if you do
exotic things such as bringing over non-standard versions of system files, try to put everything back to
normal when you leave ere you cause whoever follows you to become hopelessly confused.
Local file systems

The local file system in the Alto world is called either the "Alto file system" or the "BFS", the latter
being an acronym for Basic File System. The biggest that a BFS can be is 22,736 pages. This is
substantially bigger than-the entire disk on an Alto. However, Dolphins and Dorados have much bigger
local disks. Hence, when a Dolphin or Dorado is emulating an Alto, its local disk is split up into separate
worlds called partitions, each containing a maximum-sized BFS. Dolphin disks can hold two full
partitions, while Dorado disks can hold five. What partition you are currently accessing is determined
by the contents of some registers that the disk microcode us~. There is a command called "partition"
in the Executive and the NetExec that allows you to change the current partition.
When operating in the Pilot world, a disk pack is called a physical volume. and it is divided into
worlds called logical volumes. (Pilot. you will recall, is the new operating system written in SOD.) The

1983 EDITION

THE BRIEFI~G BLURB

15

area of the disk devoted to Pilot volumes must be disjoint from the area devoted to Alto-style partitions.
Most Dolphins that run Cedar are set up with a half-sized Alto partition, and the other three-quarters
of the disk devoted to Pilot; most Dorados that run Cedar have one full-sized Alto partition, and the
other four-fifths of the disk devoted to Pilot.
In current Cedar, many programs still restrict you to working with files in the local file system,
which is maintained by Pilot in the appropriate logical volume. The editor Tioga, for example, will let
you read remote files specified by a full path name, but it won't let you edit them; only local files may
be modified. In subsequent Cedar's, there will be a new local file system and directory package, the
Nucleus and FS respectively, to go along with the new virtual memory manager (also part of the Nucleus).
These wonders will make it somewhat easier to ignore the existence of the local file system, except for
its beneficial effects on performance; that is, they will make clean living more nearly automatic.
All of our local file systems use a representation for files that drastically reduces the possibility of a
hardware or software error destroying the disk's contents. The basic idea is that you must tell the disk
not only the address of the sector you want to read or write. but also what you think that sector holds.
This is implemented by dividing every sector into 3 parts: a header, a label, and a data field. Each field
may be independently read, written, or compared with memory during a single pass over the sector. The
Alto file system stuffs a unique identification of the disk block, conSisting of a file serial number and
the page number within the file, into the label field. Now, when the software goes to write a sector, it
typically asks the hardware to compare the label contents against data in memory, and to abort the
writing of the data field if the compare fails. This makes it pretty difficult. though not impossible, to
write in the wrong place. Furthermore, it distributes the structural information needed to reconstruct
the file system over the whole disk, instead of localizing it in one place, the directory data structures,
where a local disaster might wipe it out. Each local file system also has a utility program called a
Scavenger that rebuilds the directory information by looking at all of the disk labels.
Remote file systems

The most important local file servers are IFS's, an acronym for Interim File System (one of the
crown jewels of the BCPL programming environment). Like I always say. ·:temporary7. m~s "until it breaks", and
"permanent" means "until we change our minds". Indigo and Ivy are two prominent local IFS's; Indigo stores
mostly project files, while Ivy stores mostly personal files. MAXC also serves as a file server for some
specialized applications. Juniper was CSL's first attempt to build a distributed transactional file server;
it was one of the first large programs written in Mesa. Alpine is a new effort to build such a beast in
the context of Cedar, in support of distributed databases and other such wonderful things. Some Walnut
users have been storing their mail databases on Alpine for a month or more.
There is no coherent logic to the placement of "general interest" files and directories, nor even to
the division between Maxc, Indigo, and Ivy. Browse through the glossary at the end of this document
to get a rough idea of what's around. If something was made available to the universities in the University Grant
program, then it is probably on Maxc (or archived off of Maxc). since Maxc is the machine that the university folk can access.

IFS supplies a general sub-directory structure which the Maxc file system lacks, and as a result there
are lots of place to look for a file on an IFS. For example. on Maxc you might look for
[Maxc]Doc)MyFavoritePackage.press. or
[Indigo]Documentation.press,
or perhaps some other permutation. This requires a bit of creativity and a little practice. However, if
you get in the habit of using "·"8 in file name specifications, you will find all sorts of things you might

1983

EDITION

THE BRIEFING BLURB

16

not otherwise locate. Note that a "." in a request to an IFS will expand into all possible sequences of
characters, including right angle brackets and periods. Thus, for example, a request for
.
Dealing with editor bugs

All text editors have bugs. Furthermore. you are often most likely to tickle one of the remaining
bugs in an editor when you are working furiously on a hard problem. and hence. have been editing for
a long time without saving the intermediate results. As fate would have it, these are exactly the times
when it is most damaging and most upsetting to lose your work. There is nothing quite like the sinking
feeling you get when a large number of your precious keystrokes gurgle away down the drain. Both
Bravo and Tioga have mechanisms that can. in some cases, save you from the horrible fate of having to
do all those hours of editing over again. Bravo attempts to safeguard you by keeping track of everything
that you have done during the editing session in a log file; in case of disaster, this log can be replayed
to recapture most of the effects of the session. [f you have a disaster when editing in Bravo, be careful
NOT to respond by running Bravo again to assess the damage. By running Bravo again in the normal
way. you will instantly sacrifice all chance of benefiting from the log mechanism, since the log allows
replay only of the most recent session. What you want to do instead is run the program "BravoBug"
("Bravo/R" is not an adequate substitute). It wouldn't be a bad idea to ask a wizard for help also.
While you are looking for a wizard. try and think of some good answer to the question "Why are you
using Bravo, anyway?", which said wizard will almost certainly ask.
The most common-perhaps I should really say "the least rare"-source of editing disasters in Tioga
is problems with monitor locks. Unfortunately, this class of problem usually makes further progress in
any part of Cedar impossible, since Tioga is so basic to the Cedar system. If you can get to the CoCedar
debugger, you might be able to save your edits by calling the procedure
.. ViewerOpsImpl.SaveAllEdits[ ]
Rumor has it that Cedar versions from 4.2 on will allow you to invoke this procedure by hitting a special
collection of keys in Cedar itself, even after Tioga has become wedged. A further rumor has supplied more
details: holding down both the left and the right shift keys and the Swat key for more than 1 second will invoke SaveAIlEdits[
While the saving is taking place, the cursor will become a black box.

J.

Printing
In general, our printers are built by taking a Xerox copier and adding electronics and a scanning
laser that produce a light image to be copied. There are many different types of such printers. and there
are multiple instances of each printer type as well. There are also many different programs that would
like to produce printed output. The Press print file format was our first answer to the problem of
allowing every printing client to use every printer. Press tiles are the Esperanto of printing. Most print

1983

EDITION

THE BRIEFING BLURB

18

servers demand that the documents that you send to them be in Press format This means you have to
convert whatever you have in hand (often text) to Press format before a server will deign to print it.
Press file format <30> is hairy, and some print servers don't support the full generality of Press.
Generally, however, such servers will simply ignore what they can't figure out, so you can safely send
them any Press file you have.
A Press file can ask that text be printed in one of an extensive collection of standard fonts.
Unfortunately, you must become a wizard in order to print with your own new font. You can't use a
new font unless it is added to the font dictionary on your printer, and adding fonts to dictionaries is a
delicate operation: a sad state of affairs. If the Press file that you send to a printer asks for a font that
the printer doesn't have, it will attempt a reasonable substitution. and. in the case of Spruce, tell you
about the substitution on the break page of your listing. If you have chronic font difficulties of this sort,
contact a wizard.
There is a new print file format under development, called Interpress. The print servers that are
part of the Star product speak a dialect of Interpress. A print file in Interpress format is called a master.
Our local plans for printing Interpress masters involve converting them first into a printer-dependent
print file in so-called PO format (with conventional extension ".pd"). From there, a relatively simple
driver program on each printer should be able to produce the final output
The rest of this section was contributed by Julian Orr of ISL:
PARC has a variety of printers available for your hardcopy needs. We have high volume printers
for quantities of text. listings, and documentation: we have slower printers with generally higher quality
for more complex ftles; and we have very slow printers for extremely high quality. All of our current
printers except Platemaker offer 384 spots per inch and share a common font dictionary. We use two
different software systems for printing Press ftles. both running on Altos: one is called Spruce. and the
other is called (confusingly) Press. Spruce offers speed and spooling, but it can only image characters
and rules. and not too many of them. This makes it limited in graphics applications. Furthermore,
Spruce is limited to the particular sizes of fonts that it has stored in its font dictionary: it does not know
how to build new sizes by converting from splines. Press is slower. but can handle arbitrary bitmaps,
and can produce odd-sized fonts from splines.
ISL is developing Interpress printing capabilities. Printing" .pd" files is now an option on most
Press printers (that is, on printers running the program Press as opposed to Spruce). Just ship your
... pd" file to the printer in the standard way: it is smart enough to figure out whether what you have
sent it is in PO or Press format. and it will invoke PDPrint or Press as appropriate. Documentation on
these two printing programs is available, by the way 01. 32>. PO printing should not be undertaken
without consultation with a wizard.
Dover printers run Spruce for high volume printing. producing a page per second. CSL's Dover,
named Clover, is found in room 2106; ISL's Dover. named Menlo, is in room 2305. Samples of the
Dover font dictionary may be found next to Clover and Menlo. Instructions for modifying the queue
and generally running these Spruce printers are to be found next to their Alto terminals.
Lilac is our color PreSs printer and may be found in 2106 with Oover. It is a three color,
composite-black machine; it generally produces good quality output. but is occasionally temperamental.
Anyone interested in color printing or the state of Lilac should join the distribution list LilacLoversf .pa.
In the ISL maze area, room 2301, we have an assortment of black and white Press printers, answering
variously to the names of RockNRoll. Quoth. and Stinger. The printers are two Ravens (Raven is a
Xerox product), one Hornet, and one Gnat (the latter two are prototypes). The print quality is normally
excellent Instructions for interpreting status displays are posted locally. To be informed of which
printer is functioning and where. join the list ISLPrintf.pa. There should be three printers up for most
of the summer. Periodically one or another of these or Lilac are pre-empted for debugging.

1983 EDmON

THE BRIEFING BLURB

19

Our best quality printer is Platemaker, which is normally operated at 880 spots per inch, but can be
run lip to 2200 spi; it is not normally useful to go beyond 1600. Platemaker uses a laser to write on
photographic paper or film. Color images can be done in individual separations, which are then merged
using the Chromalin process. The Platemaker printing process is used for final prints of fine images or
for printing masters for publication. If you wish to have something printed, speak to Julian Orr, Eric
Larson, or Gary Starkweather.
Sending and Receiving Mail
We rely very heavily on an electronic mail system. We use it for mail and also for the type of
announcement tha~ might, in other environments, be posted on a physical or electronic bulletin board.
In our environment, a physical bulletin board is pretty useless, since people spend too much of their
days staring at their terminals and too little wandering the halls. Electronic bulletin boards might work
satisfactorily. But a bulletin board, being a shared file to which many people have write access, is a
rather tricky thing in a distributed environment. It probably presupposes a distributed transactional file
server, for example. Mumble. For whatever reason, the fact remains that we don't have an electronic
bulletin board facility at the moment As a result, announcements of impending meetings, "for sale"
notices, and the like are all sent as messages directed at expansive distribution lists. If you don't check
your messages once a day or so, you will soon find yourself out of touch (and saddled with a mailbox
full of obsolete junk mail). And conversely, if you don't make moves to get on the right distribution
lists early, you may miss lots of interesting mail. This business of using the message system for rapid distribution of
announcements can get out of hand. One occasionally receives notices of the form: "meeting X will start in 2 minutes-all
interested parties please attend".

Grapevine is the distributed transport mechanism that delivers the local mail [33]. When talking to
Grapevine, individuals are referred to by a two-part name called an "R -name", which consists of a prefix
and a registry separated by a dot; for example. "Ramshaw.pa" means Ramsha~ of Palo Alto. In
addition to delivering the mail, Grapevine also maintains a distributed database of distribution lists. A
distribution list is also referred to by an R -name, whose prefix conventionally ends in the character
up-arrow, as in "CSLt.pa". Distribution lists are actually special cases ofa construct called a Grapevine "group". Groups
can be used for such purposes as controlling access to IFS directories. There is a program named Maintain that allows
you to query and update the state of the distribution list database. In fact, there are two versions of
Maintain: the documented one with the unfortunate teletype-style user interface is used from within
Laurel or the Mesa Development Environment (34); the undocumented one with the futuristic menu
interface is used from within Cedar. Some distribution lists are set up so that you may add or remove
yourself using Maintain. If you try to add yourself to Foot.pa and Maintain won't let you, the proper
recourse is to send a message to the distribution, list Owners-Foot.pa, asking that you please be added
to Foot.
At the moment, Grapevine pretty much has a monopoly on delivering the mail. But there are
several different programs that give users access to Grapevine's facilities from different environments.
From an Alto, one uses Laurel, which is mentioned elsewhere as a pioneer of modeless editor interfaces.
Even if you aren't a Laurel user, I recommend that you read Chapter 6 of the Laurel Manual [35], which
is an enlightening and entertaining essay on proper manners in the use of the mail system. In the Mesa
Development Environment, the program Hardy provides services analogous to Laurel's. From within
Cedar, most folk use Walnut, whose documentation appears as part of the Cedar Manual <25). Walnut
represents a step towards the future in some respects. since Walnut uses Cypress, the Cedar database
management system. to store your mail in a database. Access to Grapevine from within Cedar can also
be had without the database frills through a program called Peanut, which stores your messages in a
structured Tioga document instead of in a database. Finally, in case travel should take you away from
your multi-function personal workstation. there are servers on the Internet known by the name "Lily"
to whom you can connect from any random teletype in order to peruse the mail sitting in your Grapevine
mailbox.

1983

EDITION

THE BRIEFING BLURB

20

Packaging Systems and Controlling Versions
In the BCPL world. the primary facility for packaging up a group of related files and either handing
them out or storing them for later recall was the dump file. A dump file, given conventional extension
·'.dm", is simply the concatenation of the dumpees, together with enough header infonnation to allow
the dum pees to be pulled apart again. Oump files have fallen out of favor.
In the Alto/Mesa world. and more strongly, in the Cedar world. a collection of software called "OF
files" has grown up that attacks the problem of describing and packaging systems, detailing their
interdependencies, and controlling the versions of things. You can find out a lot about OF files by
reading Eric Schmidt's dissertation [36]. You can find the answers to detailed questions about the
behavior of the various programs that deal with OF files by reading the reference manual for OF files
<37>. All that I will try to do here is to give you some idea of what OF files are good for, and how, in
a general sense, they are used. One way or another, all Cedar programmers must make their peace with
OF files: they perfonn valuable functions, and they have no current competition.
In the simplest case. a OF file just consists of a list of the names of a related set of files. At this
level. a OF file is something like a dump file: given the OF file, you can get at each of the files that it
describes. Of course. you want to be sure that you get the right versions of the described files. so just
having the OF file list their names isn't quite enough. If there were an Internet-wide notion of version
number that made sense, we could get around this problem by specifying the version number along with
the file name. But there isn't The closest thing to a Internet-wide unique identification stamp that we
have is the create date of the file. Thus, what a OF file really contains is a list of file names and
associated create dates.
The first program that you will meet that deals with OF files is Bringover. Bringover's job is to
retrieve to your local file system the set of files described by a particular OF file. This would be
something of a challenge unless the OF file included some hint to Bringover concerning where in the
great, wide Internet the correct versions of these files might be found. So OF files do indeed include
such hints: in particular, they include specifications of remote directories on which to look. These
directories are just hints, in the sense that Bringover will always verify by checking the create date that
it is getting you the correct version of the specified file. If Bringover can't find the correct version on
the 'specified directory, it will issue a sprightly error message. Bringover has lots of bells and whistles.
For example, you can point it at either a local or a remote OF file; you can ask it to retrieve just a
selected subset of files to your local disk, rather than the entire set described by the OF file; or you
can individually consider the files one by one, deciding which you would like to retrieve and which you
wouldn't.
Suppose that [ am working on a collection of files. such as the sources for this Briefing Blurb. I
have made a OF file that describes them, and [ can use Bringover to retrieve them from their remote
and pennanent home to my local file system. where I can edit them. The next thing that I need is a
service that is symmetric to Bringover: after doing my editing. I want to put the new versions back on
the remote file server. along with a new OF file that describes the new versions. This function is
perfonned by SModel. I run SModel, and point it at the old OF file. SModel considers each file in .
tum, and looks to see if [ have edited it; that is, it looks to see if the create date of that file in my local
file system is now different than the create date stored in the old OF file. If so, SModel deduces that I
have edited the file. It stores the new version that [ have made out onto the remote directory. After
doing this for each file in tum, SModel writes a new version of the OF file itself, filling in all of the
create dates correctly to describe the new version of the entire ensemble. If the OF file describes itself. as most
OF files do. SModel is smart enough to make sure that the new version of the OF file is stored out to the remote server as well.

SModel also has lots of bells and whistles. but let's not go into them.
If that were the whole story, mere mortals could figure out OF files without straining their brains.
But there's more. So far, we have only discussed OF files as descriptions of ensembles of files. In fact.

1983 EomON

THE BRIEFING BLCRB

21

these ensembles are often components of large programs. And this has consequences.
First, there are two distinctly different reasons that you might have for retrieving a program: you
might want to change it, or you might just want to run it. In the latter case, you don't need to bring
over all of the sources; all that you need is the runnable ".bcd". We could handle this by having two
OF files: one for the users and the other for the maintainers. But that would be a disaster: the two
OF files would never agree! Instead. each OF file distinguishes between files that it "exports" and the
rest The exported files are the ones that users need. .while maintainers are assnmed to need the entire
ensemble. You can warn Bringover that you are a user rather than a maintainer by giving it the "/p"
switch (which stands for ~blic-only).
Secondly, some programs are going to depend upon other programs: that is, the programs themselves
will be "users" ("clients" is a better word here). This suggests that one OF file should be able to contain
another OF file. In fact. there should be several different kinds of containment. corresponding to such
phrases as:
.
"They who maintain me also maintain the stuff described by the following OF file."
''They who maintain me are also users (but not maintainers) of the stuff described ... "
"They who use me are also users of the stuff described ... "
You get the point? For more details on the ways that these things are done ("includes" and
"imports"). check out the reference manual.
In case you still aren't convinced that things are complicated. it is now time to mention the fact that
OF files are used for yet another purpose: they describe components of the Cedar release. During the
Cedar release process. all of the new versions of Cedar components. which are sitting out on development
directories. must be checked for consistency, and then moved en masse tq the official release directory.
And an entire new set of OF flIes must be produced. describing the released version of the system (as
opposed to the development version). This means. among other things. that some OF flIes must specify
two different remote directories: the development directory and the release directory. In addition. there
is a third OF file program, called VerifyOF, whose purpose is to perform certain consistency and
completeness checks on a OF file. By insisting that all component implementers have successfully run
VerifyOF on their components. the Cedar Release Master ensures that the release process has at least a
fighting chance of succeeding <38>.
In fact. there are several other programs related to OF files that are sometimes useful. OFDisk. for
example, looks at all of the files on your local disk and classifies them according to where they may be
found on remote servers. This is a convenient way to determine what local files need to be backed up
before erasing the local file system for some reason. For more on OFOisk, an introduction to OFDelete.
and more, see the OF flIes reference manual <37>.
OF files grew up over time in response to a mixed bag of needs. As they became more popular.
features were added one by one to make them more useful in these varying contexts. The resulting
system as a whole is rather hard to grok. but I hope that this introduction has given you a leg up on the
problem. at least.

1983 EDITION

THE BRIEFING BLURB

22

Some Tidbits of Lore
About CSL

CSL has a weekly meeting on Wednesday afternoons called Dealer, starting at 1:15. The name
comes from the concept of "dealer's choice"-the dealer sets the ground rules and topic(s) for discussion.
When someone says she will "give a Dealer on X", she means that she will discuss X at some future
weekly meeting, taking about 15 minutes to do so (plus whatever discussion is generated). Generally,
such discussions are informal, and presentations of half-baked ideas are encouraged. The topic under
discussion may be long-range, ill-formed. controversial, or all of the above. Comments from the audience
are encouraged. indeed. provoked. More fonnal presentations occur at the Computer Forum on Thursday afternoons:
the Forum is not specifically a CSL function. and it is open to all Xerox employees. and sometimes also to outsiders. Dealers
are also used for announcements that are not appropriate for distribution by electronic mail. Members
of CSL are expected to make a serious effort to attend Dealer.
On occasions of great festivity, Dealer is replaced by a picnic on the hill (that is. Coyote Hill, across
Coyote Hill Road), with Mother Xerox picking up the tab.
The CSL Archives (not to be confused with TENEX archiving) are a collection of file cabinets and
3-ring binders that provide a continuing record of CSL technical activities. The archives are our primary
line of defense in legal matters pertaining to our projects. They also make interesting reading for anyone
curious about the history of any particular project.
There is also an institution known as the CSL Notebook, which exists to make all of the potentially
interesting documentary output of CSL folk easily accessible to all CSL folk. Trip reports, design
documents. immigration manuals (like this one): they should all be submitted to the CSL Notebook
<39>. If you thought that it was worth writing down. it is pretty likely that there are other folk in CSL
who would consider it worth reading, and submitting it to the CSL Notebook is one easy way to get it
read. (I believe that likely looking submissions to the CSL Notebook are considered for entry into the
CSL Archives as well.)
About ISL

ISL also has a weekly meeting, on Tuesdays starting at 11:00 am. This meeting has no catchy name
at the moment.

1983 EDITION

THE BRIEFING BLURB

23

Some Code Phrases
You may occasionally hear the following incomprehensible phrases used in discussions, sometimes
accompanied by laughter. To keep you from feeling left out. we offer the following translations:

"eommilting e"or 33"
(1) Predicating one research effort upon the success of another. (2) Allowing your own research
effort to be placed on the critical path of some other project (be it a research effort or not). Known
elsewhere as Forgie's principle.

"You can tell the pioneers by the a"ows in their backs."

Essentially self-explanatory. Usually applied to the bold souls who attempt to use brand-new
software systems, or to use older software systems in clever. novel. and therefore unanticipated ways .. ,
with predictable consequences. Also heard with "asses" replacing "backs".
"We're having a printing discussion."

Refers to a protracted, low-level. time-consuming. generally pointless discussion of something
peripherally interesting to all. Historically, printing discussions were of far greater importance than they are now. You
can see why when you consider that printing was once done by carrymg magnetic tapes from Maxc to a Nova that ran an XGP.

Fontology

The body of knowledge dealing with the construction and use of new fonts,

It has been said that fontology

recapitulates file-ogeny.

"What you see is what you get. ..

Used specifically in reference to the treatment of visual images by various systems, e.g.• a Bravo
screen display should be as close as possible to the hardcopy version of the same text. Also known is
some circles by the acronym "WYSIWYG", pronuonced "whiz-ee-wig".
",\-Ioving right along': "Pop!': or "Hey guys, up-level!"

Each of these phrases means that the conversation has degenerated in some respect, often by
becoming enmeshed in nitty-gritty details. Feel free to shout out one or more of these phrases if you
feel that a printing discussion has been going on long enough. If two participants in a large meeting
begin discussing details that are of interest to them but not of interest to the group as a whole. shout
"Offline!" instead.
"Life is hard"

Two possible interpretations: (1) "While your suggestion may have some merit. I will behave as
though I hadn't heard it'.' (2) 'While your suggestion has obvious merit, equally obvious circumstances
prevent it from being seriously considered." The charm of this phrase lies precisely in this subtle but
important ambiguity.
"What's a spline?"

"You have just used a term that I've heard for a year and a half. and I feel I should know, but
don't. My curiosity has finally overcome my guilt." Moral: don't hesitate to ask questions. even if they
seem obvious.

1983

EDITION

I

THE BRIEFING BLuRB

24

Hints for Gracious Living
There are a couple of areas where life at PARC can be made more pleasant if everyone is polite
and thoughtful enough to go to some effort to help out. Here are a few words to the wise:
Coffee
Both ISL and CSL have coffee alcoves where tea. cocoa. and several kinds of coffee are available.
All coffee drinkers (not just the secretaries or some other such barbarism> help out by making coffee. If
you are about to consume enough coffee that you would leave less than a full cup in the pot, it is your
responsibility to make a fresh pot. following the posted instructions. There are lots of coffee fanatics
around. and they get irritated beyond all reason if the coffee situation isn't working out smoothly. For
those coffees for which beans are freshly ground, the local custom is to pipeline grinding and brewing.
That is. you are expected to grind a cup of beans while brewing a pot of coffee from the previous load
of ground beans. This speeds up the brewing process for everyone, since a load of ground beans is-at
least, had better be-always ready when the coffee pot runs out.

Sharing Office Space

Be warned as well that some lab members are unbelievably picky about the state of their offices.
The convention is that any Alto in an empty office is fair game to be borrowed. Private Dolphins and
Dorados may be borrowed only by prior arrangement with their owners, because of the problems of
sharing disk space. If you use someone's office for any reason. take care to put everything back exactly
the way it was. Don't spill crumbs around, or leave your half-empty cocoa cup on the desk, or forget
to put the machine back in the state that you found it, or whatever. Of course, lots of people wouldn't
mind even if you were less than fanatically careful. But some people do mind, and there is no point in
irritating people unnecessarily.
Sharing printers
When you pick up your output from a printer. it is considered antisocial merely to lift your pages
off the top of the output hopper. and leave the rest there. Take a moment to sort the output into the
labelled bins. Sorting output is the responsibility of everyone who prints, just as making coffee is the
responsibility of everyone who drinks (coffee). Check carefully to make sure that you catch every break
page: short outputs have a way of going unnoticed, and hence being missorted, especially when they
come out right next to a long output in the stack. The rule for detennining which bin is to use the first
letter that appears in the name on the break page. Thus, "Ramshaw, Lyle" should be sorted under uR",
while "Lyle Ramshaw" should be sorted under ·'L". A trickier question is what to do with output for "Noname",
or the like. FollOwing the rule would suggest filing such output under "N", but that doesn't seem very helpful. since the originator
probably won't find it Check the contents and file it in the right bolt if you happen to recognize whose output it is: otherwise,
either leave it on top of the printer or stick it back in the output hopper.

1983 EDITION

THE BRIEFING BLURB

25

The phone system
When the Voice Project has had its way, our phone system will be a marvelous assemblage of
computers talking to computers, and this section of the Briefing Blurb will have to be expanded to tell
you all about it At the moment, however, we are simply customers of Pacific Telephone, so there isn't
too much to say. First. a little preaching.
If you make a significant number of personal long-distance phone calls from Xerox phones, it is
your responsibility to arrange to reimburse Xerox for them. This may not be that easy, either, since
phone bills take quite a while (six weeks or so) to percolate through the bureaucracy upstairs, and the said
bureaucracy also has a lot of trouble figuring out where to send the phone bills of new people, and
people who move around a lot. Just because it is easy to steal phone service from Xerox doesn't make
it morally right: if you think you aren't being paid enough. you should start agitating for a raise. If
enough suspicious calls are made without restitution. PARC (being a bureaucracy) will impose some bureaucratic "solution" on all
of us.

So as not to end on a sour note, let's discuss how the phone system works, anyway, The offices
within PARC have four-digit extensions within the 494 exchange, a system known as Centrex: to dial
another office, those four digits suffice. Dialing a single 9 as the first digit gives you an outside line,
and you are now a normal customer of Ma Bell: see a phone book for more details (Oh, come now,
surely you know about phone books!). Dialing a single 8 gives you different sounding dial tone, and
puts you onto the IntelNet (not to be confused with the InterNet). The IntelNet is a Xerox-wide
company phone system. complete with its own phone book. and its own phone numbers. If you are
calling someone in some remote part of Xerox, you can save Mother Xerox some bread by using the
IntelNet instead of going straight out over Ma Bell's lines. On the other hand. you may not get as good a cirCUIt
to talk over-although this situation is frequently said to be improving. Furthermore, through the wonders of modern
electronics, you can dial any long-distance number over the IntelNet. Just use the normal area code and
Ma Bell number: the circuitry is smart enough to take you as far as possible towards your destination
along IntelNet wires, and then switch you over to Ma Bell lines for the rest of the trip. Using the IntelNet
doesn't start to save money until the call is going a fair distance: therefore, the IntelNet doesn't let you call outside numbers in
area codes 408, 415. and 916-better to just dial 9.

One more thing: after you have dialed a number on the IntelNet. you will hear a funny little
beeping. At that point. you are being asked to key in a four-digit number to which the call should be
billed. You should use the four-digit extension number for your normal office phone under most
circumstances. Calls made by dialing 9 instead of 8 are always charged to the phone from which they are placed.
The first three rings (roughly speaking) of an incoming call occur only in your office. The next
roughly three rings happen both at your office phone and at a receptionist's phone, centrally located in
the laboratory. During normal business hours, the receptionist's phones are staffed: thus, someone will
at least take a message for you, and leave it on a little slip of paper in your physical message box. If
the second three rings go by ~ithout either of those two phones answering, the call is then forwarded to
the guards desk downstairs (I believe).
If you are expecting a call but won't be near your normal phone, a call forwarding facility exists:
dial 106 and then the number to which you want your calls to be forwarded. Later on (try not to forget),
you dial 107 on your normal phone to cancel the forwarding. When I forward my phone, I turn the
phone around physically, so that the touch-pad faces the wall. This helps me to remember to cancel the
forwarding again later, at which point I tum the phone back the· normal way. There is also a way to
transfer incoming calls to a different Xerox number: Depress the switch hook once, and dial the
destination number: when the destination answers, you will be talking to the destination but the original
caller won't be able to hear your conversation: depressing the switch hook again puts all three of you
on the line: then you can hang up when you please. If the destination doesn't answer. depressing the switch hook
once again will flush the annoying ringing or busy signal.

1983

EDITION

THE BRIEFING BLURB

26

References
Reference numbers in [square brackets) are for conventional hardcopy documents. Many of them
are Xerox reports published in blue and white covers; the CSL blue-and-whites are available on
bookshelves in the CSL Alcove. Reference numbers in  are for on-line documents. The
path name for such files is given herein in the form
[FileServer]Sub Directory >FileName.Extension
for backward compatibility with earlier systems. Recently. the simpler alternative form

IFileServer/Directory ISubDirectory I FileName. Extension
has begun to come into local currency. but some systems still demand brackets rather than slashes.
: The generic form for a reference to an on-line document
[n]:
The generic form for a reference to a hardcopy document.
[1]:
Sunset New Western Garden Book. Lane Publishing Company. Menlo Park, CA. 1979. The
definitive document on Western gardening for non-botanists; 1200 plant identification
drawings: comprehensive Western plant encyclopedia; zoned for all Western climates; plant
selection guide in color.
[2]:
John E. Warnock. The Display of Characters Using Gray Level Sample Arrays. blue-and'white
repon CSL-8D-6.
[3]:
Richard F. Lyon. The Optical Mouse. and an Architectural Methodology for Smart Digital
Sensors. blue-and-white repon VLSI-81-I.
[4]:
The Ethernet Local Network: Three Reports. blue-and-white repon CSL-8D-2.
[5]:
John F. Shoch. Yogen K. Dalal, Ronald C. Crane. and David D. Redell. Evolution of the
Ethernet Local Computer Network. blue-and-white repon OPD-T8102.
<6>: [Maxc]NetTopology.press.
Contains a picture of the entire internetwork
configuration in seven pages. It is out of date. All such documents are always out of date.
A copy is posted on the wall opposite the Alcove in CSL.
[7]:
David R. Boggs, John F. Shoch, Edward A. Taft, and Roben M. Metcalfe. Pup: An
Internetwork Architecture. blue-and-white repon CSL-79-10.
[8]:
Internet Transport Protocols. Xerox System Integration Standard repon XSIS 028112,
December 1981.
[9]:
Courier: The Remote Procedure Call Protocol. Xerox System Integration Standard repon
XSIS 038112, December 198I.
[10]: C.. P. Thacker, E. M. McCreight. B. W. Lampson. R. F. Sproull, and D. R. Boggs. Alto: A
personal computer. blue-and-white repon CSL-79-1I.
AltoHardware.press. Everything that you need to know to write your own
Alto microcode.
[12]: The Dorado: A High-Performance Personal Computer; Three Papers. blue-and-white repon
CSL-8l-I.
<13>: [Indigo]OoradoBooting.press. Describes how to boot a Dorado, and how to
configure it to boot in various ways.
[14]: Myer, T. H .. and Barnaby. 1. R. TENEX Executive Language Manual for Users. Available
from Arpa Network Information Center as NIC 16874, but in the relatively unlikely event
that you need one. borrow one from a Tenex wizard.
<15>: lMaxc]BCPL.press. The reference manual for the BCPL programming language.
<16>: [Maxc]OS.press. The programmer's reference manual for the Alto Operating
System.
including detailed information on the services provided and the interface
requirements.

1983 EDITION

THE BRIEFING BLURB

27

<17>: [Maxc]Packages.press. A catalogue giving documentation for the various BCPL
packages that other hacker's have made available.
[18]: James G. Mitchell, William Maybury, and Richard Sweet. Mesa Language Manual. Version
5.0. blue-and-white report CSL-79-3. A cross between a tutorial and a reference manual.
though much closer to the latter than the former.
<19>: [Ivy]Doc)Compiler60.press. Describes the changes in the Mesa language and the
compiler that occurred in. moving from Mesa 5.0 to Mesa 6.0.
[20]: Morris. J. H. The Elements of Mesa Style. Xerox PARC Internal Report, June 1976.
Somewhat out of date (since Mesa has changed under it), but a readable introduction to some
useful program structuring techniques in Mesa.
[21]: Adele Goldberg and David Robson. Smalltalk-80: The Language and Its Implementation.
book published by Addison-Wesley. 1983.
[22]: Warren Teitelman. Interlisp Reference Manual. Published in a blue and white cover.
although not officially a blue-and-white. October. 1975.
[23]: The Interlisp-D Group. Papers on lnterlisp-D. blue-and-white report CIS-S (also given the
number SSL-SO-4), Revised version. July 19S1.
[24]: L. Peter Deutsch and Edward A. Taft. editors. Requirements for an Experimental Programming
Environment. blue-and-white report CSL-So-I0.
<25): [Indigo]Documentation>Manual.df. Hardcopies are entitled The Cedar Manual.
[26]: Alto User's Handbook. Internal report, published in a black cover. The version of September,
1979 is identical to the version of November. 1978 except for the date on the cover and title
page. Includes sections on Bravo. Laurel. FTP. Draw, Markup, and Neptune
<27): [Maxc]systemname.TTY.
and these files are sometimes more recent than SubSystems.press.
[28]: Jerome. Suzan. Bravo Course Outline. Internal report, published in a red cover. Oriented
to non-programmers.
<29>: [Indigo]TiogaDoc.tioga. or TiogaDoc.press. How to use the Tioga
editor.
<30>: [Maxc]: [Maxc]: [Maxc]PDPrintOps.press. Describes the PDPrint printing program.
[33]: Andrew D. Birrell, Roy Levin. Roger M. Needham. and Michael D. Schroeder. Grapevine:
an Exercise in Distributed Computing. blue-and-white report CSL-82-4.
<34): [Ivy]Maintain.press. Documentation for the teletype version of Maintain. the version
that is used from within Laurel or Tajo.
[35]: Douglas K. Brotz. The Laurel Manual. blue-and-white report CSL-SI-6.
[36]: Eric Emerson Schmidt. Controlling Large Software Development in a Distributed Environment.
blue-and-white report CSL-S2-7.
(7): [Indigo]Documentation>DFFilesRetMan.press. The reference manual for the use of
OF files.
<3S): [Indigo]Documentation)ReleaseProcedures.press.
Describes the policies and
procedures that individuals who contribute to Cedar releases need to understand and observe.
(9): [Indigo]Docs)Ho~ToUseCSLNotebook.press.

1983 EDITION

2

A Glossary of Terms, Subsystems, Directories, and Files
(and acronyms. protocols. and other trivia)
Try reading me in Tioga, using the "De'" command to get around!

abstract machine: A set of low-level functions and capabilities. provided by some combination of
hardware and software. that forms the underpinnings of a system sitting above. For example.
the [nterlisp~O system~ which runs on various machines. consists of a lot of
machine-independent stuff sitting on top of a small amount of machine-dependent code. The
goals of the machine-dependent part were specified by describing an abstract machine that it
must implement. As another example. part of the Cedar project has been the specification
of a "Cedar computer" as an abstract machine.
Alpine:
A transactional file server being built within CSL for use by database systems
and other distributed computing applications. Alpine is being built on top of Cedar, and will
help support the FS file system.
Alto: (On its way to being archaic.) A small personal computer with a bitmap display and mouse.
designed at P ARC; the precursor to D-machines. See the blue-and-white report titled "Alto:
A personal Computer", number CSL-79-11.
Alto world:
An environment created by running an Alto emulator on a O~machine.
Alto FontGuide.Press:
A file. available on [lndigo) pairs associated with it, called its property list.
bank: A unit of measurement of primary storage in an Alto world. equal to 64K 16-bits words, that
is. 128K bytes. An Alto II has four banks. while Oorados have at least eight.
bar: A generally thin. generally rectangular. generally invisible region of the screen in which certain
generally display-related actions occur. e.g.. the scroll bar. the line-select bar.
baseboard:
A microcomputer that lives on the lowest printed-circuit board of a Dorado. The
baseboard listens to the terminal's boot button. and to various thermometers. Its job is to
supervise the rather complex booting sequence necessary for bringing a Dorado up from a
cold start. The baseboard announces its state to the outside world by flashing a number
(encoded in unary) on a little green light on the Dorado chassis. Signs near each bank of
Dorados explain what various numbers of flashes mean.
Bayhil1:
Another name for Building 96. occupied by part of SOD. The Bayhill building
is located on Hillview just before it runs into Arastradero.
BCD: A compiled object program module in Mesa or Cedar: an acronym for ~inary ~onfiguration

3

Qescription.
BCPL:

A free-wheeling and type less system programming language used as the
environment for much early Alto programming. Also. the compiler for that language.
BFS: An acronym for Basic File System: the contents of a disk or partition used by an Alto world.
Also a standard software package for low-level management of an Alto file system.
BC~'s export services to their clients, and. in tum. import various services from
Binder:
other BC~'s. The process of resolving these inter-module references is called binding. and
the Binder is the program that does it. Actually, the loader can handle many of the easy
cases of binding on the fly, as part of the loading process: but for complex stuff, you need
the Binder. The Binder accepts compiled modules (with extension ".bcd") and binding
instrutions in the form of a configuration description (with extension ".config"): it produces
another ".bed" as output.
BITBLT:
(pronounced "bit-blit"). A complex instruction used for moving and possibly
modifying a rectangular bitmap. The "BLT" part is an acronym for BLock '!ransfer.
bitmap:
Generally refers to a representation of a graphical entity as a sequence of bits
directly representing image intensity at the points of a raster. The display hardware and
microcode on an Alto or D-machine process what is essentially a bitmap of the image to be
displayed. At PARCo bitmaps are nonnally stored word-aligned, and in row-major order.
blue-and-white:
A report that has been cleared for distribution outside Xerox. and published in
a blue and white cover. Such reports have identifying numbers formed by concatenating the
laboratory acronym, the year. and a small integer. One of my favorites is the Laurel Manual,
by Douglas K. Brotz, number CSL'81-6: I especially recommend Chapter 6. CSL
blue-and-whites are stored on bookshelves in the CSL Alcove. A list giving the titles and
numbers of all of the blue-and-whites is available from the PARC Library.
boot: Short for "bootstrap", which is in tum short for "bootstrap load". Refers to the process of
loading and starting a program on a machine whose main memory has undefined contents.
boot button:
The small button behind the keyboard used (sometimes in conjunction with the
keyboard) to boot some program into execution. On Dolphin's or Dorado's, there are other
more potent boot buttons on the chassis, in addition to the boot button behind the keyboard.
A file that contains a bootable program. Used to start Cedar. as well as various
boot file:
games and other useful programs available from the NetExec in the Alto world.
boot server:
A computer on the network that provides a retrieval service for certain stand-alone
programs (which are encapsulated as boot files). See NetExec.
bootlights:
(archaic) A screen pattern resembling a city skyline. Occurs occasionally in the
Alto world when some erroneous unanticipated condition arises, e.g., getting a parity error in
a BCPL program on a disk that doesn't have Swat.
Bravo:
(archaic) An integrated text editor and document formatting program that runs
on the Alto; a vital program that nevertheless is no longer maintained or supported.
BravoBug:
(archaic) A program used when Bravo crashes to replay the editing actions up
to the point of the crash.
BravoX:
A successor to Bravo written in Butte with somewhat greater functionality and a
somewhat richer interface. Warning!: BravoX source tiles are stored in a weird and wonderful fonnat that
almost NO programs other than BravoX
(perhaps?) Dolphins.

can handle. Also. BravoX runs. at the moment, only on Alto II's and

break page:
A header page that divides one printed file from another in the output of a
Spruce printer. If Spruce encountered any difficulties during the printing run, it will inform
you of them on the break page.
Bringover:
A program that retrieves files from remote file servers to one's local disk:
Bringover reads ...df' files in order to figure out what versions of what files should be

4

retrieved, and where in the great wide electronic world they might be found. Use of Bringover
(confusing as it may be at the outset) is to be recommended over use of either FTP (in the
Alto world) or the FileTool (in Cedar), since the version control and system-description
features of ".dr' files are very valuable.
bug: A computing term for a non-feature, something that is not as intended. Sometimes used in
a different sense to refer to the act of pointing at something with the mouse, and then clicking
a mouse button; but this usage is frowned upon by 100% of our Usage Panel (namely me:
I recommend using the verb "click" instead in this context. since I think that "bug" is already
an overloaded word).
bug award:
Refers to a occasional custom within CSL and ISL wherein those brave souls
responsible for ferreting out the cruelest and most intricate bugs in critically important systems
are rewarded for their efforts by being presented with a cute little bug-shaped sticker that
they can then display on their office nameplate or elsewhere. A bug award is the moral
equivalent of a gold star. If the sticker consists of a background from which a bug has been
excised. then the award is an "inverse bug award". and serves to praise its recipient for
producing code that is notably free of insect infestations.
BugBane:
A package that implements the basic primitives necessary for high-level debugging
in the Cedar world; the User Exec is a client of BugBane, and. in turn, provides debugging
services to users of Cedar.
Building 32:
A part of OSO, located on Hanover Street. north of Page Mill. Once called
PARC·place, when it was occupied by parts of PARe.
A part of PARC, located on Hillview, just across Coyote Hill from the Building
Building 34:
35, the home of the ICL.
Building 35:
The main building of PARCo located at the intersection of Coyote Hill and
Hillview. The site of the cafeteria.
Building 37:
A pan of PARC, located on Hanover Street, north of Page Mill. and just south
of Building 32. The site of the CSL Electronic Model Shop.
Building 96:
A part of OSO, located where Hillview runs into Arastradero; also called the
Bayhill building. Current home of some parts of SO~.
Butte:
A compiler for BePL that outputs Mesa-style byte codes instead of Nova
assembly code; also. the byte codes themselves. and the microc::ode that implements them.
button:
A small area on the screen that reacts when clicked with the mouse. In Viewers.
buttons are rectangular areas labelled with a word or phrase; they are organised into menus.
byte code:
Lisp, Mesa, Cedar. Smalltalk. and Butte at PARC compile into directly executable
languages that are stack oriented. and whose op codes are usually one byte long. Such an
instruction is called a byte code. These byte codes are in tum interpreted by special microcode
on each of our various machines.
Cabemet:
A particular mail server that is part of the Grapevine distributed transport
mechanism. located in the CSL machine room.
caret: A blinking pointer, indicating where keyboard characters will appear when typed
catch phrase:
A chunk of Mesa or Cedar code that is prepared to handle a certain type of
exceptional condition. The best of way to think of a catch phrase is as the body of a
procedure variable that is dynamically bound. Such procedures variables are called signals.
If you suspect that an exceptional condition might arise. and you think that you knows what
to do if it does, you specify this response as a catch phrase; that is. you bind a procedure
value to the signal. which is a procedure variable. If any procedure that you call notices that
the condition has in fact arisen. it will notify the world by "raising the signal". which should
be thought of as a procedure call to the catch phrase that you specified. (This method of
explaining signals is a minor facet of the religion esposed in the CLRM.)

5

Cedar:

A large project in CSL to build a programming environment for CSL's future
applications. Also the name of that environment. Also the name of the programming
language upon which it is built. The Cedar language is a variant of Mesa augmented by
garbage collection, atoms, and run-time types. The design of the Cedar environment was
strongly influenced by the programming environment and services available in Interlisp and
Smalltalk. For a discussion of the goals of Cedar. see the blue-and-white report titled
"Requirements for an Experimental Programming Environment", number CSL-80-1O.
CedarGraphics:
A subroutine package of graphic primitives, built within ISL, that forms an
important part of Cedar. Its design was heavily influenced by the results of experimental
systems written in JaM.
Chardonnay:
A Grapevine server.
Chat: A program that provides teletype-like "interactive" access to a remote computer on the
network. Most programming environments include this capability in some form: both Alto
and Cedar include programs actually named "Chat". Chat is mainly used to communicate
with Maxc and IFS servers.
Checkpoint:
A method used in Cedar to preserve the state of your computing world. Taking
a Checkpoint involves preserving a shapshot of the current state of the virtual memory, but
not of the file system. If. after taking a Checkpoint, something bad happens and your Cedar
system gets wedged, the command RollBack will return you to the earlier clean state of your
virtual memory; but changes to the file system made between the Checkpoint and the
subsequent RollBack, such as storing edited versions of files, will not be undone.
Cheshire:
A subsidiary of Xerox. They make a machine that binds stacks of paper into
booklets by melting glue and letting it be absorbed by the edges of the paper. There are
Cheshire binders in CSL and in the PARC TIC.
Chromalin:
The trade name of a fancy color printing process used with the PlateMaker for
creating high-resolution color prints from Press files or PO files.
Chipmunk:
A O-machine Mesa program for interactively creating and editing integrated
circuit designs. Chipmunk makes use of a color display in addition to the normal
black-and-white one. It is a successor to Icarus.
Cholla:
A Laurel-based IC fabrication line control program. which is used in ICL.
CIFS:
An acronym for ~edar !nterim ~il.e ~ystem. CIFS is currently used within Cedar
to manage a portion of the local disk as a cache containing readonly copies of remote files.
This function and others will someday be provided by FS. CIFS was the first CSL system
to allow the components of a hierarchical file name to be separated with simple slashes instead
of with square brackets and angle brackets: the clumsier brackets are being used in this
document (sigh) for compatibility with the past.
CIS: An acronym for Cognitive and Instructional Sciences Group. A part of PARC, and the home
of many of the builders of Interlisp-O.
Clearinghouse:
The analog of the Grapevine registration database in the NS world That is. a
machine running Star talks to the local Clearinghouse in order to find out how to talk to a
particular file server or print server.
click: A manipulation of a mouse button. Pushing and releasing a mouse button several times in
quick succession is sometimes called a "double-click", "triple-click", etc. as appropriate. The
phrases "click-hold" and "double-click-hold" are also sometimes heard.
client:
A program (as opposed to a person) that avails itself of the services of another
program or system. Laurel is a client of Grapevine. See user.
Clover:
A Dover located in CSL.
CloverFonts.Press: A file, available on [lndigo). that lists by family name, face, size, and
rotation all of the fonts in C1over's font dictionary. That is, this file lists the fonts that you

6

can print with; for the fonts that you can see on your screen, see AltoFontGuide.Press
instead. To see the characters of the fonts in all their glory, check out the book located on
top of Clover called CloverCharacters.Press.
CLRM:
Acronym for the Cedar Language Reference Manual. This document isn't exactly
easy bedtime reading, but it is the most authoritative description currently available of the
behavior of Cedar programs in interesting and subtle cases. The CLRM also attempts to
convert you to a particular religion regarding the proper design of a polymorphic language
within the Algol tradition. To get the good dope about current Cedar without spending the
time necessary to undergo religious conversion, skip immediately to Chapters 3 and 4 of the
CLRM.
CoCedar:
A world-swap debugger for Cedar.
color display:
A CRT display with red, green, and blue phosphors. Griffin and Chipmunk both
use the color display, and the color display is also available to users of Cedar with a minimum
of hassle through the good auspices of the Cedar ColorDevice. The public Dorados with color
displays are listed at the sign-up sheets.
ColorDevice:
A component of Cedar that provides low-level support for a color display.
Com.cm:
A file used by the Alto Executive to store the current command being executed.
See Rem.cm.
Commander:
A "tight-weight" command interpreter. providing the minimum of functionality
needed by Cedar implementers while they are developing a new release of the system. Most
users of Cedar can instead enjoy the more plentiful features of the UserExec.
component:
Among many other things, a chunk of software that is distributed as part of a
Cedar release.
config:
A source file that tells the Binder how to assemble modules into a complete
system.
CoPilot:
A world-swap debugger for Pilot.
Copy Disk:
A stand-alone program used to transfer an Alto BFS, that is, the entire contents
of an Alto disk or partition. May be used between computers or on a single computer with
multiple disk drives.
create date:
When said of a file, the date and time that the information contained in this
particular version of this particular file was created. Create dates are generally stored accurate
to the nearest second. This makes them sufficiently unique that the pair  can serve as a unique identifier for a particular pile of bits.
Proof that you are who you say you are; usually your Grapevine R'name and
credentials:
the corresponding password.
CSL: Acronym for Computer Science Laboratory, a part of PARC, located on the second floor of
Building 35. CSL Notebook:
A mechanism for distributing, indexing, and generally sharing the documentary
output of folk in CSL.
cursor:
A small picture on the display that tracks the motions of the mouse.
Cypress:
A database package based upon an entity-value-relationship model of data, and
written in Cedar. Walnut, Hickory, and Squirrel are clients of Cypress.
D-machine:
A generic name. referring to any of the current mctchines within Xerox that
implement the PrincOps architecture: Dandelions. Dicentras. Dolphins. and Dorados are the
primary D-machines.
DO: (,'D-zero", not "00") An obsolete name for the Dolphin, aD-machine.
Daffodil:
An inexpensive D-machine using custom VLSI, being designed by local folk.
Since the Daffodil may become the hardware base of future OSO products, certain details
concerning the Daffodil project are rather sensitive.

7

Daisy:
A Dover located in the Bayhill building.
Dandelion:
The name of the processor that is in the Star products; an example of a
D-machine.
dead: Either not currently operational (said of a piece of hardware), or operational but not currently
undergoing continued development and support (said of bodies of software).
Dealer:
The name of CSL's weekly meeting, occurring on Wednesday afternoons from
1:15 until 2:45 (or so); also used to refer to the person speaking at that meeting. Giving such
a presentation is referred to as "giving a Dealer" or sometimes "Dealing". See also weekly meeting.
An Alto subsystem providing
DDS: (archaic) Acronym for Descriptive Directory System.
sophisticated manipulation-of the Alto "t1le directory system. See also Neptune.
DF files:
" A collection of programs for describing the files needed to build a complicated
system, for automatically retrieving these files from remote tile servers to the local disk
(Bringover), and for storing them back later (SModel). Unlike the more grand and glorious
system models to come, OF files primarily addresses the problems engendered by our current
feudal collection of file systems. The letters "OF" are an acronym for Description Files, which
suggests that the phrase "OF files" is redundant.
.
Dicentra:
A recent and inexpensive D-machine. The Dicentra essentially consists of the
Dandelion'S CPU squeezed onto one Multibus card. and communicating with memory and
with 110 device controllers over the Multibus.
dirtball:
A small, perhaps struggling outsider; not in the major or even the minor leagues.
For example, "Xerox is not a dirtball company".
distribution list:
A list of R-names to which mail can be addressed. In some cases, Maintain can
be used to add oneself to interesting DL's, such as "MesaFolklore1'.pa". If Maintain responds
that you aren't allowed to do that the correct recourse is to send a polite message to
"Owners-MesaFolkloret.pa", asking that they please add you to their list. For more details
about distribution lists. try either the Laurel manual or the document
[Ivy]Maintain.Press. which describes the Alto and Tajo versions of Maintain.
DiskDescriptor:
A file that contains the disk allocation information used by an Alto file system.
DL: Acronym for Distribution ~iSL
DLS: Acronym for Data Line Scanner: an Alto equipped with lots of modems plus other hardware
and microcode to allow dialing into and out of the Internet.
DMT.boot:
Acronym for Display Memory Tester. A memory diagnostic for the Alto world.
DMT is automatically booted from-the network by the Alto Executive after the Alto has
been idle for about 20 minutes. DMT accepts vanous commands: try pushing the "s" key. and also try
typing shift-swat. Designing cursors for DMT IS a popular sport: send your suggestion as a list of 16 octal numbers
to David Boggs (Boggs.PA). along with a suggested tItle line and an indicatIon of whether you want to. be credited
by name.

Dolphin:
A D-machine; once called the DO. More flexible than a Dandelion, but also
slower and more expensive.
Dorado:
A high-performance D-machine, designed by CSL and coveted by all and sundry.
See the blue-and-white report titled "The porado: A High-Performance Personal Computer",
number CSL-81-l.
Dover:
Generic name for a type of 384 bpi laser-scan printer built on the Xerox 7000
xerographic engine and connected to an Alto by means of a Orbit interface. Successor to
EARS. Dovers are normally driven by the progr~ Spruce.
Dragon:
Generic name of a new, custom-chip processor being designed by a team 'in
CSL; it is hoped that the Dragon will satisfy our ambitions to have "a Dorado in a shoe
box".
Draw:
(archaic) An Alto subsystem that permits interactive construction of pictures

8

composed of lines. curves, and text Draw users may be interested to note that a program
ReDraw exists that converts Draw source files into Press files that will print without the
jaggies on a Dover. Users of Alto emulators on D-machines must use DDraw and ReDDraw
instead.
Dumper.boot:
(archaic) A file used for desper;:ttion debugging in an Alto world. Dumps (most
ot) the current core image to Swatee for subsequent inspection by a debugger.
DWIM:
Acronym for Do What I Mean: a facility intended to help the programmer by
making LISP do what you mean, rather than what you say.
EARS:
(archaic) Acronym for Ether Alto Research SLOT. An obsolete prototype
laser-scan printer built on the Xerox 7000 xerograPhic engine and equipped with a hardware
character generator. ((nteresting to some as an example of a third level acronym: the S in EARS stands for
SLOT. and the L in SLOT stands for LASER. and LASER itself is

a~

acronym!)

EditTool:
A menu-oriented command interface to the Tioga editor. providing complete
access to Tioga's functionality, including the commands that you can't type (either because
they can't be typed. or because you have forgotten how to type them).
EFTP:
A venerable PUP-based protocol now mostly used to transfer print files to print
servers.
An arm of CSL located on Hanover street in Building 37: this
Electronic Model Shop:
group of folks do small-scale production runs of computer equipment for CSL. Frequently
called the Garage.
EmPress:
An Alto subsystem used to convert text files to Press format and ship them to a
Press print server.
emulator:
A technique in which one computer is programmed to imitate another. Fast
imitations are called emulators, while sufficiently slow ones are called simulators.
EOS: Acronym for Electro-Optical Systems; an organization located in Pasadena that was formerly
a part of XerOX. The-defense contracting portion of EOS was recently sold by Xerox for 40
megabucks. The portion of EOS that built Scientific Information Systems is now SIS; they
are the ones who are marketing D-machines running Interlisp and Smalltalk to the outside
world.
Ernestine:
A particular Lily server located in Building 35.
Ethernet:
The communication line connecting many computers (with compatible interfaces)
together. Strictly speaking, an Ethernet is a single. continuous piece of co-axial cable, but
the term is sometimes applied to the entire network accessible through the cooperation of
Gateways (which is more correctly called an InterNet). Ethernets come in two flavors: the
original Ethernet. now called the Experimental Ethernet, was built within PARC and runs at
3 MBits/sec. The Ethernet that has been proposed as a communication standard is a
re-engineering that runs at 10 MBits/sec. PARC currently has Ethernets of both these flavors
running around. as well as a special 1.5MBits/sec Ethernet used by the EtherPhones. See
the blue-and-white report titled "The Ethernet Local Network: Three Reports", number
CSL-80-2.
EtherPhone:
A box of magic widgets that can replace your office telephone. giving you much
greater functionality by taking advantage of the power of computing in general, and-of your
personal multi-function workstation in particular.
An EtherPhone has a microphone, a
speaker, digital-to-analog and analog-to-digital converters. a connection to Ma Bell, an Ethernet
interface, and several microprocessors to tie them all together. The EtherPhone is a recent
product of the Voice Project within CSL. The existence of the EtherPhone should make it
easy to write lots of exciting experimental systems (any volunteers to write a CedarVoice
interface?).
Executive:
A distinguished Alto subsystem that provides simple commands to inspect and
manipulate the file system directory. and to initiate other subsystems.

9

export:

A Mesa or Cedar program that provides (either some or all ot) the services
described in an interface is said to export that interface.
tile extension:
The portion of a file name that appears following a period (possibly null). By
convention. a number of extensions are reserved to indicate the type of data in the file. though
not all subsystems are consistent in their use of extensions. Some commonly encountered
extensions are:
an Alto Executive command (not really an extension)
.al:
screen font rasters in the original format
.bcd: Mesa object program module
.bcpl: BCPL source program module
.bfs: an entire Alto file system gathered into a file
.boot: program invokable by booting
BCPL object program module
.br:
.bravo:
text file containing Bravo formatting information
.cm: Executive command file
.config:
Mesa source that describes how to combine modules
.df: description of a system for use with OF files software
.dl:
distribution list (in a file as opposed to in Grapevine's database)
.dm: (archaic) dump file. Le.• several logical files stored as one
Swat error message file
.errors:
.icons:
file containing displayable Icon images
.image:
executable Alto/Mesa program
.jam: JaM interpretable code
.ks: screen font rasters in a fancy format
.laurel:
special flavor of .bcd that can be run within Laurel
.log: history of certain program actions
.mail: Laurel mail file
.mail-dmsTOC:
Laurel table-of-contents file
.mesa:
Mesa source program module
.pd: file in PO (= printer dependent) print file format. usually produced from an Interpress
master
.press:
print file in Press format
.profile:
records a user's preferred values of various user interface parameters in
Cedar
.run: executable Alto program. that is. a subsystem
.sil: SIL source file for a drawing
Smalltalk source program text
.st:
.strike:
screen font rasters in a compact and efficient but limited format
.style: Tioga document style rules for formatting
.symbols:
Mesa symbol table (for debugging)
.syms:
SCPL symbol table (for debugging)
.tex: TEX source text
.tfm: font metric information
.tip: TIP interaction description
.tioga:
Tioga text document

10

file name:
See file extension and path name for information about the local conventions for
file names.
file server:
A computer on the network that provides a file storage and retrieval service.
MAXC, IFS. and Alpine are three different types of file servers.
FileTool:
A program in Cedar that allows the user to store and retrieve files from and to
remote file servers. Use of the FileTool to retrieve portions of large systems to one's local
file system is fraught with peril. since it is quite important that one retrieve consistent versions
of things if the large system is to work, and the FileTool doesn't include any scheme of
version control. Cautious programmers use Bringover and ".dr' files from the beginning;
everyone uses Bringover and ",dr' files eventually.
FLG: (pronounced "flug") In LISP programs, a switch that customizes a program's behavior to an
individual user's working habits.
fog index:
A measure of prose obscurity. Units are years of education required in order to
understand the measured prose.
font: An assortment of characters all of one size and style: more precisely. a mapping from a set
of character code numbers to a consistent collection of graphic images.
Fonts.widths:
A file containing character-width information for a large number of fonts. Used
by some programs that do text formatting while producing Press files. The standard source
is [Indigo)Fonts. Widths. Other programs appeal to separate" .tfIn" files, one for each
font, as their source of information about character metrics.
roo: The first meta-syntactic variable. The second is "bar". There is a tie for third between "fum"
and "baz". The words "foo" and "bar" are cognates, both derived from "fubar", an acronym
popular in the U.S. Navy and used by early computer programmers employed by the Navy.
possibly as a technical term describing the state of a system.
Football:
A two-person game in Cedar.
format:
An attribute of a node in a Tioga document Examples might be "long quotation",
or "item in a bulletted list". The effect of the various formats is defined by the style.
FS: A file directory system that will emerge in Cedar along with the Nucleus; FS will replace
CIFS and the Common Software Directory (a part of Pilot).
FTP: Acronym for File Transfer Protocol (or Program). An Alto world program that provides a
convenient user interface to -the file tranSfer protocol. enabling the transfer of files between
co-operating computers on the Internet.
Garage:
A nickname for the Electronic Model Shop, a part of CSL.
Gateway:
A computer serving as a forwarding link between separate Ethemets. Gateways
may also perform certain server functions. ~uch as name lookup.
germ: A small part of Pilot that runs first: the germ handles bootstrap loading. inloading and
outloading memory images during worldswaps, teledebugging, and the like.
Grapevine:
.
The distributed electronic message transport system: it has a set of protocols all
its own, and provides various server functions such as authentication. See the blue-and-white
report titled "Grapevine: an Exercise in Distributed Computing", number CSL-82-4.
Griffin:
A Mesa illustration program. a successor to Draw. Excellent on filled areas. and
handles color. Griffin was the source of many of the pretty pictures hanging near Lilac.
group:
(when referring to Grapevine) A set of R-names. The standard interpretation
of a group is a distribution list. For example, CSLt.PA is the group of all people in CSL,
in c~ they all should. get copies of a message. Groups can also be used for other purposes.
such as access control. The R-names that constitute a group are called its members. In
addition, a group has friends and owners: a friend is someone who may add or delete herself
from the group, while an owner may add or delete anyone from the group.
Hardy:
A Tool that provides the functionality of Laurel. that is, mail sending and

11

receiving, within Tajo: a client of Grapevine.
Hickory:
A reminder and calendar system based on the Cypress database in Cedar.
Hornet:
Generic name for a family of 300 bpi laser-scanned printers, built on top of 2600
copiers.
Ibis: An IFS server in SDD/Palo Alto.
Icarus:
(archiac) An Alto-based program for creating and editing integrated circuit
designs graphically and interactively.
icon: A small image representing some concept. Used extensively in Star and Cedar.
Idun: An IFS server in SDD/Palo Alto: the home file server of the Pilot group.
ICL: Acronym for !ntegrated 9rcuit haboratory, a part of PARC, located in Building 34.
IDL: Acronym for Integrated Design Laboratory. an incipient part of PARe. Once formed. IOL
(to be pronounced "ideaF rather-than "idle") will be located somewhere in Building 35.
IFS: Acronym for Interim File System. An Alto-based file server. Many IFS servers exist on
various Ethemets, including-Ivy, Indigo, Ibis, Iris, Idun, Igor, Phylum. and Erie.
IFU: Acronym for !nstruction ~etch ~nit: many computers have them.
Igor: An IFS server in SDD/Palo Alto: the home file server of the Mesa group. This name
should be pronounced "Eye-gore", as in the movie Young Frankenstein
Imager:
A new implementation of the CedarGraphics package that is under development
implementation module:
A Mesa or Cedar module that actually provides a set of services, as
opposed to an interface module, which simply specifies exactly what those services are to be.
Indigo:
An IFS server in PARC, used by CSL and ISL to store project software files.
[Indigo):
A directory on which documentation for various Alto subsystems
are stored (generally with extension .press).
[IndigoJ:
A directory on which screen fonts for the Alto are stored (extensions
.al, .strike, or .ks). Subdirectories are used on this directory to distinguish various families
of display screen fonts that have accumulated over the years.
[Indigo):
A directory on which the standard starting configurations for Alto
disks are stored. as files with extension ".bfs". The normal way to initialize a new Alto world
is to use Copy Disk to retrieve one of these disk images.
[Indigoj: A directory containing the Cedar source code and documentation.
[Indigo)DocumentatioO>:
A directory containing the on-line documentation for
the latest version of Cedar.
[IndigojTop~:
A directory containing top level .df files for components of the
current Cedar release.
[Indigo): A directory containing various documents of printing interest including
Fonts.widths. You might be interested in CloverFonts.Press, or AltoFontGuide.Press.
[Indigo):
A directory of packages released by ISL for use within Cedar. Contains mainly
interactive graphics software and document formatting tools.
[Indigo):
A development directory for [Indigo): that is, this is where
components of a new release of Cedar are stored while they are being developed. One of the
jobs of the release process is to move things from  to : The analogous development directory for [Indigoj.
input focus:
Suppose that the user types a key, while operating in an environment that
supports multiprogramming-lots of things going on at once, each in their own window..
Which program was the keystroke intended for? Different systems have different conventions
on this important point. In Tajo, the window in which the cursor is currently located gets
the keystroke. But in several other systems, including Cedar, there is a concept called the
"input focus" that is passed around among the running programs: whatever program has the

12

input focus gets the keystrokes. Left-clicking a mouse button inside of a window often has
the side effect of giving that window the input focus.
Inscript:
A mechanism for keeping track of user input to a program in a general way (key
strokes, mouse clicks, and the like), used within Cedar.
install:
A term applied to the Alto Operating System and a number of subsystems
(notably Bravo), referring to a procedure whereby certain configuration options are established.
Frequently. what is really going on is that the program being installed is salting away somewhere the current hard
disk addresses of the pages of important files. so that later access to those files can avoid the tedious operations of
looking up the file in a directory and chaining through disk headers to get to the right place within the file.

Intelnet:
The Xerox corporate phone system, accessible by starting your dialing with the
digit S. Not to be confused with the Internet.
interface:
A formal contract between pieces of a system describing a collection of services
to be provided. A provider of these services is said to "implement the interface"; a consumer
of them is called a "client of the interface",
interface module: In Mesa and Cedar, interfaces are written down as a special kind of source file,
starting with the word "DEFINITIONS" instead of "PROGRAM". This explicit encoding
of an interface is called an interface module.
Interlisp:
A dialect of Lisp with a large library of facilities, as witnessed by Interlisp's
famous IS-pound reference manual (would that Cedar were so well documented!).
Interlisp·D:
An implementation of [nterlisp on D-machines. done by a group within PARCo
It provides network facilities and high-level graphics primitives. See the blue-and-white report
entitled "Papers on Interlisp-O", number CIS-S (SSL-SO-4) Revised.
Internet:
Many Ethernets connected by Gateways form an Internet
InterPress:
A print file format standard that is currently under development: a second cut
at the same issues addressed by Press format.
InterScript:
A standard format for the interchange of editable documents that is currently
under development.
Iris: An IFS server in SDD/Palo Alto, which serves as the official source of released Pilots.
ISL Acronym for Imaging Sciences Laboratory, a part of PARC located on the second floor of
Building 35. Ivy: An IFS server in PARC, used by CSL and ISL mainly to store personal files.
jaggies:
The annoying sharp comers visible when smooth curves are imaged on a raster
device without sufficient resolution.
JaM: Acronym for lohn (Warnock) and Martin (Newell). An interactive language, similar to the
language Fortil, with a simple, stack-oriented execution model: equipped with lots for graphic
operations as primitives; implemented in Mesa.
JaMGraphics:
A component of an ISL release which provides JaM commands for all the
CedarGraphics features. Creating laM pictures with laMGraphics can be very addictive.
Jedi: A Hornet at PARe.
Juniper:
(archaic) An Alto-based distributed file system, built within CSL.
Juno: A constraint-based system for interactive graphics in Cedar.
junta: A technique for eliminating layers of the Alto Operating System that are not required by a
particular subsystem.
Kanji:
A Dover in Building 34.
Klamath:
A forthcoming version of Pilot and other Mesa system software.
Lampson:
A unit of speech rate. 1 Lampson is defined to be Butler's maximum sustained
speed. For practical applications. the milliLampson is a more appropriate unit.
Larch:
A family of specification languages.

13

Laurel:
An Alto-based, display-oriented program that provides access to the facilities of
Grapevine for sending and receiving mail. Succeeded by Walnut in the Cedar enviroment.
Leaf: A page-level file access protocol supported by some IFS's.
level: There is a tree structure imposed upon the nodes that make up a Tioga document. and the
Tioga editor can be informed to suppress the display of all nodes deeper than a certain level.
In combination with scrolling, the levels commands in Tioga provide a convenient way to
navigate in a well-structured document.
level i system:
(for i E [1..3]). A terminology for classifying (software) systems according to
their intended user community:
1

implementers only

2

implementers and friendly users

3
naive users
Librarian:
A Tajo program for check-in/check-out of the modules of a large Mesa system,
used in SOD; also, a server for this program.
Lilac: A Puffin located in CSL, right next to Clover.
Lily: A program that provides teletype-style access to the mail sitting in one's Grapevine mailbox.
Lily is designed to help out those folks who, because of travel or whatever, are unable to use
their personal computers and either Laurel. Hardy, or Walnut. Also, a server that runs this
program.
logical volume:
A portion of a physical volume that is being used to support a Pilot environment:
the Pilot equivalent of a partition.
look: An attribute of a character or string of characters in various editors, including. Bravo and
Tioga. "Bold" and "italic" are examples of Bravo's typographic looks, while "emphasis" and
"quotation" are examples of the functional looks espoused by Tioga. The meaning of looks
in Tioga, like the meaning of formats, is defined by the style.
Loops:
A layer of software on top of Interlisp that turns it into an object-oriented
environment tailored for building rule-based expert systems.
Lotus:
Internal development name for the 1075 Xerox copier.
Lupine:
The translator used to generate RPC stubs so that Cedar modules can call
procedures located on remote machines.
Maggie:
A tape server; that is, a machine on the Internet with tape drives that it will let
a requesting machine use.
Magic: ,
Acronym for Multiple Analyses of the Geometry of Integrated Circuits. A
system for dealing with VLSI designs: printing them, converting- them among formats,
examining them with various programs.
A. program for updating Grapevine registration information. There are two
Maintain:
versions of Maintain. One, with a widely reviled teletype-style user inteface, is available
within Laurel, or as a Tool in Tajo. It is documented in the file [Ivy]Maintain.Press.
The other, with a nifty buttons-style interface. is available in Cedar. It is not yet documented.
MakeConfig:
A program that reads Mesa configs and bcds and produces a collection of
commands that will compile and bind the many modules of a system in the correct manner
to build a consistent system.
Marion:
A Librarian server in SOD/Palo Alto.
Markup:
A dead Alto subsystem for editing Press files.
MAXC:
Acronym for Multi-Access Xerox Computer (pronounced "Max"). A locally
produced computer that is functionally sunilar to-the DEC PDP-lO. At one time, there were
two MAXC's, named Maxe! and Maxc2, but Maxe! has gone away forever. From now on,

14

"Maxcl". "Maxc2", and "Maxc" are aU names for the same machine, which used to be called
Maxc2.
[Maxc]:
A directory on which standard Alto (BCPL) programs and subsystems are stored.
Only object code files (extension .br) and runnable flIes (extension .run) are stored here:
source files and documentation are stored on [Maxc] and [Maxc),
respectively.
[Maxc):
A directory on which documentation for Alto programs is stored.
Common extensions are .press (for files directly printable by Press or Spruce), and .tty (plain
text).
'(Maxc):
A directory on which source versions of'standard Alto programs are
stored.
[Maxc]:
(archaic) A directory containing flIes that are usable as templates (in Bravo)
for various kinds of documents (e.g., memos. letters. reports).
(Maxc): A directory containing Alto printing and graphics programs.
[Maxcj:
A directory containing documentation related to printing and
graphics facilitles such as Press files and font file formats.
(Maxcj: A directory containing standard TENEX subsystems.
Menlo:
A Dover located in ISL.
menu: A collection of text strings, buttons, or icons on a display screen generally used to represent
a set of possible acdons.
Mesa:
A PASCAL-like. strongly typed, system programming language developed by
CSL and SOD.
Mesa Development Environment:
The package of software used by SOD to develop other
software in Mesa; combines the Tajo user interface with the compiler, binder, packager, and
other system software running on top of Pilot. The name "Mesa Development Environment"
is often used when the plans to market this body of software running on Dandelions are being
discussed.
MesaNetExec:
A Mesa implementation of the NetExec; valuable because it knows how to load
Othello.
MetaFont:
A font-designing language built by Don Knuth at Stanford. and used to generate
fonts for use with TEX. Metafont is available as MF.Sav on Maxc.
Microswitch keyboard:
Microswitch is a company that makes keyboards. The standard
Alto keyboard, also in use at PARe on D-machines, is made by Microswitch.
MIG: An acronym for Master Image Generator: a high-resolution laser-scanning printer. based on
a photographic process. - The MIG-l can run up to 2000 bpi, while the slightly different
MIG-3 runs at about 800 bpi. Also called the Platemaker.
Mockingbird:
A music system that runs on a Dorado with an attached audio synthesizer and
its keyboard. The goal of Mockingbird is to relieve the serious composer of some of the
clerical burden of writing out scores for music as it being composed. For more details. see
the blue-and-white report "Mockingbird: A Composer's Amanuensis", number CSL-83-2.
mode: A special state through which certain user interfaces must pass in order to perform certain
functions. For example, in order to insert characters into a document in Bravo, one must
type the "I" key, which invokes the "Insert" command. The effect of this command is to
put Bravo into "insert mode", in which typing the "I" key has a quite different effect (to
whit. it inserts an "1" into the document). One must then hit another special key, "ESC", in
order to leave "insert mode", Modes are locally viewed as generally evil.
modeless:
Describes a user interface that is free of modes. In stich an interface, pressing a
particular key always has essentially the same effect. Laurel was the first local system with
an approximately modeless editor interface: the Tioga editing interface is very similar.

15

mouse:

A type of pointing device with which many personal computers come equipped.
The switches on the mouse are called "buttons" to distinguish them from the "keys" on the
keyboard.
mouse-ahead:
Analogous to typeahead. except refers to mouse clicks rather than to key strokes.
Can become very confusing to non-wizards. as there is no analog of the backspace key for
mouse clicks. that is. no way to cancel unwanted mouse clicks.
An Intel standard specifying the physical and electrical characteristics of a bus
Multibus:
by which various boards in small computers can communicate. Many useful boards that plug
into a Multibus are available. such as Ethernet cards and disk controller cards. The Dicentra
is a D-machine that uses the Multibus.
name lookup:
In the context of network communications. the process of mapping a string of
characters to a network address. Also. the protocol that defines the mechanism for performing
such a mapping.
name lookup server:
A computer that implements the name lookup protocol.
Nebula:
A time server on the Internet that is equipped with an antenna to listen to time
broadcasts made by a synchronous satellite. and hence has excellent long-term reliability.
There is a display showing Nebula's opinion of the time in the same room as Clover: just
the thing for setting your digital watch.
Neptune:
An Alto subsystem providing more sophisticated manipulation of the file directory
system than is available with the Executive. See also DDS.
NetExec.boot:
A mini-Executive usable on an Alto without a spinning disk and obtainable
directly over the Ethernet (from a boot server). The NetExec makes available a number of
useful stand-alone programs. including Copy Disk. Scavenger. FTP. a number of diagnostics,
and lots of neat games.
network address: A pair of numbers  that uniquely identifies any
computer in an Internet.
node: A chunk of text in a Tioga document: each heading and paragraph in a document froms a
node. and the nodes are hierarchically structured. Node-structured documents are easier to
browse, using the levels commands in Tioga. Note: you can't have two nodes on the same
line.
NS: An acronym for Network Services: the protocols for using the Ethernet in the Star world
NS packets are analogous to PUP's. and the NS protocols include analogs to such higher-level
protocols as FTP.
Nucleus:
A new vittual memory and file system base that is being built for Cedar, to
replace portions of Pilot; it will emerge in Cedar 5.0.
Nursery:
A large room in CSL. across from the Commons: so named because it was to
be where new printers would be nursed to life. and also where fresh blood (summer interns
and the like) would be housed. Does thiS mean that Bob Taylor thinks of graduate students as infants? [
don't think so: course, I could be wrong", The funny windows were intended to make it convenient
to hold demonstrations in the Nursery with some of the audience on the outside. looking in.
object-oriented:
Describes a philosophy about how programs should be structured that finds its
purest expression in the Smalltalk system. An object is a little pile of private data together
with a collection of procedures by which other folks are allowed to ask the object to do
something. Other folks must not play with the data directly, but instead are required to
interact with the object only by calling its procedures (or. in Smalltalk parlance. sending it
messages.) Think about complex numbers as a trivial example: A non-object-oriented
programmer would probably represent a complex number as a record containing' two real
numbers. An object-oriented programmer would be tempted to represent a complex number
as a record containing public fields and private fields. The values of the public fields would

16

be procedures, with field names such as: AddToMe, MyXCoord, MyYCoord. NegateMe,
My Magnitude, and the like. The private fields in the standard implementation of complex
number would be simply two reals, named X and Y. The advantage of the object-oriented
approach is that someone else can come along later and implement a new flavor of complex
number that uses polar coordinates in the private fields, and previous programs that dealt
with complex numbers will not have to be changed.
OIS: An acronym for Office Information Systems: a name for a concept. a type of product, and
(perhaps) a market. not particular organization.
OPD: An acronym for Office Products Division, located mostly in Dallas. They make and sell 820's
and the like: seeproducts.
Orbit:
A high performance Alto-based image generator designed to merge source rasters
into a raster output stream for a SLOT printer (e.g., Dover). So named because it ORs bits
into buffers.
OS: Acronym for Operating System. Generally used to refer to the Alto Operating System, which
is stored in the file Sys.liOot. Rarely used locally to refer to the operating system of the same
name that runs on IBM 360/370 computers.
OSD: An acronym for Office Systems Division, of which SDD is a part; they deal with the higher
end of the office marke~ in contrast to OPD.
Othello:
A network-bootable Pilot utility, good for initializing logical volumes and the
like.
page (on a disk): A unit of length: an Alto or Pilot page is 512 bytes. while an IFS page is 2048
bytes.
PARe:
Acronym for ~alo ~lto B.esearch ~enter.
partition:
A chunk of a large local disk that is being used to emulate the largest system
disk that the Alto OS allows. A Dorado has five partitions, while a Dolphin has two.
Partitions are numbered starting at 1: the phrase "partition 0" refers to the current default
partition. The current partition in use is determined by the contents of some registers that
belong to the disk microcode. You can change these registers with the "partition.-" command
available in the Executive and in the NetExec. A (14-sector) partition has 22,736 Alto pages
(11.6 MBtyes). It took a little adroit shoehorning to fit two full partitions onto a Dolphin's disk: it turns out

a

that a Shugart 4000 has just one too few cylinders to squeeze in two full partitions. So we have to ask the heads to
seek off the end of the advertised disk (on the inside. It happens). and put one more cylinder in there! Ah. the joys
of hardware hacking...
.

PasMesa:
A program that more or less compiles Pascal source into Mesa source, and hence
assists in importing Pascal programs into our environment: developed in CSL.
path name:
The complete name of a file, including the file server and directory or subdirectory
on which it is stored-everything you need to know to get the file. In the old style of writing
(Alto and IFS), a path name consists of a machine name in square brackets followed by a
directory name in angle brackets. optionally followed by one or more subdirectory names
separated with right angle brackets. followed by the file name itself. as in
[Indigo).. (see path
subsystem:
A program running under a specific operating system. Normally used to refer
to Alto programs that run under the Alto as. but also used to refer to PDp·lO programs
that run under TENEX.
Swat: A debugger used primarily for BCPL programs. Also, the key used in conjunction with the
"control" or "shift.. keys to invoke this debugger. as well as various other debuggers. The
Swat key is the lowest of the three unmarked keys at the right edge of the keyboard. Used
as a verb to refer to the act of striking these keys or entering the debugger.
Swatee:
A file used by debugging programs (both Swat and the Alto/Mesa debugger) to
hold the core image of the program being debugged. Also used as a scratch file by many
Alto subsystems. Not to be deleted under any circumstances.

21

Sys.boot:
An Alto disk file containing the executable representation of the Alto Operating
System.
SysDir:
The Alto file directory. Roughly speaking, this file contains the mapping from
file names to starting disk locations.
SysFont.al:
An Alto screen font used by the Executive and (generally) as a default by other
programs. The safest way to change your SysFont is with the Delete.- and Copy.- commands of the Alto
E.'tecutive. Simply FTP'ing a new font on top of SysFont will cause exotic behavior during the CounterJunta when
FI'P is finished.

system models:
A part of the Cedar proj~t, aiming at giving programmers help is describing the
structure of large systems: getting consistent versions of files, replacing single modules within
a running system, and recompiling and rebinding just what has been changed, all in the right
order.
Tajo: The user interface portion of the Mesa Development Environment. Each facility in the Tajo
environment is called a Tool, and Tajo itself is sometimes called the Tools Environment.
Tank: An n-player video arcade game in Cedar. Get a tank game going and then close the tank
viewer and check out the wonderful icon that results.
teledebug:
Debugging one machine from another other the Internet. The prefix "tele-" is
used in general for doing things remotely.
Telnet:
A PUP-based protocol used to establish full-duplex, teletype-like communication
with a remote computer. (The term is borrowed from a similar protocol used on the Arpa
network.) Chat speaks this protocol.
Tenex:
An operating system for the DEC PDP-lO computer. which also runs on MAXC.
TEX: A document compiler written by Don Knuth at Stanford; there are one and a half
implementations ofTEX at PARC: one in Sail that runs on Maxc. the half in Cedar (waiting
on progress on the Imager). TEX can handle mathematical formulas, but doesn't let you see
anything like what you get
Thyme:
An electrical-level dircuit simulator, used for evaluating the correctness and
performance of small pieces of the designs of integrated circuits.
thumbing:
A technique of positioning a file (usually text) to an arbitrary position for viewing
on a display. The name is intended to suggest the "thumb-index" with which some dictionaries
are equipped, which performs somewhat the same function: gets you to roughly the right
place quickly.
TIC: Acronym for Technical Information Center; the fancy name for what is more generally
known as the PARC library.
Tioga:
The document editor in Cedar. which was built by folk in ISL. Tioga formatting
uses the concepts of level. node. look. format. and style: for more details, read TiogaDoc.tioga.
Documents formatted with Tioga can be printed with the TSetter.
TiogaDoc.tioga:
Documentation for the Tioga editor. At one point, the official home of this file
was the directory [IndigoJDocumentation>.
TIP: A system for interpreting keyboard and mouse actions and turning them into sequences of
commands. You may customize your Tioga user interface by layering your own TIP table
on top of the standard Tioga TIP table.
Tool: A facility available in the Tajo environment, or the program that makes that facility available.
For example. one speaks of the "File Tool", which can perform file transfers for you.
Tools Environment:
Former name for Tajo.
transaction:
A collection of reads and writes of shared data that is guaranteed to be atomic:
either all of the writes happen (the transaction commits) or none of them do (it aborts).
Furthermore. the reads will see consistent data in that either all of the writes made by some
other transaction will be visible. or none of them will.

22

Trident:
The brand name of a type of disk drive that is quite common around here.
There are T·80·s (that is, 80MByte Trident drives) and T-300's. Tridents are manufactured
by Century Data Systems. a subsidiary of Xerox.
Trinity:
The version of Pilot and other Mesa system software between Rubicon (the
current base of Cedar) and Klamath.
TSetter:
The typesetting program for Tioga documents: converts foo.tioga into foo.press,
and optionally sends the latter to your favorite print sener.
typeahead:
An ability to type characters to a program before that program has asked for
them. Useful for wizards: essential when using slow machines. See also mouse-ahead.
typescript:
A tile used to back-Up information (usually text) appearing in a region of the
display.
Twinkle:
A Gateway in Building 35 of PARe.
uncaught signal: An exceptional condition (perhaps an error indication) that no current program
other than the Mesa or Cedar debugger has expressed a willingness to deal with. The
debugger is willing to deal with anything, of course: it deals with these exceptional events
by halting the offending process and then informing the user. In the language of the CLRM,
an uncaught signal should be thought of as an invocation of a dynamically bound procedure
that turns out not to have been bound at all: see catch phrase.
user: A person (rather than a program) who avails herself of the services of some program or
system. At the moment, the author is a user of Tioga. See client.
user.cm:
A tile in the Alto world containing a number of logically distinct sections that
each define certain configuration parameters (e.g., the location of a preferred print sener for
a particular tile format). Programs that interpret such parameters are often organized to read
user.cm only at installation time (e.g:, Bravo).
UserExec:
The command interpreter for Cedar.
viewer:
The name for a window in the Viewers window package.
ViewerDoc.tioga: Documentation for the Viewers window package. You might try looking for this
file on the directory [Indigo)Oocumentation>.
Viewers:
A screen management and window package for Cedar providing buttons, menus,
and windows.
ViewRec:
A software package in Cedar that produces convenient user interfaces to fairly
arbitrary programs automatically.
Viking:
A Dover on the first floor of Building 35.
VLSI:
Acronym for yery !::arge ~cale !ntegration of electro~ic circuits on chips.
VM: Acronym for Yinual Memory.
Voice:
A small but mighty project in CSL to tame the telephone and otherwise make
full use of voice communications in our personal information systems. The Voice Project
recently produced the EtherPhone.
Walnut:
A mail system for Cedar. Walnut uses the Cypress database to store and organize
messages, and it calls upon Grapevine to transpon them.
Watch:
A Cedar performance monitoring tool displaying computing activity.
A Mesa program that does source compares: compares two text files and reports
WaterLily:
the differences. Available in Alto/Mesa, Tajo, and Cedar.
wedged:
Describes the state of a program when there is no response to input from either
the keyboard or the mouse. May affect the whole system (my system is wedged) or just some
pan thereof.
weekly meeting:
The (boring) name of ISL's weekly meeting, held on Tuesdays starting at 11:00
am. See also Dealer.

23

white boards:
A package in Cedar for arranging and accessing information graphically.
Winchester:
Originally. this was the name of a project within IBM. But the name leaked
out. and it is now used industry-wide to refer to a particular rigid disk technology. In a
Winchester disk drive. the heads and platters come all hermetically sealed: that is. Winchester
drives do not use removable disk packs.
window:
A display region. usually rectangular. used to view (a portion 00 an image that
generally exceeds the bounds of the region.
wizard:
One who knows a programming system inside and out
Wonder:
A Dover on the third floor of Building 35.
world-swap:
The process of writing out the complete state of a machine's processer and
memory onto a disk file. and of swapping in a different state. Some debuggers work by
means of world-swaps. which swap between the debugger and the program being debugged.
~ote

that. the more memory you have. the slower a world-swap will be.

XGP: (archaic) Acronym for Xerox Graphics Printer. An obsolete. CRT scanned, 200 bpi, continuous
paper. xerographic printer. XM: Acronym for Extended Memory: an option on Alto II's that allows the memory size to be
increased from one to four banks.
Yoda: A Dover in Building 35.
Zinfandel:
An Alto mail server that is part of the Grapevine distributed transport mechanism.

The Tioga Editor
Release as
Last edited

[lndigo]. and such a file exists. it is opened.
Otherwise, if  is one of the standard set of extensions. you will be informed that the
file doesn't exist. However, if  is not a standard extension, the system tries to open
the file as if you had simply selected . If this succeeds. it searches in the file for a
definition of . This convention is intended for use with programs that have many
instances of .mesa is a file containing a definition for
. and an implementation for the item
is currently loaded. the system will find the name of the file holding the implementation (our

. thanks to the Cedar runtime model for providing this information). Otherwise. the system tries
to open the file as if you had simply selected . and. if this succeeds, searches in the
file for a definition of Documentation>TiogaDoc.Tioga

CEDAR 4.2

TIOGA EDITOR

10

Select matching brackets
CfRL-] extends the selection to the left and right to find a matching pair of [..)'s. Similarly
for CfRL-}, CfRL-). and CfRL-). Note that you hit CfRL with the right bracket to extend the
selection. In addition, you can hit CTRL with the left bracket to insert matching brackets around
the selection.

Fine point: Unfortunately, our keyboards don't have both left and right quote keys.
However most of the fonts, including TimesRoman and Helvetica. do provide a left and right
single quote. The keyboard key inserts a right single quote (code 047); the left single quote
(code 140) can be inserted using the MakeOctalCharacter command in the Edit Tool or with
the Insert Matching Single Quotes command (CfRL-'). The Edit Tool also has a command
which extends the selection to find a matching pair of left and right single quotes. The situation
for double quotes is even less unifonn. Some fonts, such as Oassic, have a left double quote
(code 264) in addition to a right double quote (code 042). However, most fonts have only the
042 double quote. so the Tioga commands for inserting and matching double quotes use that
code exclusively.

CEDAR 4.2

TIOGA EDITOR

11

Editing
Text input
Typed-in characters are inserted at the caret.
To insert the current time use CfRL-T - "T" for Time.
When you insert a carriage return by hitting RETURN. the system will automatically copy the
blank characters (tabs and spaces) from the start of the previous line. To suppress this. type
SHIFf-RETURN and only the carriage return will be inserted.
To insert control characters or characters with a specific octal code. use CfRL-K or CfRL-O ...
The former will change the character before the caret to a control character. while the latter will
convert tlie three digits before the caret to the corresponding octal character. The inverse
operations are also available as CfRL-SHIFf-K and CfRL-SHIFf-O.
Abbreviation Expansion
CfRL-E - "E" for Expand abbreviation
When you hit CfRL-E, the caret is moved to the right of the selection if necessary and the
keyname to the left of the caret is then replaced by the expansion text (according to the definition
which is linked to the style in a manner described below). If the key name had looks. they are
added to the expansion. If the key name was all caps, the expansion is made all caps too. If the
keyname had an initial cap. the first character of the expansion is made uppercase (useful at the
start of sentences. for example). If the definition node has a non-null format, the format of the
caret node is changed to be the same as the definition node. If the expansion contains a
placeholder. the first placeholder is selected. Otherwise the entire expansion is selected.
Definitions for abbreviations come from Tioga documents which are automatically read by
the system when needed. The name of the appropriate abbreviations file is determined by the
style that is in effect at the caret when the expansion takes place. For example. if the style is
"Report". the abbreviations will come from the file "Report.Abbreviations". You can override
this by explicitly naming the abbreviations file along with the keyname. For example. "Mesa.proc"
will expand the abbreviation for "proc" from the file "Mesa.Abbreviations" independent of the
style in effect at the caret. (Fine point: Since the system interprets a period before the keyname
to mean that you're specifying a particular abbreviations file. you cannot type a vanilla abbreviation
after a period.)
Each definition in an abbreviations file consists of a separate branch. The top node of the
branch holds the key name followed by an equals sign and then the text expansion. The rest of
the branch, if any, is copied after the caret node as part of expanding the abbreviation. Any text
following the keyname is moved to the end of the last child node in the branch. The definition
may also include a list of operations to be performed after the expansion has been inserted. These
operations have the same format as those in EditTool and are placed in parentheses after the
keyname and before the equals sign.
Delete Character or Word
BackSpace: CfRL-A. CfRL-H. or BS. Deletes the character to the left of the caret.
Fine point: If the caret is at the stan of a node. thiS does a Join command (q.v.).

BackWord: CfRL-W. or CfRL-BS. Deletes the word to the left of the caret.

CEDAR 42

12

TIOGA EDITOR

DeleteNextChar: CfRL-SHIFT-A, CfRL-SHIFT-H. or SHIFT-SS. Deletes the character to the right
of the caret.
. DeleteNextWord: CfRL-SHIFT-W, or CfRL-SHIFf-SS.
caret.

Deletes the word to the right of the

Delete
As mentioned above, you can delete something by selecting it with CTRL held down.
addition. you can delete the current selection by hitting DEL.

In

Paste
Paste: CfRL-P. The most recently deleted text is copied to the caret. You can also use the
Edit Tool to save the current selection to be pasted later.

Copy, Move, Replace. and Transpose
These operations are all carried out by making selections. They are described in detail in the
previous section.

Insert matching brackets
CfRL-[ adds a matching pair of [.. ]'s to the ends of the selection. Similar CTRL commands
exist for {, (, <, -, " and to. CfRL-B inserts matching placeholder brackets ~~.
Note: CfRL-' inserts a left single quote (code 140) and a right single quote (code 047); CfRL-"
inserts the same character (code 042) at each end of the selection.

Case
All lower: CTRL-C. Makes the selection all lower case.
All caps: CTRL-SHIFT-C. Makes the selection all upper case.
Initial caps: CfRL-double C. Capitalizes each word in the selection.
First cap: CfRL-SHIFf-double C. Capitalizes the first word of the selection

Repeat
Hitting ESC will repeat the most recent non-empty edit sequence starting with the current
selection. Edit sequences are separated by user-made selections. For example, if you select a
word. delete it. type a new one. and then select something else, the edit sequence is delete followed
by text entry. If you hit Repeat. the system will do a delete and retype the new word.
Auto-repeat is done by Esc-select: if you hold down the ESC key while making a selection, a
Repeat will automatically be done as soon as the selection is completed. This is useful when
you're doing a large number of repeats.

Undo
Hitting SHIFf-ESC undoes the most recent edit sequence and restores the selection to its prior
state. If you want to undo more than just the most recent sequence, use the Edit History tool
which is described later.

CEDAR 4.2

,

TIOGA EDITOR

13

Tree structure editing
As explained in the introduction, Tioga documents consist of a tree of nodes. The following
commands let you break, join, and nest nodes in the tree.
Break: CfRL-RETURN - break node at insertion point to create a new node.
Join: crRL-J - join node at insertion point with previous node.
Nest: CfRL-N - move selected nodes to deeper nesting level in tree.
UnNest: CfRL-SHIFf-N - move selected nodes to 'shallower nesting level in tree.
Break & Nest: CfRL-I - simultaneously insert a new node and nest it.
Break & UnNest: crRL-SHIFf-I - simultaneously insert and unnest.

CEDAR 4.2

TIOGA EDITOR

14

Looks
Characters have looks which are named by the lower case letters "a" to "z". Looks are
interpreted by the style to change the appearance of the text For example. look "e" might stand
for "emphasis" and might result in italic face in one style and bold face in another. Each character
has a set of looks - thus it may have several looks simultaneously. but each look occurs only once.
You can use the Edit Tool to read or change the set of looks for selected characters. The following
keyboard commands are also available for dealing with looks.
Selection Looks

You can change the selection looks with the following commands. (Recall that the LOOK
shift is the top blank key to the right of as.)
LooK-char to add to selection looks.
LOOK-SHiff-char to remove from selection looks.
LooK-space to remove all selection looks.
Caret Looks

Caret looks determine the looks of typed-in text The caret picks up the looks of the adjacent
selected text whenever a selection is made. Changing the selection looks also changes the caret
looks. However. if you wish to change the looks of the caret without changing the selection looks,
left-click the character key twice in quick succession.
LooK-char-char to add to caret looks.
LOOK -SHIFf-char-char to remove from caret looks.
LOOK-space-space to remove all caret looks.
Using Selections To Copy Looks

To copy the looks of some existing text to the primary selection. hit CTRL-Q. and then with
the CfRL key still held down. select the text with the looks you want to copy. The source looks
replace any looks the selection previously had.
Automatic Mesa formatting

The CfRL-M command scans the selection for Mesa keywords. comments, and procedure
names and gives them looks k, c. and n respectively. (As a convenience during typein, the entire
caret node is reformatted if the selection is a single character or less.) With the standard Cedar
style. the keywords will then be displayed in small caps. the comments will be italic. and the
procedure names will be boldface. We expect to provide more extensive reformatting capabilities
in the future.

CEDAR 4.2

TIOGA EDITOR

15

Formats
Just as characters have looks. nodes have fonnats. The "fonnat" is the name of a rule in the
style that tells how to modify various parameters when displaying the node. For example, a style
for documents might contain fonnats for titles. headings, quotations, standard paragraphs, etc. The
Edit Tool has facilities for reading and changing the fonnat of a node. or you can use the commands
described below. (By convention, the null fonnat name is equivalent to "default".)
Setting and inserting caret node format
CfRL-" will delete the word to the left of the caret and make it the fonnat of the caret node.

Fine point: In most cases you will give this command immediately after typing the fonnat
name, so the caret will naturally be in the correct place. However, to handle cases in which
you select the name before hitting CfRL-", the caret will automatically be forced to the right of
the selection at the start of this command.
CfRL-SHIFT-" inserts the fonnat name.

This gives you a simple way to find out the fonnat of a selected node.
Using selections to copy formats

To copy the fonnat of some exisiting node to the selection nodes, hit CfRL-F, and then with
the crRL key still held down, select the node with the format you want to copy.

CEDAR 42

TIOGA EDITOR

16

The Edit Tool
The Edit Tool provides a variety of operations on Tioga documents.
The text fields in the Edit Tool follow the convention that clicking the field name with LEFT
causes the contents of the field to be selected pending-delete while clicking with RIGHT causes the
field to be cleared and selected.
Search and Substitute
Search

To do a search, enter the text you're looking for in the "Target" field. select where you
want the search to start. and left-click "Search" to search forward. right-click to search backwards,
or middle-click to search first forward then backwards. The system searches from the current
selection and updates the selected viewer if the search succeeds. (Fine point: in both searches
and substitutes. the match is limited to a single node - we do not yet have mechanisms for
doing matches across node boundaries.)
The multiple choices below the "Replacement" field control what is matched in searches
and replaced in substitutes. You can select or deselect an item by clicking it with the mouse.
White text on black background means that the item is selected; black text on white means it
is not selected.
Text - if this option is selected, match characters of target text when searching.
Looks - if selected, match looks of target text when searching.
Format - match format of target node.
Style - match style of target node.
Comment - match comment property of target node.
For example, if you pick the Looks option and deselect the Text option, you can search
for any text that has a particular set of looks. (f you pick only Text, the matching will ignore
the looks of the target. If you pick Text and Looks. the matching text must match both the
characters and the looks of the target text
The other options deal with node properties. If you pick Format, the matching will be
limited to nodes with the same format as the target node. Similarly, if you pick Style, the
matching will only look at nodes whose style is the same as the target node's. Finally. if you
pick Comment, the match will consider only nodes with the same value of the Comment
property (TRUE or FALSE) as the target.
The first two rows of boxes below the multiple choices give you control over how matching
is performed. Left-click with the cursor over a box to change the choice next to it. The various
choices are as follows:
1. Case of matching text
Match Case - matching text must have same case as target text,
Ignore Case - matching text does not have to have same case as target text.
2. Interpretation of target text
Match Literally - don't treat target text as a pattern.
Match as Pattern - do treat target as pattern. (Patterns are described below.)
3. Context of target text
Match Anywhere - ignore context of matching text.
Match Words Only - matching text must not have adjacent letters or digits.

CEDAR 4.2

17

TIOGA EDITOR

Match Entire Nodes Only - matching text must span entire node.
4. Matching target looks
Subset as Looks Test - looks of matching text must include target looks.
Equal as Looks Test - looks of matching text must be identical to target looks.
Substitute

To do a substitution, enter the new text in the "Replacement" field, enter the text to be
replaced in the "Target" field, and hit "Substitute" in the menu at the top of the Edit Tool.
The TextiLooks/Formatl ... options guide the search in the usual manner and also control what
is replaced.
If you pick Text and Looks, the matching text will be replaced just as if you had selected
it with pending delete and made a source secondary selection of the replacement text.
If you pick only the Looks option, the matching text will have the target looks removed
and the replacement looks added.
If you pick only Text. the replacement text will have the looks of the replaced text added
to it (Fine point: if the looks of the replaced text are not uniform, the looks of the first
character will be used throughout.)
If you pick Format. the matching node will get the format of the replacement node.
Similarly. picking Style causes the matching node to get the style of the replacement node.
and picking Comment causes the matching node to get the same value of the Comment
property as the replacement node.
The final three boxes in the Search&Substitute section give you further control over this
operation.
1. First character capitalization of the replacement text
First cap like replaced - if the replaced text starts with a capital letter, force the
first letter of the replacement to be a capital too.
Don't change caps - leave the replacement capitalization alone.
2. What is done to the matching text
Do Replace - do the usual substitute or replace.
Do Operations - instead of doing a replace, select the matching text and then do
the operations currently in the "Operations" field of the Edit Tool.
3. Where the substitutions will take place
Within Selection Only - substitute is limited to current selection.
After Selection Only - substitute after selection to end of document.
In Entire Document - substitute in the entire selected document
Case-by-Case Substitutes

,

In .addition to doing global substitutes. you can decide on a case-by-case basis whether
or not to replace the matching text by the new text Use the search commands to find the
first matching text. Then if you hit "Yes", the system will do a "Replace" followed by a
search forward. If you hit "No", it will skip the "Replace" and simply do another search.
Thus to selectively substitute. start with a search. then .do "Yes" for the cases you want to
change and "No" for the others. The "Replace" command simply does for the current
selection what a substitute would do for a match. Finally, the "Count" command is available
to tell you how many substitutions would take place without actually changing the document.

CEDAR 4.2

TIOGA EDITOR

18

In order to do a search or substitute, you will typically need to fill in the Target or Replacement
fields in the Edit Tool. Naturally, this changes the selection, and before you can do the operation,
you must restore the selection to the place where you actually want it to take place. The system
helps you with this by saving the primary selection if it is not in the Edit Tool when you left-click
either the Target or the Replacement button. The commands along the top of the Edit Tool Search. Substitute. Yes, No. Replace, and Count - restore the saved selection if the primary
selection is in the Edit Tool when they are clicked. The net effect is that if you start out with
the selection in the right place, you can left-click the Target or Replacement buttons. fill in the
needed information. and then directly click one of the commands without needing to reselect since
the system will do it for you.
Patterns for Search and Substitute
When you specify that the target be matched as a pattern rather than literally. the following
symbols in the target text are interpreted specially. A short summary of these symbols appears
at the bottom of the Search&Substitute section of the Edit Tool.
Characters

#

Match any single character.

*
**

Match shortest possible sequence of characters.
Match longest possible sequence of characters.
Match the next character in the pattern exactly.
Match any character except the next one in the pattern.

Alphanumeric characters
@

Match any single alphanumeric character (letter or digit).

&

Match shortest possible sequence of alphanumeric characters.

&&

Match longest possible sequence of alphanumeric characters.

Non-alphanumeric characters
-@

Match any single non-alphanumeric character.

-&

Match shortest possible sequence of non-alphanumeric characters.

-&-& Match longest possible sequence of non-alphanumeric characters.

Blank characters

%

Match any single blank character.

$

Match shortest possible sequence of blank characters.

$$

Match longest possible sequence of blank characters.

Non-blank characters

-%

Match any single non-blank character.

-$

Match shortest possible sequence of non-blank characters.

-$-$

Match longest possible sequence of non-blank characters.

CEDAR 4.2

TIOGA EDITOR

19

Miscellaneous
Match start or end of node.
{

Mark start of resulting selection.

}

Mark end of resulting selection.

<

Mark start of named subpattern.

>

Mark end of named subpattern.

The named subpatterns are of use in substitutes that reorder or duplicate parts of the
matching text. The full syntax for a named sub pattern is . The special case
of "match any sequence of characters" is provided as a default - i.e.,  is equivalent to
. As far as the matching is concerned, the occurrence of  is the
same as if the subpattern had appeared without a name, but it has the side-effect of remembering
the subsection it matched. The "Replacement" field can contain 's corresponding to
named subpatterns in the target. The replacement text is constructed by replacing the 's
with the section of replaced text that matched the subpattern. The replacement is automatically
considered to be a pattern whenever the target is - you don't need to do anything special to
get the 's in 'the replacement interpreted as subpatterns.
For example. if the target is
Target: WHILE [] 00
and the replacement is
Replacement: WHILE  IS  00
then "WHILE blue[moon] 00" will be converted to "WHILE moon IS blue 00".
Looks, Formats. Styles. and Properties

Looks
The Looks commands let you read and modify the looks of the caret or the selection. The
looks are shown as a series of letters in the "Looks characters" field. The box lets you pick
whether you want the looks for the selection or the looks for the caret.
Get - fills the "Looks characters" field with the letters for the caret/selection looks.
Set - reads the "Looks characters" field and sets the looks of the caret/selection.
Clear - removes all looks from the caret/selection.
Add - adds the specified looks to the caret/selection.
Sub - removes the specified looks from the caret/selection.

Formats
The Format commands let you read and modify the format for the root node or the selected
nodes. The box at the right lets you pick the case you want.
Get - fills the "Format name" field.
Set - reads the "Format name" field and sets the node's format
Clear - removes the node's format name. This is the same as specifying "default" format
Styles

CEDAR 4.2

TIOGA EDITOR

20

A style is a collection of interpretations for looks and fonnats. The Style commands let
you read and modify the name of the style for the root node or the selected nodes. The new
style applies to the specified node and all the nodes within its sub-branches that do not
themselves have explicit styles.
Get - fills the "Style name" field.
Set - reads the "Style name" field and sets the node's style.
Clear - removes any style specification from the node.
LoadStyleDefinition - reads the "Style name" field and reloads the style definition from
that file with extension "Style". (Don't put the extension in the field - just put
the style name and let the system add the extension.) Do this operation after you
have edited (and saved) the style definition and want to load the new version.
LoadAbbreviations - reads the "Style name" field and reloads the abbreviation definitions
from that file with extension "Abbreviations". Do this after you have edited the
abbreviations and want to load the new version.

Properties
A node can have an arbitrary set of "properties". Each property consists of a name and a
value. Certain properties are used by the system, but you (and your programs) are free to add
others.
The "Property name" field specifies the name of a property. (Incidentally, case distinctions
do matter in property names - "foo" is a different property than "Foo".) The "Property
value" field specifies a value. The box lets you pick whether you are talking about properties
of the root node or the selected nodes.
Get - fills the "Property value" field with the current value of the named property.
Set - reads the "Property value" field and sets the property value.
Remove - removes the named property from the node.
List - fills the "Property name" field with the names of the node's properties.
In addition to setting and reading properties, there is a mechanism that lets you find nodes
with a certain property value. For example, if you have annotated a document with comments
under the property name "MyOpinion", and you want to find nodes in which your comment
included the word "good", enter the name in the "Property name" field and the text in the
"Value pattern" field. Then use the "Find" command to search forward or backwards from
the caret node for a node with a value of the property that matches the pattern. (Left-click to
search forward. right-click to search backwards.) Value patterns can use the standard set of
special characters for searches. If a match is found. the node is selected and the property value
is displayed.

C..omment Property
All nodes have a "Comment" property which is either "TRUE" or "FALSE", If its value is
the text of the node is not seen by programs such as the compiler that are only interested
in the basic text contents. This makes it possible to intermix documentation and program text
without requiring special escape characters to mark the start and end of comments. You can
set the Comment property by using the Edit Tool or with the following commands.
CfRL-\ - set comment property of all selected nodes to TRUE
CfRL-SHIFT- \ - set comment property of all selected nodes to FALSE

TRUE,

If you are worried about not knowing at a glance what is a comment node and what is not, find a StyleRule in the
style that applies to all the formats you are interested in (e.g.. "standard" in Cedar.style), and insert the line

CEDAR 4.2

TIOGA EDITOR

21

isComment {visible underlining} {none underlining} .ifelse cvx .exec
This will cause the contents of all comment nodes to be underlined. (You might want to say "strikeout" instead of
"underlining" if the style already uses underlining to mean something else. and legibility is not your main concern.)

Miscellaneous
Sort and Reverse
These commands let you sort or reverse lists of things. The "Sort" command sorts things
in alphabetical order. ignoring case. "Sort-and-remove-duplicates" is useful when you are
merging sets of things. The box below the Sort button lets you pick whether you want increasing
or decreasing order in the result The right box lets you pick what will be sorted: text delimited
by blanks. lines delimited by carriage returns. or branches of the document tree. Leading blanks
are ignored when sorting lines or branches.

Operations
These commands let you construct simple edit macros. The "Operations" field holds a text
description of a command sequence. The "GetLast" command fills in the Operations with the
description of the most recent sequence. i.e.. the one a Cancel would cancel or a Repeat would
repeat "Do" executes the description in the operations field. "Begin" marks the start of a
command sequence. "End" fills the Operations with the description of the commands since the
most recent "Begin". "SetCom" stores the operations under the CTRL-number key for the
number in the "Command [0 .. 9]" field. Conversely. "GetCom" fills the "Operations" field with
the current CTRL-number definition.
To see how this works, select the following word: "hello". Hit DEL and type in "howdy".
Now hit the "GetLast" button. The Operations field should now contain: Delete "howdy".
Edit the Operations field contents to replace "howdy" by "goodbye", then hit the "SetCom"
button (first put 1 in the Command field if it's not already there). Now select the "howdy"
you typed earlier and hit CTRL-l. If all went well. the "howdy" will have been deleted and
"goodbye" inserted in its place. More examples of edit macros will be given later.

Searches and Operations on Files
You can use the EditTool to look through a list of files for one in which the current search
specifications are satisfied. This can be accomplished by clicking the "SearchEachFile" button
after filling in the "Files" field with the file names (or "@" followed by the name of a file that
holds the list of file names). When you left-click SearchEachFile. a new viewer is created, and
one-by-one the files will be loaded and searched until a match is found. The list of files will
be updated when a match is found so that when you are finished with one file you can left-click
SearchEachFile again to look for the next one. You can hit the "Stop" button at the top of
the EditTool to interrupt the search. but you should not try doing other operations while the
search is in progress since it resets the selection each time it loads a file.
Occasionally you will want to apply certain operations to an entire set of files. You can
do this by filling in the "Operations" field and the "Files" field, and then clicking
"DoForEachFile". A new viewer will be created. and one-by-one the files will be loaded,
selected, edited, and saved. No confirmation is required for the saves. so the entire process can
go on without you. In fact. you should not try to do anything else while this is going on since
the operations use the primary selection. The one exeception is the "Stop" button which you
can hit to terminate the process.

CEDAR 4.2

TIOGA EDITOR

22

Operations via the User Exec
You can invoke a set of operations from the User Exec as well as directly from the Edit
Tool. When you run TiogaExecCommancis, one of the commands it registers is DoTiogaOps
which expects a command line containing operations in the same format as in the operations
field. One possible application of this is to create a command file that initializes various Edit
Tool switches to your favorite settings. For example, you could use the following to set up
some of the search parameters: DoTiogaOps IgnoreCase MatchWords MatchPattem.

Edit Commands
This section of the Edit Tool contains buttons for all the basic edit commands. These are
useful if you can't remember what keys to hit for an infrequent command or if you've set your
user category to beginner or intermediate to filter out certain commands. Many of the buttons
correspond to commands that have been documented above. However, a few of them are
primarily of use in constructing edit macros and have not been mentioned before. For
completeness, all the buttons will be given a brief description.
Modifying selections
CaretBefore - move caret to front of selection
CaretAfter - move caret to end of selection
CaretOnly - reduce selection to a caret
Grow - selection grows in hierarchy of point, character. word. node, branch
Document - select entire document
PendingDelete - make primary selection pending delete
NotPendingDelete - make primary selection not pending delete
MakeSecondary - make the primary selection become the secondary selection
MakePrimary - make the secondary selection become the primary selection
CancelSecondary - remove the secondary selection
CancelPrimary - remove the primary selection
Copy. Move, and Translate
ToPrimary - copy/move secondary to primary
ToSecondary - copy/move primary to secondary
Transpose - transpose the primary and the secondary
Moving the caret
GoToNextChar - make primary caret only and move one character toward end of
document or one toward start if you right-click instead of left-clicking
GoToNextWord - like GoToNextChar, but move toward end by "words" or one toward
start if you right-click instead of left-clicking
GoToNextNode - move caret one node toward end or one toward start if you right-click
instead of left-clicking
Saving and Restoring the selection
SaveSel-A - save primary selection to restore later
RestoreSel-A - restore the selection previously saved by SaveSel-A
SaveSel-B - save primary selection to restore later

CEDAR 4.2

TIOGA EDITOR

RestoreSel-B - restore the selection previously saved by SaveSel-B
Extend the selection to matching brackets
(... ) - extend primary selection to matching parens
<...> - extend to matching angle brackets
{... } - extend to matching curly brackets
[...] - extend to matching square braekets
" ..." - extend to matching double quotes
' .. .' - extend to matching single quotes
-...- - extend to matching dashes
•... ~ - extend to matching placeholder brackets
Find placeholders
Next•... ~ - move primary selection to next placeholder
Prev •... ~ - move to previous placeholder
Delete and Paste
Delete - delete the primary selection
Paste - insert saved text at caret
SaveForPaste - save text for later pasting; overwrites text saved by Delete
Repeat and Undo
Repeat - repeat the last command sequence
Undo - undo the last command sequence
Deleting character/word next to caret
BackSpace - delete the character to the left of the caret
BackWord - delete the word to the left of the caret
DeleteNextChar - delete the character to the right of the caret
DeleteNextWord - delete the word to the right of the caret
Inserting matching brackets around the selection
Add( ) - insert parens around the selection
Add< > - insert angle brackets
Add{ } - insert curly brackets
Add[] - insert square brackets
Add" " - insert double quotes
Add' • - insert single quotes
Add- - - insert dashes
Add. ~ - insert placeholder brackets
Capitalization
AllCaps - make the selection upper case
AllLower - make the selection lower case
InitialCaps - make the words in the selection start with caps
FirstCap - make the selection start with a cap

CEDAR 4.2

23

TIOGA EDITOR

24

Special characters
MakeOctalCharacter - convert the 3 digits before the caret to the corresponding character
MakeControlCharacter - convert the character before the caret to a control character
UnMakeOctalCharacter - convert the character before the caret to 3 digit representing
its character code
UnMakeControlCharacter - convert the control character before the caret to a normal
character
Tree structure commands
Break - break node at caret
Join - join caret node to one before it
Nest - move selection deeper in tree
UnNest - move selection higher in tree
Miscellaneous commands
CommentNode - set Comment property of aU selected nodes to TRUE
NotCommentNode - set Comment property of all selected nodes to FALSE
ExpandAbbreviation - expand the abbreviation to the left of the caret
MesaFormatting - add Mesa looks. formats, and style to selection
Command 0 1 2 3 4 5 6 7 8 9 - do saved command macro
Writing Edit Macros

A few examples should get you started writing your own edit macros. First. assume you
find yourself doing a lot of edits of the form [. You might like a single command to insert the brackets and move the
caret to the place where you will insert the . To construct such a command. first select
a particular ".
The "Show" command will display the events starting with the number in the "since event
number" field. If that field is empty it will show as many as are still remembered. The format of
the entries is . TAB. and then a list of operations. The "Undo" command undoes
the edits since the specified event number.

CEDAR 4.2

TIOGA EDITOR

27

Printing and the TypeSetter Tool
[n the glorious future. Tioga will have an interactive typesetter that wi11let you make incremental
revisions to a typeset document to adjust pagination. page layout, and other details before actually
printing it Michael Plass and [ have started work on this. but until it's available. the current
typesetter will do a more than adequate job of letting you print your files. Documentation for the
TSetter tool may be found in [Indigo] bigger

adds the amount to the current parameter value

 smaller

substracts the amount from the parameter value

 percent
percentage

multiplies the parameter value by the specified
Le .• value

~

(amountllOO)*value

 percent bigger

increases value by specified percentage

 percent smaller

decreases value by specified percentage

Font Parameters
family
"TimesRoman"

the

name

of

current

font

family.

size

value is the font size in points

face

one of regular. bold. italic. or bold + italic

such

You can alsO add or remove italic or bold by means of the following commands:
+ bold face, -bold face.

+ italic

face. or -italic face

underlining

one of all. visible. letters+digits. or none

strikeout

one of all. visible. letters + digits, or none

CEDAR 4.2

as

TIOGA EDITOR

31

Indent Parameters
leftIndent

left indent for start of lines

rightlndent

right indent for end of lines

firstlndent

added to leftIndent for first line of paragraph

restIndent

added to leftIndent for remaining lines of paragraph

top Indent

distance from top of viewer/column to first baseline

Leading Parameters
Leading parameters are stored as triples of  which. following
Knuth, we refer to as "glue", You can set the separate components individually. or you can
push three values on the stack and use one of the leading glue commands to set them all at
once.
There are three kinds of leading corresponding to the spaces between lines in a node,
the space above a node, and the space below it. The actual space between a node is the
maximum of the "below" leading of the first node and the "above" leading of the second.
leading

distance between baselines within a node

leadingStretch

how much leading can increase

leadingShrink

how much leading can decrease

leadingGlue

size. stretch. and shrink for leading

top Leading

distance between baselines above a node

topLeadingStretch

how much top leading can increase

top Leading Shrink

how much top leading can decrease

topLeadingGlue

size. stretch. and shrink for top leading

bottomLeading

distance between baselines below a node

bottomLeadingStretch

how much bottom leading can increase

bottomLeadingShrink

how much bottom leading can decrease

bottomLeadingGlue

size. stretch, and shrink for bottom leading

Layout Parameters
lineFormatting
minLineGap
(can be negative)

FlushLeft. FlushRight. Justified, Centered
min distance between line top and previous bottom

leftlndent

all lines indent this much on left

rightlndent

all lines indent this much on right

firstIndent

first line indent this much more on left

restIndent

other lines indent this much more on left

top (ndent
viewer/page

top line at least this much down from top of

CEDAR 4.2

TIOGA EDITOR

bottomlndent

32

bottom baseline at least this up from bottom of page

Page Layout Parameters
pageWidth

width of the paper

pageLength

height of the paper

leftMargin

whitespace at left of the page

rightMargin

whitespace at right of the page

top Margin

whitespace at top of the page

bottomMargin

whitespace at bottom of the page

headerMargin

height of area below topMargin for headers

footer Margin

height of area above bottomMargin for footers

bindingMargin

not used at present

lineLength

width of lines of text

Dimensions
pt

point

pc

pica

in

inches

cm

centimeters

mm

millimeters

fil

10t4 points

fill

lOt8 points

Miscellaneous
style
isComment
of node

the name of the current style
pushes .true or .false according to comment property

isPrint

pushes .true if executing print rules, else .false

nestingLevel

pushes integer; 0 for root. 1 for .top level, etc.

CEDAR 4.2

TIOGA EDITOR

33

Tioga User Exec Commands
Note: If the following commands are not known to the UserE:    ...
To spedi}' a default style for files with no extension in their name. use the fake extension name "null" in this list

Default Style

This entry specifies the default style to be used with documents that do not explicitly name
a style and do not have an extension given in the ExtensionStyles list The entry is of the form
DefaultStyle: Cedar
Default submenus

This entry specifies which menus. if any, should automatically be displayed when you create
a new Tioga viewer by clicking one of the buttons in the upper right comer or by giving an Exec
command. The entry is of the form
DefaultTiogaMenus: places levels
or
DefaultTiogaMenus: none
You may delete or reorder the menu names to suit your tastes.
Scroll bottom offset

When you are typing and the caret goes to a new line just off the bottom of the viewer.
Tioga will automatically scroll the viewer up a little to make the caret visible again. This parameter
controls how far up to scroll: a big number causes larger but less frequent glitches.
ScrollBottomOffset: 3

CEDAR 4.2

35

TIOGA EDITOR

Scroll top offset
When you do a Find command you may want to see a few lines in front of the match to
give you more context. This parameter tells Tioga how many extra lines to want in such situations.
The entry is of the form
ScrollTopOffset: 1
Selection Caret
The default behaviour for Tioga is to place the caret at the end nearer the cursor when the
selection is made. Some people have requested to have the caret always placed at one end or the
other. hence this profile entry. The choices are before. after. and balance. The entry is of the
form
SelectionCaret: before
Selection Displacement
This lets you specify a vertical displacement for making selections. Tioga behaves as if you
had pointed this number of points higher up the screen so that you can point at things from
slightly below them. The entry is of the form
YSelectFudge: 2
TIP Table
This entry specifies the TIP tables to use with Tioga documents. The entry is of the form
TiogaTIP: MyOwnTip.tip Default
See the section on TIP tables for more information.
Unsaved Documents Cache Size
This controls the number of unsaved documents the system will remember. The entry is of
the form
UnsavedDocumentsCacheSize: 4
Show Unsaved Documents List
If this is true. a viewer will be created holding an up-to-date list of the unsaved documents
that can still be reloaded. The entry is of the form
ShowUnsavedDocumentsList: TRUE
User category
As described above, this entry lets you control your user category.
Beginner, Intermediate. and Advanced. The entry is of the form
UserCategory: Intermediate

CEDAR 4.2

The alternatives are

TIOGA EDITOR

36

Command Summary
This is a short summary of the Tioga commands available using the keyboard and mouse. Other
commands are available through the Edit Tool, the Edit History Tool, and various User Exec
operations.
The extra keys on the keyboard are used for common editing actions. Recall that the bottom
right blank key can be used as another CTRL key, and you can use either CTRL key and either SHIFT
key interchangeably.
ESC
SHIFT-ESC
Esc-select
DEL
LF
CTRL-LF
BS
SHIFT-BS
CTRL-BS
CTRL-SHIFT-BS
NEXT
SHIFT-NEXT
RETtJRN
SHIFT-RETURN
CTRL-RETURN

Repeat last action
Undo last action
Automatic repeat of last action when finish selection
Delete
Load file in "No Name" viewer
Load Imp! file in "No Name" viewer
Backspace character
Delete next character
Backspace word
Delete next word
Find next placeholder (middle blank key)
Find previous placeholder
Insert carriage return with leading spaces copied from previous line
Insert carriage return
Break node

Mouse button clicks are used for making selections.
CLICKS
SINGLE
DOUBLE
TRIPLE
extend

LEFT

~IDDlE

Select letter
Select node

Select word
Select branch

RIGHT
Extend selection at current level
Reduce selection level and extend
Increase selection level and

Selections are used for delete, copy, and move.
CTRL-select
SHIFT-select
CTRL-SHIFT-select

Delete when finish selection
Copy to primary
Move to primary

LOOK commands are used for editing looks. (The LOOK shift is the top blank key.)
LOOK-char
LOOK-SHIFT-char
LOOK -space

Add look to selection
Remove from selection
Remove all from selection

Except for CTRL-A. CTRL-H. and CTRL-W, the following commands are not enabled for beginning
users. We provide both CTRL-A and CTRL-H as a convenience to users with strong habits from
previous systems. A ..... indicates a command enabled for advanced users only.
CTRL-A
CTRL-SHIFT-A
CTRL-B
CTRL-C
CTRL-SHIFT-C
CTRL-CLICK-C
CTRl-SHIFT-CLICK -C

Backspace character
Delete next character
Insert matching placeholder brackets
Lower case
Upper case
Initial caps
First cap

CEDAR 4.2

TIOGA EDITOR

CfRL-D
CTRL-E
CTRL-F-select
CfRL-H
CfRL-SHIFT-H
CfRL-I
CfRL -SHIFT-I
CfRL-J
CfRL-K
CfRL-SHIFT-K
CTRL-M
CfRL-N
CfRL-SHIFT-N
CfRL-O
CTRL-SHIFT-O
CfRL-P
CfRL-Q-select
'CfRLos-select
CfRL-T
CfRL-V
CfRL-W
CTRL-SHIFT-W
CfRL-x-select
CfRL-Z-select
CfRL-)
CTRL-[
CfRL-!
CfRL-"
CfRL-SHIFf-"
CfRL-\
CfRL-SHIFf-\

Select document
Expand abbreviation
Copy format to primary *
Backspace character
Delete next character
Indent (does Break and Nest) *
Unindent (does Break and UnNest) *
Join nodes *
.
Make control character
Unmake control character
Automatic MESA formatting
Nest *
.
UnNest *
Make octal character
Unmake octal character
Paste
Copy looks to primary
Copy primary to selected destination
Time
Select visible (expand to selection to blanks)
Backspace word
Delete next word
Select for transpose with primary
Move primary to selected destination
Select matching [..]'s (same for }, ), and »
Add matching [..]'s (same for", " -, {, (, and <)
Have Tioga read its TIP tables again •
Set format to word before caret •
Insen format name •
Set comment property TRUE *
Set comment property FALSE •

CEDAR 4.2

37

How To Use Walnut
Version 4.2
Release as
Came from

By
Last edited

[Indigo ]Manual)WalnutDoc. tioga, .press
Willie-Sue Haugeland
By Willie-Sue Haugeland on June 8, 1983 4:03 pm
Jim Donahue on June 2, 1983 1:17 pm

Abstract
Walnut is a computer mail system interface that runs in Cedar. It provides facilities
to send and retrieve mail (using the Grapevine mail transport system), and to display and classify
previously retrieved messages.

Walnut is under active development. This document describes how to obtain and use Walnut
4.2, the latest version of Walnut released with Cedar 4.2.

How to Use Walnut: Contents
O. Introduction
1. Database structure

2. User interface
3. The log
4. Becoming a user
5. Coping with releases and crashes
6. User profile options
7. Shortfalls and wishes
[If you are reading this document on-line, try using the Tioga Levels and Lines menus
(if you can) to initially browse the top few levels of its structure before reading it
straight through.]

XEROX
DRAFT

Xerox Corporation
Palo Alto Research Center
3333 Coyote Hill Road
Palo Alto, California 94304

For Internal Xerox Use Only - DRAFT

How TO USE WALNUT

2

o. Introduction
Walnut is a mail system that runs in Cedar. Walnut provides facilities to send and retrieve mail
(using the Grapevine mail transport system), and to display and classify stored (Le. previously retrieved)
messages. Walnut uses the Cypress database system to maintain infonnation about stored messages; we
hope that this will allow Walnut to integrate smoothly with new applications, such as a calendar system
or an online "white pages".
Walnut is under active development. It is not unusual for new versions of Walnut to be distributed
to willing users between fonnal Cedar releases. Though the underlying database structures used by
Walnut change from time to time. these changes never require any hand-editing on the part of users;
Walnut performs the conversions automatically.

WAL~UT42

How TO USE WAL:-.IL'T

3

1. Database Structure
We shall describe a user's model of Walnut's database. This model suppresses many details whose
understanding would be required in writing a new application on Walnut's database. but are irrelevant
for accessing the database through Walnut's user interface,
Walnut's database contains two entity types: message and message set.
A message entity corresponds to a message retrieved from the Grapevine mail transport system.
Like all database entities it has a name. consisting of the sender's RName concatenated with
a unique message ID provided by Grapevine. A message also has several immutable
properties: its sender. its subject. and so on. Its unread property is a BOOL whose value is
TRUE when the message is first stored in the database. and is set to FALSE when the message
is first displayed.
A message entity is also a member of one or more message sets. A message set entity is named by
a text string containing no embedded blanks. There are two distinguished message sets:
Active and Deleted. A newly-retrieved message is made a member of Active. A message that
is removed from all other message sets is added to Deleted. Using the Active and Deleted
message sets in this way ensures that each message belongs to at least one message set.

WAL~L'T

42

How TO USE W ALNlrr

4

2. User Interface
Walnut implements four viewer types: the Walnut control viewer, the message set display viewer,
the message display viewer, and the message composition viewer. When Walnut is running there is one
Walnut control viewer, and any number of instances of the other viewer types. The iconic form of the
Walnut control viewer is a mailbox. Anything that can be done with Walnut can be done by starting
from the control viewer (sometimes by creating other viewers).
Walnut's user interface attempts to be consistent with conventions used elsewhere in Cedar. Clicking
LEFT on a button representing a Walnut entity (a message or a message set) "selects" the entity (makes
it an implied parameter to other operations); clicking MIDDLE on such a button opens the entity (displays
more information somehow). This is analogous to the behavior of icons in Cedar.
Unless otherwise specified. hereafter "click" means "click with the LEFT mouse button".
2.1 Message sets

The message sets in a Walnut database are represented by buttons in the Walnut control viewer.
The Active and Deleted message set buttons always appear first; other message set buttons appear in
alphabetical order. There may be several rows of these buttons.
To create a new message set (containing no messages) type its name into the MsgSet: field of the
control viewer, then click Create. A message set button with this name will appear. Similarly, to delete
an existing message set, type its name and click Delete. Walnut requests confirmation if the message
set contains any messages. If you delete a message set containing messages, the messages are deleted
from the set (as if clicking each message with CTRL·LEFT as described below) before the set is destroyed.
To find out how many messages are currently in a message set, type the name of the set and click
SizeOf.
To create a message set display viewer. click MIDDLE on the corresponding message set button of the
control viewer. The iconic form of a message set displayer is a stack of envelopes.
The message set displayer contains a one·line button for each message in the set Each message
button looks much like a line in the top window of Laurel: it shows the date of the message, the name
of the sender (or To: field if the sender is the current user). and the message subject At most one of
the message buttons in a set is selected (shown with a grey background). To select a message, click LEFT
on it; to select and display a message, click MIDDLE on it To delete a message from the message set,
click CTRL·LEFT on it; its button will disappear. (Note that if this message belonged to no other message
set, it is added to the Deleted set, and hence is still accessible.)
A message set displayer also contains several command buttons that operate on the selected message.
Categories lists (in the Walnut control window) the message sets in which the selected message
appears (a message can simultaneously be in several message sets).
MoveTo adds the message from the message set to all of the message sets selected in the control
window, after first deleting it from the message set.
.
Display displays the selected message.
Delete deletes the message from the message set; if it thus becomes a member of no other message
sets, then it is moved to the Deleted message set
AddTo adds the messages to the selected sets without first dbing the deletion.
Finally, the Active message set includes a NewMaii button that reads new mail and adds the messages
read to this message set.
For the MoveTo, Delete, and AddTo buttons, LEFT·clicking simply performs the operation desCribed
above, while RIGHT· or MIDDLE· clicking performs the operation and displays the next message in the set

WAL:--iLi4.2

How TO USE WALNl;'T

5

2.2 Messages
As described above. a message can be displayed by clicking MIDDLE on a message button of a message
set displayer. This creates a message display viewer. whose iconic form is an envelope (clicking
SHIFT·MIDDLE on a message button causes the created viewer to fill the entire column). The message
within such a viewer is not editable. This viewer is associated with the message set that created it. so
clicking MIDDLE on anottter message of the same message set shows this new message in the same message
displayer. This is designed to avoid a proliferation of message displayers. Of course. there are times
when you really want to create viewers on several different messages in one set. Clicking a message
displayer's Freeze button (which then disappears) permanently binds the message to the message
displayer. If all message displayers for a given message set are frozen. then MIDDLE clicking in the
message set creates a new displayer. A frozen message displayer cannot be unfrozen. but can be
destroyed.
A message displayer has several other buttons. The Categories button is the same as that on
message set displayers. Answer and Forward create a Walnut Send viewer initialized either with a
proper heading for an answer to the message or a copy of the message for forwarding. The Print button
uses the TSetter to print the message -- it will complain (in the Walnut control window) if the TSetter
is not loaded. And the remaining Split. Places and Levels buttons are from Tioga.

2.3 Sending mail
To create a message composition viewer click the NewForm menu item in the Walnut control viewer.
or use the Answer or Forward buttons on a message display viewer. [n iconic form this viewer is the
back of an envelope. with the title "WalnutSend ... 6/02/83". The message composition viewer is a Tioga
viewer for typing in the message header fields and message body. NewForm, PrevMsg. and GetForm
menu items are guarded while the Sender is dirty. When a command requires confirmation. appropriate
buttons appear in the viewer menu area; the control window is used for messages.
Clicking the Clear button of a message composition viewer causes its message text to be replaced
by a standard message form. PrevMsg restores the contents of the last successfully sent message.
GetForm loads into the viewer the file whose name is currently selected (if no file extension is given
and no file is found with the selected name. the extension ".form" is used); it also sets the input focus
at the first placeholder. Confirm and Deny buttons appear for confirmation if the existing message text
has been edited. StoreMsg stores the contents of the viewer in the selected file: this gives a way to save
partially composed messages.
The Split. Places and Levels menu items are the usual Tioga operations: if a message composition
viewer is split. then NewForm. PrevMsg and GetForm operations on a split viewer will cause all but
the one bugged to be destroyed (the message composition viewer becomes "unsplit"). This will also
happen if Answer or Forward reuse a split message composition viewer.
Clicking the Send button initiates the sending process. If the message is addressed to a public
distribution list or to more than twenty individuals. it probably should contain a Reply-To: field. If it
does not. a message is printed in the control window and buttons labeled Self. All, and Cancel appear.
These buttons mean "Reply-To: sender", "no Reply-To: field", and "Reply-To: sender but don't send".
respectively. If errors occur in sending. a message is printed in the control window. If the transmission
is successful. the message is saved and a new form appears: RIGHT-clicking Send causes the message
composition viewer to become iconic after syntax checking has been done. While a Send is in progress,
the viewer is not editable. An AbortSend button is visible during part of the sending process. should
you decide not to send the message. The last successfully sent message can to restored by clicking
PrevMsg.
Clicking the Destroy button asks for confirmation if there is an unsent message in the viewer. It is

WADil.:'T 4.2

How TO USE WALNl.rr

6

a bad idea to destroy a message composition viewer while message transmission is in progress.
2.4 Retrieving mail

Walnut polls the mail servers at regular intervals. If there is new mail for the logged-in user, the
Walnut control viewer displays a message like
You have new mail at 27 ·Sep·82 14:28:45 PDr
Clicking the NewMaii button in either the control viewer or the Active message set viewer retrieves
all the new mail. You can "button ahead" during message retrieval. The new messages appear as
buttons at the bottom of the Active message set viewer, with a "?" in the leftmost column of each new
message button to show that the message is unread. If the control window is iconic and there is new
mail, the flag on the icon is raised: for convenience, there is a NewMail button in the Active MsgSet
displayer, which will retrieve the waiting mail.

2.5 Global operations
The Walnut control viewer has a few more buttons that will now be described. Clicking Commit
commits all changes that you have made to Walnut's database. The only other operations that
automatically commit database changes are Destroy and CloseAIi. If you perform a Walnut operation
that updates the database and then boot or rollback without doing a Commit, the effects of that operation
are in the log and will be performed on the database and then committed when you next run Walnut
The CloseAII button furnishes a quick way of ending a session with Walnut CloseAII destroys all
message displayers, and closes all message set displayers. Then it executes a Commit and closes the
Walnut control viewer.
.
The Archive operation provides a way to copy a set of messages into a file that can later be read by
either Walnut or Laurel. Type a filename into the On File: field and click Archive. All messages in the
currently selected message sets are copied to the named file (if the file name has no extension,
".ArchiveLog" is assumed).
Clicking the (guarded) Expunge button expunges the Walnut database: all messages in the Deleted
set disappear without a trace. (Laurel purges deleted messages every time you Quit or change mail files.)
Without the Expunge operation, Walnut's database would grow without bound. The Expunge operation
may fail if your disk is nearly full: this is a motivation for regular Expunges. Section 4 contains more
information on this topic.
Finally, clicking the Destroy button causes Walnut to commit and then close the Walnut database.
This is a good thing to do before booting or rolling back: it redtices the possibility of mangling the
database.
Walnut registers several infrequently-used commands with the Cedar Executive. All of the command
names contain the prefix "Walnut", so typing Walnut-? to the Executive enumerates them. The Walnut
command creates a Walnut control viewer if you should happen to Destroy yours. The WalnutExpunge
command has the same effect as clicking Expunge, but can be used when the control viewer does not
exist. The WalnutOldMailReader command is described in Section 3, and the WalnutScavenge
command is described in Section 4. WalnutNewMail simulates clicking the NewMail button.

WALNt.:T 4.2

How TO USE W ALNL'T

7

3. The log
Walnut keeps a record of all retrieved messages and all database updates for a single user in a
Walnut log file. This is a text file with a very simple format (an extension of the .mail format used by
Laurel and Hardy); load your Walnut log into a Tioga viewer to see this. (Since your Walnut log be a
large file, you may wish to use the Open Huge command to load it into a Tioga viewer.)
The important point is that the truth about your Walnut mail resides in a Walnut log file; the
Cypress database that Walnut uses for query processing can always be reconstructed by replaying a
Walnut log file. The Walnut log mechanism is very robust, which makes Walnut's mail storage quite
reliable even if Walnut (or some other part of Cedar) crashes.
Walnut locates the log file for a particular user by consulting the Walnut.WalnutLogFile entry of
the user profile. If there is no such entry. the name Walnut.DBLog is assumed. At present, the log file
must reside on the Cedar workstation's local disk. This means that to use Walnut on a public Dorado,
you must copy the log to the Dorado from a file server, then stan Walnut (Walnut command to the
Executive). At the end of a public Dorado session you must stop Walnut (Destroy button), then copy
the log to a file server. Soon, Walnut will be capable of accessing a Walnut log stored on an Alpine file
server, just as it can access Cypress databases today.
A Walnut log grows with each retrieved message and database update until an Expunge command
is given to the Executive. This command writes a new Walnut log that only contains information about
the messages that have not been deleted. and updates the database to be consistent with this. (Note that
this requires disk space for two copies of the log.) Because the cost of a full Expunge is proponional to
the size of your Walnut log (which can grow to be quite large, if you are a "pack rat"), there is a "shon
cut" Expunge that only deletes messages from the point in the log of the previous Expunge; it is enabled
by setting the Walnut.EnableTailRewrite user profile option. When enabled. LEFT-clicking Expunge
causes the shon-cut expunge to be performed. while RIGHT-clicking performs the full expunge. Note
that with the tail-rewrite expunge any quite old messages that you delete (which appear before the
expunge cut-off point) will not be removed from the log or database; thus. once in a while you will still
need to do a full expunge.
Jim Morris's advice concerning files on the local disk is to "keep your bags packed". A prudent
individual will apply this philosophy to his Walnut log. Include this file in a personal .df file (such as
the one that contains your user profile), and make it a habit to SModel it every few days.

WADiL'T 4.2

How TO USE WALNlrr

8

4. Becoming a User
4.1 Standard usage
First, bring over the latest Walnut by typing
Bringover /a /p Top>Walnut
to the Executive: this will also retrieve WalnutSend, Cypress. and AlpineUserImpls. These latter files
will be loaded by Walnut (AlpineUserImpls only if needed).
,

Edit your personal profile to contain all of the entries specified in WalnutDefaultprofile (public in
Walnut.dO. The only profile entry that most users will want to experiment with is "InitialActiveRight:
TRUE"; making it FALSE causes the Active message set displayer to create itself in the left viewer column.
like all other message set displayers.
To start Walnut. type
Walnut
to the Executive. This will spend a long time loading. but finally a Walnut control viewer will appear.
You can include Walnut in a checkpoint. Be sure not to click checkpoint until the message "Walnut
4.2" appears in the Walnut control viewer typescript. Message and Message set displayers get updated
after each rollback: if a displayed message or message set has since been deleted. the viewer will be
destroyed.
To read a Laurel or Hardy mail file. or a file created by Walnut's Archive operation. first run
Walnut as just described. Then type
WaJnutOldMailReader  {optional message set name}
to the Executive. If you fail to specify a message set name. the messages will be placed in Active. If
the specified message set does not exist. it will be created.
4.2 Using Alpine for Walnut database storage
The Alpine server "Luther.alpine" can be used to store Walnut databases. Using Alpine improves
Walnut performance somewhat. especially for operations that write to the Walnut database. It frees up
space on the local disk that is otherwise occupied by the Walnut database. It also reduces the cost of
using Walnut on a public machine (you move only the log to the new machine. not the log and database.)
The drawback of using Alpine is that on occasion it may abort Walnut's transaction; Walnut will recover
from this gracefully. but it may take some time to replay your uncommitted actions stored in the log.
Transaction aborts are infrequent. so on balance the Alpine server is an improvement over the local disk.
Contact Karen Kolling to obtain an Alpine account.
Using Alpine changes the procedure for Walnut installation only slightly.
Edit your personal profile to contain the entries:
Walnut. WalnutSegmentFile: "[Luther.alpine]Walnut.segment"
Walnut. WalnutLogFile: "YourName. WalnutDBLog"
With your profile in this state. you must run AlpineUserImpls before invoking the Walnut command.
One way of ensuring this is to include the items
Run AlpineUserlmpls; RunAndCall Walnut
in your CommandsFrom: profile entry. It is ok to take a checkpoint after running AlpineUserImpls
and Walnut.

WAL="iUT 4.2

How TO USE W AL:-.iUr

9

There are two ways to create a Walnut database on Alpine. The first is to follow the procedure
above, in which case Walnut will notice the absence of a database and create one by scavenging from
the log. The second is to copy the database from the local disk to the Alpine server, using the procedure
call
4AlpineCmds.Copy[to:
"Walnut.segment"]

"[Luther.alpine]Walnut.segment" ,

from:

You must run AlpineUserImpls before attempting to call this procedure. For more information on
Alpine operations consult [Indigo]Oocumentation>Overview.tioga•. press
[Indigo ]Manual>Overview. tioga. .press
by Horning on June 1. 1983 6:48 pm

Abstract: This Overview is intended to introduce you to the basic vocabulary and concepts that
you need before plunging into sources of more detailed information about the Cedar Language.
It assumes that you have already read the Briefing Blurb and the Introduction to Cedar.
If you haven't, read them first and retu rn. It starts with a brief review of the common concepts
that Cedar shares with other members of the Pascal family. then gives a somewhat less hasty
tour of the more novel features of Mesa. followed by a discussion of the additional changes that
produced Cedar. Finally, there is a guide to sources of further information.
Version 4.2 of the Cedar language documentation corresponds to Release 4.2 of the Cedar
system. It is intended to supersede aI/ descriptions prior to June 1983. Previous documents may
be read for historical interest. but are believed only at the reader's peril.
[If you are reading this document on· line, I suggest that you use the Tioga Levels and
Lines menus to initially browse the top few levels of its structure before reading it
straight through.]

XEROX

Xerox Corporation
Palo Alto Research Center
3333 Coyote Hill Road
Palo Alto, California 94304

DRAFT - For Internal Xerox Use Only - DRAFT

CEDAR LANGUAGE OVERVIEW

Cedar Language Overview: Contents
Introduction
Review of the Pascal-like features
Data and types
Statements

FroDl Pascal to

~esa

Modules
Exceptions
Processes, monitors, and condition variables
Control constructs
Miscellaneous

FroDl

~esa

to Cedar

Garbage collection, collectible storage. and REFs
Safety
Delayed binding
Misce/laneous

Converting

~esa PrOgraDlS

to Cedar

Simple Programs
New language features
Restrictions of the safe language

For More InfofDlation ...

CEDAR 4.2

2

CEDAR LANGt.:AGE OVERVIEW

3

Introduction
The programming language of the Cedar Programming Environment (hereafter. Cedar Language. or
just Cedar) has resulted from an evolutionary process in PARC and SDD that spanned more than a
decade. Understanding what the language is. and why it is that way. may be somewhat easier with a little
historical background:
Mesa is a system implementation language in the "Pascal family." with extensive facilities for
modularization and separate compilation. processes and monitors. exceptional-condition handling.
and control of low-level hardware functions. It was initially designed and implemented in the PARC
Computer Science Laboratory. primarily by Butler Lampson. Chuck Geschke. Jim Mitchell. Ed
Satterthwaite. and Dick Sweet. Subsequently. the OSD System Development Department assumed
responsibility for development and maintenance. It has gone through a series of releases.
When CSL launched the Cedar Project in 1979. it chose to use the Mesa language and system as a
starting point. (Mesa 6. 7. and 8 are its closest relatives.) However. Mesa did not have a few of the
features that seemed to be important for an experimental programming environment. so some
extensions and changes were designed. The major changes resulted from adding automatic storage
deallocation (garbage collection) and facilities for delaying the binding of type information. without
sacrificing complete type-checking in either case.
This Overview is intended to introduce a competent programmer to the basic vocabulary and
concepts that are needed before plunging into sources of more detailed information about the Cedar
Language. It assumes that you know some other language in the Pascal family. It also assumes that you
have already read the Briefing Blurb and the Introduction to Cedar. If you haven't. read them first and
return.
This Overview starts with a brief review of the common concepts that Cedar shares with other
members of the Pascal family, then gives a somewhat less hasty tour of the more novel features of Mesa.
followed by a discussion of the additional changes that produced Cedar. It ends with a survey of sources
for further information.
This Overview does not provide the detail you need to actually write Cedar programs. (In particular,
the reference grammar is included but not discussed.) But when you finish reading it., you should have
a fair acquaintance with Cedar terminology and concepts. and you should have a good idea of what you
need to learn. Different things are discussed in varying depth: generally the long discussions cover things
that you should plan to study carefully.
Cedar documentation is still evolving. Comments and suggestions on how it can be made more
useful are welcome at any time. Although we plan a systematic attempt to assess the effectiveness of the
various kinds and pieces of documentation. you should not wait until asked to let us know what you
think about it
Various proposals and descriptions of interim implementations from September 1979 onward have
been given labels such as SCI. 5C2. 6C2. 6C5. TrU. and Version 3. Version 4.2 of the Cedar language
documentation corresponds to Release 4.2 of the Cedar system. It is intended to supersede all descriptions
prior to June 1983. Previous documents may be read for historical interest. but are believed only at the
reader's peril. This Overview has been compiled by Jim Homing: errors and sources of confusion should
be reported to him. Most of the contents have been abstracted from previous documents. with a small
amount of editing and validity checking.

CEDAR 4.2

CEDAR LANGUAGE OVER VIEW

4

Review of the Pascal-like features
The following summarizes aspects of Cedar (and Mesa) that are basically similar to those of other
members of the "Pascal family" of languages (e.g., Euclid, Modula, Ada). If there are any concepts in
this section that are not already familiar to you, you should probably find a Pascal textbook and study
it before proceeding to further material on Cedar. (You will find that the names for these concepts vary
somewhat from language to language.)
An algorithm or computer program consists of two essential parts, a description of actions that are
to be performed, and a description of the data that are manipulated by these actions. Actions are
described by statements, and data are described by type definitions.
Data and types
Data are represented by values. Values are immutable: they are not changed by computation. A
constant always denotes. the same value within a scope. A variable is a value that may contain another
value; assignment changes the value contained by a variable, but not the value that ~ the variable.
A value used in a program may be represented by a literal constant, the name of a constant or
variable. or by an expression. which will itself contain other values. Every name occurring in the program
must be introduced by a declaration. A declaration associates with a name both a data type and a constant
value (which may itself be a variable, and contain different values at different times).
A data type defines both a set of values and the actions that may be performed on elements of that
set It may either be directly described in a declaration that uses it, or it may be referenced by a type
name. introduced in.a type declaration. The type of every constant, variable, and expression can be
deduced from static analysis. This analysiS is performed by the compiler to ensure that all programs are
type-correct: thus the language is said to be strongly typed.
An enumerated type definition indicates an ordered set of values, i.e., introduces names standing for
each value in the set. The simple types are the enumerated types, the sub range types. and the built-in
types, including BOOt. Il'oT, REAL, and CHAR. There are standard denotations for literal constants of the
built-in types: TRUE and FALSE for BOOL, numbers for INT and its subranges and for REAL. quotations
for CHAR. Numbers and quotations are syntactically distinct from names-as are the "reserved words"
of the language. The set of values of type CHAR is an 8-bit variant of the ASCII character codes.
A type may be defined as a subrange of a simple type by indicating the smallest and largest value
of the subrange.

Structured types are defined by describing the types of their components, and indicati~g a structuring
method: ARRAY or RECORD. These differ in the mechanism for selecting a component of a value.
In an array structure. all components are of the same type. A component is selected by a computable
selector. or index. The index type. which must be simple, is indicated in the a~ay type definition. It is
usually a programmer-defined enumerated type, or a sub range of INT. Given a value of the index type.
an array selector yields a value of the component type. Every array structure value can therefore be
regarded as a mapping of the index type into the component type.
In a record structure, the components (called fields) are not necessarily of the same type. In order
that the type of a selected component be evident from the program text (without executing the program),
a record selector is not a computable value. but must instead be a name uniquely denoting the component
to be selected.
A record type may be specified as consisting of several variants. This allows different record values
of the same type to have structures that differ in the number of components. their types, or their names.
The variant describing a particular value is indicated by a special field, called its tag. Variants of a type

CEDAR 4.2

CEDAR LANGUAGE OVERVIEW

5

may also share fields in addition to the tag.
An explicit variable declaration associates a name and a static variable; the name is used to denote
the variable in expressions. Dynamic variables are generated by a special procedure (NEW) that yields a
pointer or reference value that subsequently serves in place of a name to refer to the variable. Finite
graphs in their full generality may be represented using pointers or references.
Statements
The simplest statement is the assignment statement. [t specifies that a newly computed value be
assigned to a variable (or a component of a variable). The value is obtained by evaluating an expression.
Expressions consist of variables. constants. operators, and procedure values operating on arguments to
produce new values. Constants are literal or declared: variables and procedures are built-in or declared;
the set of operators is defined within the language. and includes operators for arithmetic. comparison.
and logical operations.
The procedure statement causes the application (invocation. call) of a designated procedure value to
the values of its arguments (actual parameters).
Basic statements are the components of structured statements. which specify sequential. selective. or
repeated execution of their components. Sequential execution of a sequence of statements is specified by
separating them by semicolons; conditional or selective execution by the if statement and the select
statement: and repeated execution by loop statements.
A block can be used to associate declarations with statements. The names so declared have Significance
only within the block. Hence. the block is the scope of these names. and they are said to be local to the
block. Since a block may appear as a statement, scopes may be nested.
A block can be the body of a procedure value. A procedure has a fixed number of parameters. each
of which is denoted within the procedure by a name called the formal parameter. Actual'argument values
are supplied for parameters at each application.
Procedures may also have results: applications of such procedures may appear within expressions.

CEDAR 4.2

CEDAR LANGuAGE OVERVIEW

6

From Pascal to Mesa
Mesa extended Pascal in a number of directions intended to make it more effective for the
development of large systems. Students of programming languages will discern influences from Algol 68,
BCPL, and several other system implementation languages. It is a larger language, and is rather more
difficult to master in its entirety, than Pascal. It is intended for professional programmers, not for
beginning students.
Mesa modules are separately compiled program units, with type-checking preserved across module
boundaries. Mesa provides mechanisms for systematic handling of exceptions. processes and monitors,
procedures as first-class values that can be assigned to variables. and a fair number of syntactic and
semantic amenities intended to make programming more convenient.
The following sections introduce each of the major conceptual extensions. but do not explain them
in great depth. See (Geschke, et a/.J for a more extensive rationale, and CSL-79-3 for full details.

Modules
Mesa modules are a "programming in the large" mechanism for partitioning a system into manageable
units. They can be used to encapsulate abstractions. to provide a degree of protection, and to enforce
"information hiding." They are also the units of separate compilation.
There are two kinds of modules: DEFINITIONS modules, which define interfaces, and PROGRAM
modules, which contain the executable code to implement these interfaces.

Definitions (or deft) modules define interfaces to abstractions. They typically declare some shared
types, useful constants, and the domains and ranges of a set of procedure names. They compile into
symbol tables. which are shared by both clients and implementations. Checks are performed when modules
are bound into a configuration to ensure that separately compiled pieces have used consistent versions of
the shared definitions. Interfaces produce no executable code: they manifest themselves at runtime
primarily as symbol tables that are accessible for debugging and similar purposes.
Program modules provide implementations of abstractions. They typically declare collections of
variables that define their state and provide bodies for the procedures of their interfaces. Viewed as
source text, they are similar to Pascal procedures and Simula class definitions. They can be loaded and
interconnected to form complete systems.
At runtime. one or more instances of an implementalion may be created. A separate global frame
(activation record) is allocated for each. containing storage for its global variables (those which are
declared outside its procedures), which persist between applications of its procedures. The lifetimes of
implementation instances (unlike those of procedure applications) are not restricted to' follow any
particular discipline. Communication paths among implementations are established dynamically and are
not constrained by any (static or dynamic) nesting relationships: lifetimes and access paths are completely
decoupled. The module body itself generally contains the code to initialize the global variables and
establish any necessary invariants. It will be executed when the module is started, or upon application of
one of the module's procuedures, whichever comes first.
A module that accesses (relies on declarations from) other modules must include DIRECTORY
statements. so the necessary symbol tables can be acquired. If it uses only a subset of the declarations. it
is good practice to indicate which ones with a uSING list. Declarations in an interface are public unless
declared to be PRIVATE. Normally the importing module accesses only the public names: private
declarations may be accessed by implementing modules that indicate they SHARE the interface. A directory
statement may list the name of a file containing the symbol table to be used, but if the file name is the
same as the module name (except for the extension .bed) it is omitted.
A module that uses non-constant declarations (e.g.• exported types and procedures) from another

CEDAR 4.2

CEDAR LANGUAGE OVERVIEW

7

module must explicitly imporl it. If a module implements any part of an interface (e.g., by supplying the
value of a procedure or type that it declares), it must explicitly export it. The compiler will check that
its PUBLIC declarations are type-consistent with the corresponding declarations in the exported interface(s).
Each module is effectively parameterized by a set of inter/ace records, one for each interface it
imports, and supplies a set of export records. one for each interface it exports. Note that interfaces and
implementations need not be in one-to-one correspondence. Binding a group of modules together into a
configuration involves assigning values from the export records to the corresponding fields in the interface
records. There is a special sub language, C/Mesa. to control this process.
Accessing other modules introduces compilation order dependencies. Each module must be compiled
after the modules it accesses (and recompiled if they change). since the compiler needs their symbol
tables. But information does not flow in the other direction. Modules that are not accessed by others
(virtually all implementations) may be freely recompiled without invalidating previous compilation and
checking of any other modules.
Types. as well as procedures. can be declared opaquely in interfaces and subsequently bound to
concrete values supplied' by implementations. This makes the internal structure of the type invisible to
clients of the interface. and ensures that there can be no compilation dependencies between the definition
of the concrete type and the interface module. The definition of the type can be changed at any time
without requiring recompilation of the interface or any clients of the interface.
Effective use of Mesa requires a thorough understanding of modules and their use. They have
significantly influenced our program design and construction techniques.
Programs are almost never self-contained modules: the importation and re-use of existing code has
all the advantages of theft over honest toil-without the moral stigma. Considerable emphasiS is laid on
the careful design of iilterfaces. and on their documentation. Since it is only interface changes that force
recompilation (or perhaps even rewriting) of client programs. it is important that interfaces remain stable
for substantial periods., even while their implementations are undergoing change.
A recommended approach is to define, comment. and circulate for review, all of the interfaces in a
(sub)system before writing any of the implementations. Interfaces play much the same role as "program
design languages" in other environments. with the additional advantages of being precisely defined and
mechanically enforced.
The Mesa language definition omits many of the features commonly expected in programming
languages. such as input/output and string-manipulation operatiens. Of course. these facilities are available
to Mesa programmers. but they are provided by packages written in the language itself. The descriptions
of standard packages in the Mesa Programmer's Manual. Version 8.0, run to more than 300 pages.
When managing large collections of modules (and in systems like the Mesa' Development
Environment and Cedar they run into the thousands). module names become very important. The use
of cryptic or acronymic names is discouraged. By convention, source file names have the extension .mesa.
and object file names have the extension .bcd (for Binary Configuration Description). The definitions
module for an interface X is customarily named X: if it is implemented by a single program module,
that is customarily named XImpl.

Exceptions
Mesa provides a way to indicate when exceptional conditions arise in the course of execution and
an orderly means for dealing with them that is inexpensive if they do not arise. Exceptions cause a
transfer of control from the statement that raises them to a dynamically-selected part of the program
intended to handle the situation. They may be raised in response to the detection of "impossible"
situations. invalid inputs, the inability of an abstraction to supply its specified service. or simply unusual
events.

CEDAR 42

CEDAR LANGI,;AGE OVER VIEW

8

Mesa exceptions are conceptually similar to procedures, except that the binding to the handler is
determined by searching the catch phrases in the call stack of the process in which the exception is
raised: the dynamically innermost handler that accepts the condition is applied. Like normal procedures,
handlers can take parameters and return values. They are written in a distinctive syntax that clearly
identifies them as code for the exceptional case.
Catch phrases are syntactically and semantically similar to SELECf statements, with test items'
indicating the exceptions for which the associated handler should be applied. There are special test items
to catch arbitrary exceptions and to c'ltch an attempt to unwind the application stack in response to an
exception. A series of catch phrases may be associated with a procedure application, or enabled throughout
a block.
A handler is like a procedure body, but when it completes. there are a number of additional control
options: GOTO, EXIT, LOOP, RETRY, CONTINUE, REIECf. and RESUME. Resumption is analogous to
returning from a procedure. possibly with a result Exceptions are divided into SIGNALs, which may be
resumed. and ERRORS, which may not: in common parlance they are generally all called signals.
Since handlers may take parameters and return results, each exception name must be declared in a
scope that includes all the points where it is raised as well as all the catch phrases that accept it.
The cost of raising an exception is significantly higher than the cost of procedure application. but it
shouldn't happen very often. The system guarantees that all exceptions are handled at some level: those
that the program fails to catch are accepted by the debugger. keeping intact the state of the program
that raised it.
Exceptions can be used in very intricate ways to achieve subtle effects (e.g., by raising another
exception within a handler). Experience has shown that this is almost always a mistake. Some call it
elegance, others call it incomprehensible:
"For the programmer. the main impon of nested signals is that one needs to consider. when writing
a routine, not only what signals can be generated. directly or indirectly. by the called procedures.
but also those which can be generated by catch phrases in that procedure or even the catch phrases
of any calling procedures, also both directly and indirectly." [Mesa Language Manua~
Although his language proposals have not been implemented. Roy Levin's discussion in the-working
paper [IndigojfARROW will succeed.
A PROC type may also have ANY in place of the type of its formal parameter record type and/or
result record type. PRoc values with specific domains and ranges may be widened to these dynamic
types, and later tested and narrowed analogously to REF ANYS. They must be narrowed before being
applied.
In principle, each value in Cedar carries its syntactic type with it at all times. In practice. almost all
analysis and checking of types is done by the compiler. and both space and time efficiency are gained
by not storing constant types with values. However. the symbol tables produced by the compiler contain
enough information to recover any type on demand. made available through a standard package.
RuntimeTypes provides type-conversion routines in both directions between typed values (with type
RTTypesBasic.TV) and ordinary Cedar values. and numerous operations on typed values to examine the
type and structure of a typed value. to change its attributes. etc. Thus it is possible to write a program

CEDAR 4.2

CEDAR LANGUAGE OVER VIEW

16

that deals with any given Cedar value or type without anticipating the specific type when the program
is written. Programs such as Bug Bane (the Cedar debugger) absolutely require such flexibility.
The current implementation is too slow to be used effectively by client programs as a substitute for
true polymorphism in the language, but is suitable for examining and changing variables interactively
with the Cedar debugger.
Miscellaneous
Although Cedar was not intended as a research project in programming languages, its developers
were not immune to the temptation to make Mesa better in ways that were not strictly required to enable
the new programming environment. This section discusses a few of these new features.

Types as clusters of operations
Each type has an associated cluster of operations. The main purpose of this association is to support
a style of "object oriented" notation. Using a record-like notation, a procedure "field" will be looked up
in the cluster of the object's type, and then applied to the object and the other arguments.
It is preferred style in Cedar to use this object notation in invoking operations of interfaces designed
to support it. Consult the relevant package documentation if in doubt.
Each built-in type and type constructor in Cedar implicitly supplies a standard cluster. The cluster
extension mechanism is that each opaque or record type defined in a interface acquires all procedures
declared in the same module as parts of its cluster.
ROPES and 10

Mesa STRINGS are rather awkward objects. having been tuned for efficiency in a small-machine
(Alto) world, rather than for flexibility and convenience. They are POINTERS to fixed-length sequences
of characters. Considerable care is required to avoid surprising results, even for rather straightforward
string-processing applications. Cedar ROPES, on the other hand, are somewhat heavier-weight, more
convenient to use, and less prone to surprises. Several different implementations of ropes. efficient for
different purposes, provide the same interface.
Rope is a Cedar package that supports the creation and manipulation of immutable reference-counted
sequences of characters. Procedures are provided for concatenation. taking substrings, scanning. and other
operations. A client can provide specialized implementations for rope objects. The standard
implementation attempts to avoid copying when perfonning Substr, Concat and Replace operations. The
Rope package is the standard support for sequences of characters in Cedar..
Most of the common operations on input/output streams. plus string conversions that are commonly
used in dealing with input or formatting output, have been collected in the 10 interface. Implementations
are available for stream interfaces to all common devices. and to allow ropes and streams to be readily
interconverted.
LISTS

and A.TOMS

Cedar includes LIST OF as a new type constructor for singly-linked (by REFS) lists, and a constructor
for list values that mimics that of LIsp. avoiding the need for a lot of NEWS or CONSS. The analog of
LISP's CAR and CDR are provided by the standard fields first and rest. Unlike LISP, Cedar lists are
statically typed (although the element type may be REF ANY).
Cedar also has a built-in type ATOM. which can be used for values that are uniquely determined by
their print names. Any rope can be convened to an atom and conversely: the advantage of atoms is that.

CEDAR 4.2

CEDAR LANGUAGE OVERVIEW

17

unlike ropes. it is very cheap to compare them for equality; atoms may also have property lists. Atom
literals are just names prefixed by $.

CEDAR

~2

CEDAR LANGUAGE OVERVIEW

18

Converting Mesa Programs to Cedar - Jim Morris
This section assumes you already know how to program in Mesa (or that you have a Mesa program
to be converted), and is intended to explain the differences for programming in Cedar.
Simple programs
Let's suppose you want to run a simple program in Cedar. If an existing Mesa 5 or 6 program uses
fairly vanilla stuff, it's easy to convert:
The names of most interfaces and some procedures have changed. but the functionality is basically
the same.
The most obvious differences will be with strings and I/O. You should only need to know about
two interfaces for these: Rope and 10, respectively.
In general. the Cedar/Pilot community has dropped the use of "Defs" as a suffix for definition file
names, and introduced the suffix "Impl" for implementation files; e.g. "lnlineDefs" became
"Inline".
Here's what you need to do to your Mesa 5 or 6 program:
Change all STRINGs to ROPF3 (actually Rope.RoPE). Remove all allocations and deallocations of
strings. Change all references to StringDefs routines to use Rope or 10 routines. Rope provides
procedures to parse and manipulate ropes. [0 provides procedures to convert ROPEs to numbers
and back as noted below, One can now put special characters in rope literals by using the
escape character "\". ".,. \n , .. " inserts a carriage return (newline). " .. , \t ... " a tab, ",
. , \\ , . ." a backslash, and ". . . \123 . . ," the character whose octal code is 123. Note a
ROPE is immutable, unlike a string. Appending a character creates a new ROPE.
You should use specific sub ranges for numeric variables whenever possible, If you don't know the
range. use INT (32-bit integer), unless you know you don't need that big a number and know
you need efficiency. In those cases use INTEGER or NAT [0 .. 77777 B). Avoid using CARDlNALS
or LONG CAROlNALS: their main use is in dealing with STRINGs. The compiler recognizes the
abbreviation INT for LONG INTEGER. BOOL for BOOLEAN. CHAR for CHARACTER. and PROC for
PROCEDURE.
Change all references to I/O p~ckages of all kinds (streams, files, lTY) to use equivalent 19 routines.
10 is the only interface you should need to know about for I/O of almost any type of variable
or constant (ROPE. INT. etc.) to almost any type of device (keyboard. display, files, temporary
buffer etc.). 10 contains:
A set of CreateX routines for each kind of stream X-file, display. etc.
A set of GetX routines for each type X (integers. ropes. etc.)
A PutF routine that can be used with any type (integers. ropes, etc.) via a set of inline procedures
(inc. rope, etc.) which are used to tag the type of the arguments. It also provides a format
argument which may be used to get FORTRAN-style formatting of output. For example,
the format "%g" prints almost anything in default free-format:
stream.PutF["The sum of %g and %g is %g.\n", int(xJ, int(y], int(x+y) ]
A PutFR routine that is identical to PutF except it produces a rope as output instead of putting
its result on a stream. and a RS routine that makes a rope look like a stream so that the
GetX procedures can be used. Thus one can convert various types to and from ropes.
e.g. the following code which converts an integer to a rope and back:
r: ROPE" PutFR{, int[i]]:
j: INT" GetInt(RS[r]];
Make use of LISTs and SEQUENCEs instead of ARRAYs and DESCRIPTORs for ARRAYs. The interface
List contains some useful routines.

=

CEDARU

CEDAR LANGUAGE OVER VIEW

19

New language features
The changes in the Cedar language from Mesa 6 are fairly easy to understand for simple programs:
(a) REFs provide automatic deallocation and easier allocation:
Node: TYPE = REF Rec;
Rec: TYPE
RECORD{first: INTEGER. rest: Node];

=

x: Node .. NEW[Rec .. [5. :-.IlL]):
(b) Runtime types via REF ANY give looser binding:
TNode: REF BIRec:
Node: REF B2Rec;
x: Node ..... ;
t: TNode ..... :
q: REF ANY:
q .. t: q .. x: -- both of these are legal
t .. NARROW[q]: -- raises NarrowRetFault if q is not a TNode
-- q1' .. E is always illegal. You cannot update through a REF ANY.
-- type can also be checked explicitly:
WITH q SELECT FROM
m: TNode => {t .. m; q .. m.lson};
n: Node => {x .. n: q .. n.rest};
ELSE ERROR;
-- or
IF ISTYPE[q, TNode] THEN {t .. NARROW[q]: q .. t.lson}
ELSE IF ISTYPE[q, Node] THE:-.I {x .. NARROW[q]; q .. x.rest}
ELSE ERROR.
REF ANY is preferred to the use of variant records.
(c) Lists are built into the language:
LIST OF INT:
Node: TYPE
x: Node .. CONS[S, NIL):
y: Node .. LIST[S, 6]; -- same as CONS[S, CONs(6. NIL))
i: INT" y.first: -- i is 5
z:Node .. y.rest: -- z is CONs[6. NIL)
FOR 1: Node .. y. l.rest UI\I"TIL 1= :-.IlL 00 ..
(d) ROPES. ATOMS. SEQUENCES. and INTS are also built-in.
(e) To protect yourself and the garbage collector from obscure errors you should program in the
safe subset of the language. To get a program into the safe subset prefix each module
(PROGRAM. MONITOR, or DEFINITIONS) with the word CEDAR. The compiler will then tell you
when you are straying outside the safe subset You can wave the compiler off any block by
placing the word TRUSTED before it If you call a procedure declared in an unsafe interface
(Le.• one that doesn't start with CEDAR DEFINITIONS). the compiler will complain unless the
call is in a TRUSTED block. Most of the high-level interfaces in the Cedar system are now
safe.

=

Restrictions of the safe language

The @ operator is not permitted There are three general ways to cope with this restriction: specializing,
copying. and indirecting. For example. suppose you have a program that says
W: ARRAY [0.. 1(0) OF Z;

CEDAR 4.2

CEDAR LANGUAGE OVERVIEW

20

P[@W);
FOR i IN [0.. 100) 00 ... Q[@W[i)) ... END LOOP:
To eliminate the first @ by specializing we would make a copy of the procedure P that dealt with the
W directly-not very satisfactory. To eliminate the first @ by copying we would pass the array W in by
value and back by result-also not very satisfactory. It is best to deal with the first @ by indirecting;
just allocate W from collectable storage. writing
W: REF ARRAY [0.. 100) OF l = NEW[ARRAY [0.. 100) OF l);
P[W];
Eliminating the second @ by specialization is plausible if Q knows it is always dealing with array
elements: pass a reference to W along with an index. Otherwise. deciding between copying and indirecting
depends upon the size of a Z. If it is small copy it. writing "W[i] +- Q[W[i]]". If it is big create references
to it and pass those. writing
W: REF ARRAY [0.. 100) OF REF Z:
P[W):
FOR i IN [0.. 100) 00 ... Q(W[i)) ... ENDLOOP:
The form of variant record discrimination that does not copy the value to a new location cannot be
used. Suppose you have a variant-record data structure like
T: TYPE
REF TR:
TR: TYPE = RECORD{SELEcr t:* FROM
name. string => [x: ROPE];
link = >[i: INT. r: T):
ENDCASE):
and are accustomed to performing discriminations like
e: T;
WITH x: et SELEcr FROM
name, string => "Statements using x":
link => {Sl[x.i); S2[@x]};
ENDCASE:
You should declare a set of REFs to bound variant types like
Name: TYPE = REF name TR;
String: TYPE
REF string TR;
Link: TYPE
REF link TR;
and rewrite the discrimination to be
WITH e SELEcr FROM
x: Name => "Statements using x";
x: String => "Statements using x";
x: Link => {Sl[x.i): S2[x)};
ENDCASE:
The type of x is now a REF type. not a TR. so various other types need to be adjusted and the @ in S2
is no longer needed. If "Statements using x" is a large block, you will probably want to introduce a
procedure to avoid copying it.

=

=
=

Variant records cannot be overwritten. Similiar techniques can be used for sanitizing a program that
overwrites variant records. Assuming the declarations of T and TR from above. suppose you wanted to
write
x: T +- NEW[TR .. [name(" END"]);
xt .. [link[S. xD:
The specialization/copying technique is to simply update the thing that points at the record, writing "x
.. NEw[TR +- [link(S, x)]]". However, if you don't know all the places that point at the record. you must
introduce another level of indirection, writing
T: TYPE
REF REF TR:
x: T +- NEW{REF TR .. )lEWrrR .. [rope["END"ll1:

=

CEDAR

4.2

CEDAR LANGUAGE OVER VIEW

21

x1' .. NEWrrR .. [link[5. x]]];
Unsafe procedures cannot be passed as arguments to safe ones. The symptom of a violation of this
rule is generally a message complaining about an incorrect type when there is no obvious type mismatch.
All procedure types in an interface prefixed by CEDAR are implicitly prefixed with SAFE. The simplest
thing to do is to put SAFE in front of PROC in the argument procedure declaration. and put TRUSTED in
front of its body. As with all uses of TRUSTED. you should verify that the safety invariants are actually
maintained. and document the reason for the TRUSTED in a comment

CEDAR

~.2

CEDAR LANGUAGE OVER VIEW

22

For More Information . . .
Cedar Language Syntax
This is a one-page reference grammar describing the complete syntax of the Cedar Language. in a
compact variation on BNF developed by Butler Lampson. Keep it handy as you write programs. It
provides a relatively compact source of information on the exact form of constructs accepted by the
compiler. It will also alert you to much of the available variety in the language-but of course, not every
syntactically valid program makes semantic sense.
The parsing grammar used by the compiler is somewhat larger and more complex than the Reference
Grammar. Some of this is for technical reasons associated with LALR(l) parsing, and some of it to
enable the compiler to make certain semantic distinctions while parsing. The differences should be
invisible when dealing with correct programs. but may affect the error messages given for incorrect ones.

Annotated Cedar Examples
This document contains four complete, runnable Cedar programs chosen to illustrate the use of most
of the major features of the language, and to provide an introduction to the style of programming that
is preferred in Cedar. You should certainly invest time in studying them before attempting to write
Cedar programs. If you are one of those who learns best from examples, you may find them virtually
the only tutorial information you need to learn the language.
These examples have been chosen so that they are also useful prototypes of kinds of programs you
may want to write in Cedar. If you are like most Cedar programmers. you will probably find it easier to
start from such a prototype, and change it to do what you want. than to enter a whole program "from
scratch."

Stylizing Cedar Programs
Because Cedar programmers so frequently read each other's code, it is considered good citizenship
to adhere to certain stylistic conventions. Stylizing Cedar Programs discusses the generally agreed
conventions.
You can save yourself a lot of typing, and produce nicely formatted code at the same time. by using
Tioga's abbreviation expansion mechanism to generate all the high-level structure of your program (at
least. all the bits that aren't simply copied). The file Cedar.abbreviations lists the available macros and
their expansions: you can add your own favorites.

Cedar Program Style Sheet
This is an annotated prototype that you will probably want to keep close to hand. because it
compactly illustrates the most important principles from the previous document.

Cedar Language Reference Manual
Eventually. this is intended to be a precise definition of the complete syntax and semantics of the
Cedar Language. It is still incomplete.
The formal definition of the language is given in terms of a kemellanguage, into which all Cedar
constructs can be desugared to determine their precise semantics. The Reference Manual contains both
the definition of the kernel. and an explanation of the desugarings. It also contains several tables that
collect important information about the primitive types and type constructors of Cedar.

CEDAR 4.2

CEDAR LANGUAGE OVER VIEW

23

Cedar Language Reference Summary Sheets
This is intended to be the essence of the entire Cedar Language carefully condensed into two pages
for ready reference. It covers both syntax and semantics, with examples and notes. It is definitely not for
those with weak eyes, and should probably not even be read until you have studied the Reference
Manual proper. But it should be very helpful in checking details that you may have forgotten. Keep it
handy.
Cedar Catalog
Since so much Cedar programming is done '''at the component level," you need to know what
packages and tools are available and what they do. In general, full documentation (or at least the best
available approximation thereto) for each component is stored on [Indigo]Oocumentation>, or is
referenced in the component's OF file, stored on [lndigo]Top>.
The problem is finding out which components you should be interested in. That's where the Cedar
Catalog comes in handy. It contains a somewhat structured list of all the components in Cedar considered
"interesting" by their maintainers. A component may be interesting
because of what it provides (your program may become a client).
because of what it does (you personally may become a user), or
because of how it does it (you may study it or copy some part of it in your program).
For each entry, the Catalog indicates why it is considered interesting. and how to acquire
documentation and the component itself. It also identifies the maintainer, who is the ultimate source of
advice and help.
Mesa 5.0 Manual
The Mesa Language ManuaL Version 5.0, PARC Technical Report CSL-79-3, is the most recent
self-contained manual on the Mesa Language. It falls somewhere between a tutorial and a reference
manual. and many users have complained that it isn't entirely satisfactory for either purpose. But if you
need more information about the Mesa-like parts of Cedar, it may be your best source.
Chapter 4 gives the details of Mesa's basic control constructs.
Chapter 5 tells all about procedures.
Chapter 7 goes into more detail than you probably want about the fine points of modules. programs,
and configurations. You may be better off extrapolating from the Annotated Cedar Examples.
Chapter 8 gives some of the gory details of exceptions and exception handling. It is easy to get in
trouble unless you use them in straightforward ways.
Chapter 10 provides a pretty reasonable discussion of how to make effective use of processes.
monitors. condition variables, etc.
Who to see

If you haven't managed to find information that you want after you have looked in what you
consider to be the obvious places (or if you don't understand what you have found), don't hesitate to
ask. Almost anyone in CSL is a fount of wisdom. willing to be asked almost any question on almost any
subject. (Of course, the answers aren't equally reliable, but you can't have everything.) If the first person
you ask doesn't know the answer, chances are good that you'll get a pointer to either a person or
document that will have the answer. More specifically here are some good people to ask:
John Maxwell
assistant of first resort for general problems with Cedar
Russ Atkinson
Bug Bane

CEDAR-4_2

CEDAR LANGUAGE OVERVIEW

Roy Levin
Scott McGregor
Bill Paxton
Paul Rovner
Ed Satterthwaite
Warren Teitelman

runtime system
Viewers and Tioga
Tioga
runtime-type system
compiler
user interaction. UserExecutive. 10

CEDAR 42

24

Cedar Safe Language Syntax
3.3 1module :: = DIRECfORY (nd?(: TYPE nc) ?(USING [nu • ••• ]) ).... :

36 type:: = type Name I builtInType I typeCons
37 typeName :: = n I type Name . n I typeName{e] ··In 19,15,36,40.1
38 builtin Type :: = INT I REAL I TYPE I ATOM I
CONDITION I MONITORLOCK
See Table4~.• ~E only in a b;ran i~tel:raCes~o 1
41
39 typeCons .. - subrange I pamt~dTC . I transferTC I
arrayTC44I seqTC4S I reITC46 I hstTC 47 I
recordTCSo I unionTCS21 enumTC54I defaultTC55
40 varTC :: = ( I READONl Y I VAR) t I ANY
In II. 46, 47. ANY only in repC. VAR only in interface decL
4O.1paintedTC :: = typeName 37 PAINTED t
41 transferTC :: = ?(SAFE I UNSAFE) xfer ?drType
41.1xfer :: = PROC I PORT I PROCESS I SIG:-.IAL I ERROR I PROGRAM
42 drType :: = ?tieldsl RETURNS fiel~ I fieldsl ··In 1.41.
43 fields :: = [ d ll .... ] I[t, .•• )1 ANY '-In 41.50.52. ANYOnly in drType.
44 arrayTC :: = ARRAY tl OF t2
45 seqTC :: = SEQUENCE n : tl OF t2 -- Only as last type in 50 or 52.
46 refTC :: = REF ?varTC4O
47liStTC :: = LIST OF varTC40
3.6 14 Statement :: = el ~e21 e I block6 1escape ,loop, NULL
4.6 so recordTC :: = ?MONITORED RECORD fields43
16 escape :: = GOTO n , EXIT , CONTINUE' (RETURNIRESL'ME) ?e
52 unionTC :: = SELECT n : (t I *) FROM (n = > fields43 ).... ?
17 loop :: = ?iterator ?(WHILE e , UNTIL e)
ENDCASE -- Only as last type infields 0/50 or 52.
00 ?bodylO ?(REPEAT FINISHED = >s) ENDLOOP
4.7 54 enumTC :: = {n••••} I MACHINE DEPENDENT {(?n (ell n).... }
18 iterator :: = THROUGH e ,
4.11 55 defaultTC :: = t ~ I t ~ e
.
FOR n : t ( ?DECREASING IN e , ~ el • e2)
Only as t in a decl in body9 orfie/~3 (n: t .. e).in a TYPE binding13 0r in NEW.
( interface I implementation)
4
2 interface :: = nm f.. : CEDAR DEFINITIONS ?locks
4.2
?(IMPORTS ( (niv: I) nit)....) - { ?open7 (d I b): f.. } •
3implementation :: = nm: CEDAR
( PROGRAM ?drType42 I \10NITOR ?drType42 ?locks)
~(
( ( . I ) ) ) ?(
) bl k
. IM~RTS niv . nit....: EXPORTS neo'" - oc .
4.3
slocks .. = LOCKS e ?(USING nu' t)
6
block
::
=
?(CHECKED
I
UNCHECKED
I
TRUSTED)
3.4
{ ?open ?enable ?body ?( EXITS (n. f.. = >S): ... ) } --In 3. 11. 14.
7open :: = OPEN (n - - e I e). !..: --In 1.5.
4.4
8enable :: = ENABLE { enChoice: ... }:
9 enChoice :: =( e. !.. I ANY) = >S --In 7. 17.1.
10 body:: = (d I b): !.. ; s; ••• 1s: !.. --In 5. 17.
3.5 lldecianztion ::= n. r•• : ?(PlfBLIC I PRIVATE) varTC40 --In 2. 10. 41.
13 b",ding:: = n. !.. : ?(PUBLIC I PRIVATE) t - (
--In 2.10.
e I t2 --t=TYPE··1 CODE I ?INLINE ?(ENTRYIINTERNAL) block6i.5

e is a subnznge. n is readonly,

3.7

n Iliteral57 I (ell application26 I
(e I typeName37) • (9) n I
prefixOp e I el infixOp e21 el AND (2) e2' e1 OR (1) e21
e .,. (9) I ERROR I [ argBinding27 ] I
builtIn [e. ". ?applEn27.1] I
funnyAppl e?( [?argBinding27 ?applEn27.1]) I
s I subrange25I ifl8 1select29 I safeSelect32

19 expression :: =

Precedence is in bold in rules 19-21, All openztorsassociate to the left except
... which associates to the nght. Application has highest precedence. Subnznge
only after IN or THROUGH. s only in ;J-8 and select choiceslO 33.
20 prefixOp :: = @ (8) 1 (7) 1(- I !'lOT) (3)
21 inflXOp :: = * , / MOD (6) + (5) relOp (4) ~ (0)
22reIOp::= ?NOT(?-(= 1)/<= 1>=' # 'IN)-Inll.10.

I

3.8

I

I

I

I

23 builtIn :: = -- These are enumerated in Table 45.
24funnyAppi ::= FORK' JOIN 1WAIT' !'lOTIFY, BROADCAST'
SIGNAL I ERROR' RETURN WITH ERROR
25 subrange :: = ?typeName37 ( [ I () e1 .. e2 ( ] Il) --In 19,39.
26 application :: = e [ ?argBinding ?applEn ]
27 argBinding :: = (n - ?e ). f.. I (?e), f.. --In 19. 26.
27.lapplEn :: = ! enChoice9: ..... In 19. 26.
28 if:: = IF el THEN e2 ?(ELSE e3)
29 select :: = SELECf e FROM choice: ••• endChoice
The ";" is ': " in an expression. here and in 32
30 choice :: = (?rel0p22 el ). f•• = e2
31 endChoice :: = ENDCASE ?( = > e3) -·In 29.12.34.

>

32 safeSelect :: = WITH e SELECf FROM safeChoice; ... endChoice31
33 safeChoice :: = n : t = >e2

3.2

.

56 Dame :: = letter (letter I digit)...
s7literal :: = num ?( U I B ) 1digit (digit 'AIBI~IDIEIE) ... H I
?num . num ?exponent I num exponent'
• extendedChar 1.. extendedChar ..... 1$ n
58 exponent :: = E ?( + I ) num
59 Dum :: = digit!..
6OextendedChar:: = space I \ extension I anyCharNot'''Or\
61 extension :: = digitI digit2 digit31 N IR 1I III I.E I J..I· I .. I \
.

!atiorr. item Iitem=choose one; ?item=zero or one item; terminals: SMALL CAPS. underlined or punctuation other th3Il bold O?l (parens are tenninals only in rules

items '. = zero or more items. separated by s; Item s !..=one or more Items. separated by 5: wlthS= ":". a tratling ..... is optional: s is one of: empty"," ";" •
;reviared non-ce,minoJs: b=binding.J: l1=deciaration": e=expresslOn-'; n=::ame~: s=statement··; t=type".
'lI1IenlS: n'" means n IS deEr.ed!D nue 56: n, = n (the suos<;np"1S only for:he desu!!ar:ng).

19. 25. 54).
16 Feb 8:
CLR.'AS"':eGram.pres.

Cedar Full Language Syntax
3.8 28 iC :: = IF e1 THE:-l e2 ?(ELSE e3)
3.3 1 module :: = DIRECTORY (nd?( : TYPE tnt )
29 select :: = SELECT e FROM choice; ... endChoice
?(USING [ nUt ... ] », ... ;
( interface I implementation)
2interface :: = nm. !.. : ?CEDAR DEFINITIONS ?locks
?(IMPORTS ( (niy: I ) nit ), ... )
?(SHARES nS' .•• ) - ?access12 { ?open7 (d I b): !•• } .
3 implementation :: = nm : ?CEDAR ?safety
( PROGRAM ?drType42 I MONITOR ?drType42 ?locks)
?(IMPORTS ( (njy : I ) nit)• •••) ?(EXPORTS net ...)
?(SHARES nS' ... ) - ?accessl2 block.
4saCety :: = SAFE I UNSAFE ~'In 3, 41.
S locks :: = LOCKS e ?(USING nu: t)

3.4

:: = ?(CHECKED I UNCHECKED I TRUSTED)
{ ?open ?enable ?body ?( EXITS (n, !.. = >S):
-·In 3,13,14.
7open :: = OPEN ( n -- e Ie), !.. ;
6 block

.00

)

}

In 2, 5, 17. The -- may be written as:.

3.5

8enable ::= ENABLE (enChoice I {enChoice; ...}): --ln5.I7.
9enChoice :: =( e, !.. I ANY) = > S ·-In 7, 27.1.
10 body:: = (d 1b); !.. : s; ... 1s:!.. -·In 5. 17.
11 declaration :: = n, !.. : ?access varTC40
In 2,10,43.

VAR. R.EADONLY

onlyfor interface var.

12 access :: = PUBLIC I PRIVATE --In 2. J, ll. 1J, 50. 51. 53.
13 binding :: = n, !.. : ?access t - (
e I t2 - i!t=TYPE--1 CODE I
?TRUSTED MACHINE CODE { (e, ... ): ••• } I
?INLlNE ?(ENTRY I INTERNAL) block6 )

In 2. 10. The - may be written as =. ENTRY or (NTERNAL may be written
before t Block or MACHINE CODE only for proc types.

3.6

14 Statement :: = el ~e21
--In6, 10,17,19.

e I block61 escape I loop I NULL

16 escape :: = GOTO n 1GO TO n I EXIT I CONTINUE I LOOP I
RETRY 1REJECT I (RETURN 1RESUME)?e I e ~ STATE
17 loop :: = ?iterator ?(WHILE e I UNTIL e)
00 ?open7 ?enableB ?bodylO
?(REPEAT(n,!.. =>s): ...) ENDLOOP
18 iterator :: = THROUGH e I
FOR (n : tin) ( ?DECREASING IN e I ~ el • e2)
e is a subrange. In FOR n: t ....

If

is reodonly.

The ";" is "... in an expression, here and in 31 and 34.

30 choice :: = (?reIOp22 e1 ), !•• = >e2
31 endChoice :: = E:'-iDCASE?( = >e3) ··In 29.31.34..
32 saCeSelect :: = WITH e SELECT FROM safeChoice: ... endChoice31
33 saCeChoice :: = n : t = >e2
34 withSelect :: = WITH (nl - - el I el) SELECT ?ell FROM
withChoice; ••• endChoice31 •• The -- may be written as :.
35 withChoice :: = n2 = > e21 n2. n2. !.. = > e2

= typeName I builtinType I typeCons
37 typeName :: = nl I type Name . n21 typeName[e] I
n2 typeName --In 19,25,36.40.1,49.
38
builtInType
::=
INT I REAL I TYPE I ATOM I CONDmON I
4.2
MONITORLOCK I LONG CARDINAL I ?LONG UNSPECIFIED I
MDSZone I ?UNCOUNTED ZONE
See Table 42. TYPE only in a b or an interface:S d
39 typeCons :: = subrange2S I paintedTC40·11 transferTC41 I
arrayTC44 I seqTC4S I descriptorTC4S.11 retTC46 I listTC47 I
pointerTC48 I reiativeTC49I recordTCSO I unionTCS 2 1
enumTC54I defaultTCSS
4.3 40varTC ::= (I REAOONLY I VAR) t I A:-.IY

4

36 type ::

In I 1.4548.

ANY

only in rejTe.

VAR

only in interface decL

4O.1paintedTC :: = typeName 37 PAINTED t
4.4 41 transCerTC :: = ?safety4 xfer ?drType
41.lXCer :: = PROCEDURE I PROC I PORT I PROGRAM I
PROCESS I SIGNAL I ERROR
42 drType :: = ?fields1 RETURNS fiel~ I fields l --In 3,41.
43 fields :: = [dll , ... ] I [t, ... ] I ANY ··In 42. 50. 52. ANY only in 42.
44 arrayTC :: = ?PACKED ARRAY ?tl OF t2
45 seqTC :: = ?PACKED SEQUENCE tag53 OF t
Legal only as iJJst type in the fields ofa recorrITC or unionTe.

4S.1descriptorTC :: = ?LONG DESCRIPTOR FOR varTC40
varTC must be an array type.

4.5 46 retTC :: = REF ?varTC40

47liStTC :: = LIST OF varTC40
48 pointerTC :: = ?LONG ?ORDERED ?BASE POINTER
?subrange2S ?(TO varTC40) I POll'I'TER TO FRAME [ n J
Subrange only in a relaliveTC; no typeNamel7 on it

49reiativeTC :: = typeNameJ7 RELATIVE t
3.7 19 expresSion :: n I literalS7 I (ell application26 I
4.6
50
recordTC :: = ?accessU ( ?:vfONITORED RECORD fields4 3 1
37
(e I typeName ). (9) n I
MACHINE DEPENDENT RECORD (mdFields I fields4 3) )
prefixOp e I ~ infixOp e21 el AND(2) e21 el OR(I) e21
51 mdFields :: = [( (n pOS), ... : ?accessl2 t ), ...J.. In 50.52.
e l' (9) I STOP I ERROR I [ argBinding27 ] I
Sl.lPOS :: = (_ el ?(: e2 .• e3) 1 .- In 51.53.
builtIn [ e, ... ?applEn27.l] I
52
unionTC :: = SELECT tag FROM
funnyAppl e ?( [?argBinding27 ?appIEn27.1]) I
( n, ... = > ( fields43 I mdFieldsS1 1NULL) ), ... ?, ENDCASE
s I subrange2S I if28 I select29 I safeSelect32 I withSelect34
Legal only as lost type in the fields 0/a recordTC or unionTe.
Precedence is in bold in rules 19-21. Ail operators associate 10 the left except
53 tag :: = (n ?posSl.l : ?accessU I (COMPl.:'TEDjOVERLAID) )
.., which associates to the right Application has highest precedence. Subrange
(t I *) ··In 44. 52. • on£v in unionTe.
only qfter IN OTTHROUGH. S only in ij28 and select choictsJO 3335.
20 prefixOp :: = @ (8) I (7) I (- I NOT) (3)
4.7 54 enumTC :: = {n, ... } I MACHINE DEPE:-lDENT {(?n (e} In), ...}
21 infixOp :: = "'III MOD (6) I + I (5) I relOp (4) I~ (0)
4.11 5sdeCaultTC ::= t ~ I t ~ e I t ~ e 1_ TRASH I t ~ TRASH
defaultTC le~al only as lhe type in a decl in a body9 orfiel~3 (n: t .. e). in a
22 relOp ::= ?NOT (?- (= I <1>)1 <= I >= I # lIN) --In 21, 30.
TYPE bindingJ.3. or in NEW. Note the terminal I. TRASH may be written NULl..
23 builtin :: = -. These are enumerated in Table 45.
24 CunnyAppl :: = FORK I JOIN 1WAIT I NOTIFY I BROADCAST I 3.2 56 Dame:: = letter (letter I digit)...
SIGNAL I ERROR I RETURN WITH ERROR I NEW I START 1
57liter-.t1 :: = num ?( ( Dig I BJh) ?num) -- (NT literaL I
RESTART I TRANSFER WITH I RETURN WITH
digit (digit IAlllICIDIEIE) ... ( Hlll)?num - Hex (NT literal I
2S subrange :: = ?typeName37
?num . num ?exponent I num exponent -- REAL literaL I
( [ el .. e2] I [ e1 .• e2) I ( el .. e2 ] I ( el .. e2 ) --In 19. 39. 48.
• extendedChar I digit !•• C_I " extendedChar ... " ?L_I $ n
26 application :: = e [ ?argBinding ?applEn ]
58 exponent :: = (EJ~?( + I) num
17 argBinding :: = (n - (e II TRASH !.. I (e II TRASH). !..
59 num :: = digit !..
In 19, 26. The - may be written as:. SULL may be wnttenjOrTRASH.
60 extendedChar :: = space 1\ extension 1anyCharNot"'Or\
17.1appIEn :: = ! enChoice9; ... -- In 19, 26.
61 extension :: digitI digit2 digit31
nlNJrIR ItlI I hill I flflllLl' 1"1 \
.
. , . .
'ation: item I item =choose one; ?item =zero or one item; tennina1s: SMALL CAPS, underlined or punctuation other than bold 0'1 (parens are tenninals only in rules 19. 25, SI.L 54,1 only in 55).

=

»,

=

item s ... = zero or more items. separated by 5; items !.. =one or more items. separated by-s; with 5= ":". a trailing ";" is optional; s is one of: empty "," ";" .
"eyiated non·temunllis: b= binding"; d= declaration·': e=expression.J: n=name"': s=statement·': t=type".
nments: =obsoiete; =eiticlency nack; unsafe: = madune dependent: n' means n 1~ c!effned In :we 56. n: = n (:he s1.:bscn;lt IS only for the desuganng).

=

16 Feb
CLR.1\;{FullGram.pf!

SYntax

Notes

Examples

Meaning

DIRECTORY
odule ::= DIRECT6RY(IlcI(: TYPE (ntl) I) "[(lid: «TYPE ntl TYPE JId) ITYPE n
or It is exported.
Buffer: TYPE:
?locks '!(IMPORTS «n,y : I) nil )•.•. )
[n",: TYPE n",IIN
,!(SHARES ns•.•• )
•• Access to PRIVATE names lR nr IS allowed.
- ?access" { ?open' (d I b): !•• } .
LET REC nm-open [ ?(Iock' -l~ks. )(d I b)•... liN n",
.. [mplementaUons can have argume
1plementation ::= nm. ?CEDAR
n,yl nil ):MKINSTANCETYPE[nll]).... ]=>
Bufferlmpl: MONITOR If: CIFS.OpenFile]
.• LOCKS only lR MONITOR. to Specll
LOCKS Buffer,GetLock[h]'t
?safety ( PROGRAM ?drType" I
[(~: n~) ..... nm: TYPE n",. COSTROL: PROGRAM]] IN
l;SING
h:
Buffer.Handle
.. a non 'standard lock.
'vIONITOR ?drType" (I locks»
(I (LET LOCIC::MONITORLOCK IN LET r-{" IN LOCKliN I»
..
:'IIote the absence of selIllcolons.
IMPORTS
Files:
CIFS.
[0.
Rope
'!(IMPORTS «n,y : I) nil), .•.)
LET b'-NEWPROGINSTANCE[!!l!!siI.UNCONS IN
•• EXPORTS in PROGRAM or MONm
Buffer
'!(EXPORTS n..... )
[(ne-BINOOFROM[n., b'])..... a",-b·. CONTROL-b·.n",] - EXPORTS
.. Note the final dot.
{ •• module body .. } .
,!(SHARES ns.... )
where the body of the block is desugared thus:
[( I (Il'-Iocks.»(d I b). .... n".: PROGRAM drT1\M-{s:
- ?access" block.
... }j
tely :: = SAFE I UNSAFE "lit J. 41.
cks :: = LOCKS e '!( USING nu: t)
" ?( [nu : tl ) IN e
.0

,,[«

ock :: ...
?(CHECKEDIUNCHECKEDITRUSTED)
{ ?open ?enable ?body
'!(EXITS (n. !.. = >S): ...) }

91!!!! LET a". _ : EXCEPTIO~-NEWLA~LO, ...
INll!!!!I!eaable)BUT{(n .... =>s), ...l

-lit J. 13. IJ.

- BrilIt"ISIt~IIIS.

leJI::=OPEN(n--ele).!.. : .

(LET a->'o,...IN e.OEREF I -TheiN be.frw I.. lSueptllDlor.
LET BINOp{V(e.OEREF.I-p.
OPENPROcS(vle.DEREF).P. " IN e.DEREF]]) IN! .. IN
B~~Jok,n9"ifj
}I
{
,

lit 1. S. 17. TM -- rMJI 11« wnJlSI Q$:.

lable:: ,. ENABLE(enChoice!
fenChoice: ...

...

n:

InS. 17.

( e I ANY). ... = > { S: REJECT: EXITS
Itetry' = >GOTO Reuy"": Cont' = >GOTO Cont"" }
LET NEWFRAME[ REC [(d I b), ...]].UNCONS IN { s: ...}

tChoice :::II( e, !.. I ANY) => S
lit 7. 17.1.

od, ::= (d I b):!.. : s: ... Is:! ..
IItS./7.

:r:1tuul1D1l :: = n. !.. : ?access" varTC"
( a:
fit 1. 10. 43. v AR. READONL Yonly [0, IllUfjiJce wu.
~ess::=

PUBUCI PRlVATE

lit 1. J. II. 13. SI1 11. Sl.
,'Idutg :::a n.!.. : ?accessl.l t - (

(- Th~daulfJJ'lll,forlllS/II 1M end.

NEWEXCEPTIONCODEO --r-SIGNAL 0' ERROR I
A. (d': t.ooMAINI IN LET r'~NEWFRAME[t.RANGE].UNCONS
IN (LET r' IN {t.OOMAIN-d': block: RETURN}
BUT {Return'" = >r H I
MACHINECODE(BYTESTOINSTRUCTION(e, -D,-]
) IN a. ... - ~ .. e IS /lWJJutu1d only 0lIl:&

?TRUSTED MACHINE CODE {(e....): N'}

lit 1. 10. TM - rMJI 11« _lSI Q$ '"
Block 0' MACHINE CODE only[0, pme 1J1P4
ENTRY and INTERNAL ..... abo 11« I1«fore L

_::=sS
lit 6. 10. 17, 19.

; :: =e,. '"e,.1 e I block'i escape I loop I NULL
lcape::- GOTOnlGOTOnl
EXIT I CON11NUE LOOP I RETRY I
,RETURN I RESUME) ?e I

?(REPEAT (a, !.. = >S): ...) ENDLOOP
erator :: "" THROUGH e I
FOR(n: tl n)
( ( I DECREASING) IN e I

~

tz - S_ Q$ U1:ICtpf [or CIHI/1it:IIII, S)IIIIIU. I

)

~le"STATE

•

LET x' : t
el

el
t, - ifl-TYPE I
CODE I
?lNUNE '!(ENTRY I INTERNAL) block" I

-up :::11 (iterator I )
(WHILE e I UNTIL e I )
DO ?open' ?enable' "?body..

yarTC ), ...

{SIMPLELOOP {sS: GOTOCont": EXITS Retry"=>NliLL}:
EXITS Cont" = >NULL }
(e,"e,].TOVOIO Ie - _ }IIeldvoID-I"aJ/ }IIeldVOIDEXORVAL[excertion(code- a". args-NILJlI
GOTO (Exit''' Cont"l Loo(:l'''1 Retry") I
{ '!(r'u"e:) GOTO lReturn'u I Resume '-') } I
THISEXCEPTIONO IOUMPSTATE[e]
{litmmlr: I done'-FALSE: Sext': PROC-{}: )
{~ IN(NOTeleIFALSE):
{ !!I!!!! SIMPLELOOP {
IF Test'D OR done' THEN GOTO FINISHED:
{ enable body EXITS I..oop' = >Nt;U }: :'IIext'() }
EXITS Exit'-NULL: (a, !..• s): ... : FlNISHED-NlJU}}}
FOR x': e IN e I
~a:t:rr-Range': TYPE-e: done': BOOL .. Range'.ISEMPTY:
:'IIext': PROC-{ IF a ( ~Range'.LAST I GOTO HandleOvfl:
stream: [O.Stream- [O.CreateFileStream("X"];
x: INp·1:
{OPEN b--GetBuffer[stream]:
ENABLE {
Files.Error-~error. filel = >{
stream.Pu 10.rope{errorn:
ERROR Bu er.Error["HeTp"]}:
ANY=>{ x"12: GOTO AfterQwt} }:
y: INT .. 9: _ }:
x..stream.GelInt: .••
o,

EXITS

AfteIQuit= >{ ...}:
HandleOvfl=>{...}}:
HistValue: TYPE{ANY];
Histogram: TYPE~REF HistValue:
baseHist: READONLY Histogram:
AddHists: PROC(x, y: Histogram]
RETURNS [Histogram];
l..abelValue: PRlVATETYPE-RECORD(
firsLlast:INT,s:ROPE.x:REAL,f,g:INT,r:REF ANY];
Label: TYPE-REF LabeIValue:
Next: PROC[1: Labell RETURNS{Labe1]INUNE { RETURN[NARROW{l.rll};
H: TYPE- Histogram": Size: INT~ 10:
HistValue: PUBLIC TYPE-HV.Il:
baseHist: PUBLIC H "NEW(HistValue-ALL[lll);
x, y: HistValue ..[ 20. 18. 16. 14, U. 10.8.6,4.2.0];
FatalError: ERROR[reason: ROPE,-CODE:
Setup: PROC (bh: ftandle', a: INT - ENTRY {_l:
iJ.k: INT"O: p.q: BOOL: Ib: Labe ; main: Handle;
X" AddHists{baseHisL baseHist]-t:
Setup[bh-main. a-31:
{ENABLE Fata1Error= >RETURN(O]; [J"f{3J; ... };
[F i>3 THEN RETURN[251 ELSE GOTO NotPresent:

.. l:nnamed OPEN OK for exported

.. interface or one with a USING cia'
.. A single choice needn't be in n.
.. l:se a bindinll if a name's value is i
.. Better to miualize declared names.
.. A statement may be a nested block
.. Multiple enable choices mUlit be III
.. ERRORs can have parameters.
.. Choices are separated by semicolol
.. ANY must be last. ENABLE ends "'I
.. Other bindings. decls and statemef
.. Other statements in the outer bloci
.. Multiple EXIT choices are not in
.. AfterQuil. HandleOvjl declared hel
.. regal only in aGOTO in the block.

n

.. Interface:

An exported type.
A type binding.
An exported variable,
An exported proc.

-.0

PRlVATEonly for secl
stuff in an Interface.
An inline proc bindin!

--Implementation: Binds a TYPE and
PUBLIC forexpons.
An ~rted variable
..
with lIIitialization.
.0
Binds an error.
.0
Binds an entry proc.

.0
.0

-- A statement can be an assignment,
.. or an application without results,
.. or a block,
-- or an IF or an escape statement.

FOR tINT DECREASING IN [0..:)) UN11L fIt»3 DO -- or a loop. Try to declare t in the Fe
u: [NT"O: .•• : u .. t+4: N.
.. as shown. Avoid OPEN or ENABLE
REPEAT Out= >{... }; FlNISHED=>{... } ENDLOOP:" after 00 (use a block). FINISHED
-- must be last.
THROUGH (L.5) 00 i '"l*i ENDLOOP:
FOR i: INT"I, i+2 WHILE i<8 00) '"j+ i...:
FOR I: l..abel"lb.I.Next WHILE I #NIL DO ••• :

.. Raises j to the 6th power.
.. Accumulates odd numbers in [1..8).
.. Sequences through a list of Labels.

.. e,. e,)
e 1S .. .suimuIP. III FOR n: I .... It IS fWIIIiDnly ~XCtPl [0, 1M /ISIIgIIIMIIIIIIIM '1~IUlOf'. daullUlllr-

I

Iv: Labe1ValuelJ -{ i, 3. "Hello". 31.4EL (i+ 1),
-- A constructor with some sample
'P'!SSIIJII:: "" n I Iiteral57 (ell application" I
(e I typeNameP ) • (9) n
gfx]+lb.f+j.PRED ]:
.. expressions.
prefixOp e I e\ infixOp e, I e . prellxQp I e, . intlxQp{e,]I
pE PROCESS RETURNS [INTI"FORK f{i, JI;
-- FunnyAppls take one unbracketted
ERROR NoSpace: WAIT butrerFilIed:
-- arg: many return no resulL so .
e, reIOp(4) e, I
{" (x': Ve,.. y' :Ve,] IN r!l!m 1ret. e,l I
..
must be statements,
RT:
RTBasiC.Type-CODE{LabeIValueoll;
e, AND(2)e, Ie,. OR(l)e,. I
IF e,. THEN e, ELSEFALSEIIFe,. THEN TRUE ELSEe, I
h[3,
NOT(i>l).
i*i.
i
..
3.
i
NOT
>J.
pORq,
fb.rt];
-An applicauon With sample expressl
e t (9) I STOP I ERROR I e . DEREFERENCE I STOP[J I ERROR NAMELESSERROR I
Iv19 "{first-O.last-lO. x-3.14. g~2, f-5]:
.. Short for Iv.. LabelValue"[...I.
I
builtIri [ e, '!( , e" !..) ?appIEn"1 I e , . . builtin ?(
-- ASSIgnment to VAR binding
[first-~ last-J]"lv":
funnyAppl e?{ ~.arg.Binding" ?applEn''l) Ie. fuaayAppl '!( [argBfading ?appIEn]) I
-- I extractor).
[ qBindingJ'J
--Binding must coerce to a record. array. or local suing-- I
.1 subrange>' ru t select'" safeSelect" I withSelect"
p~ IS III bold III fllin 19'11. AU opmuon tJSStJCUUe 10 1M left cu:ept ". wlu&h )] # I
?Nor (?NOT ,,'.(EQUAL] LESS I GREATER)(y'1I x'- =y'l
«= I >=) liN)
x =y' OR x' « I »y' Ix'>=y .FlRST AND {x'<=y'.LAST
·/1t 19. ]0.
BUT {BoundsFault= >FALSE} })
liltln::
These are enumerated in Table 45.
aaYArpi :: '" FORK I JOIN I WAIT I NOTIFY BROADCAST I SIGNAL I ERROR I RETL"RN WITH ERROR I
'lEW START I RESTART ttRANSFER WITH RETURN WITH
brange :: .. (typeNa,meJ7 J)
LET t'-(t1\MName liNT). first'-( eel e,.SUCC )IN
b: BOOL"i IN [1..101: FOR x: INT IN (0..11) 00 ... ; .0 Subrange only III types or with IN.
b"( c IN Coior,,(red..green] OR x IN 1NT[0..10) ): .. The INT is redundant.
( [ I () e, - e,. ( ]11)
t".MKSUBRANGE[first. (e,.1 e,.PRED )1 BUT
·14/9....IlI. 4IL
{BoundsFauJ.t '" )t',UKEMPTYSUBRANGE!e,l}
·tIZlion: item I item = choose one: ?item= zero or one item: terminals: SMALL CAPS. underlined or punctuation other than bold 011 (parens are terminals only in rules 19, 25.51.1.54.1 only in 55).
item 5 _=zero or more items. separated by 5: Item s!.. ::;one or more Items. separated by S; With s=";". a trailing ":" is optional: 5 is one of: empty"," ":" IN ELSE OR.
breviared nolt·terminois: b=bindir.g..!: d=declaration-: e=e:<;>resslon": o=name~: s=statement": t=type-".
4Feb8
mmenls: =obsolete: =erlk:enq rt:lC!C:: = unsare. = :nocnme .le:Jenae:1t: ::~ T.ea.'1S :1 .• Jennet! _'1 ,,~!e 56. n,= n t ~e subscr:;>t 15 onl>' [or ~e Jesuganng).
CLR.\.lSumm.pres

(e,....])

=-

I

pplicatioa ::
rgBindiag ::

Syntax
=
e [?afgBinding ?applEnI
=(nIe -II (erRASH
II rRASH »). 1..1
)....

Meaning

lh ~ Files.Openlname-lb.s. mode- Files.read
! A~'CessDenied=>{ ...})· FataiError=>{ ... });
(GetProcsh].ReadProc J(k ;
tile.ReadI6ulfer-b. count-kl;
tli-3.j-. k-TRASH]: fli-3. k-TRASHI;
fl3 •• rRASHI:

IF e, rHEN e, ELSE (e, I NULL)
LET selector' -e IN
choice ELSE ... endChoic:e

i "(IF j<3 THEN 6 ElSE 8):
IF k )IIOT 1)11 Range fHEN RETURN(7I;

In 19. 16, TRASH may he wrolen as NULL. - as:,
.pplEa :: = ! enChoice': ... - In 19, 26.
BUT { enChoice: .•• }

:: = IF e, rHE)II e, (ELSE e, I )
~lect :: = SELECT e FROM
~hOlce; ... endChOice

The ", "IS

"... In

an expreSSIon: also

In ,] and.J4,

lIoiee :: .. « I relOp" ) e, ), !.. = >e,
ndChoi(.'e :: .. ENOCASE ( I .. > e,)
11119. J2. J4.

Examples

LET m' -e. a -largBiadlngilN ( lm. APPLY .a'l ?applEa 1
(a - (e I OMITTED I TRASH)). L I
(e I OMITTED I TRASH), ...

•• ECSEVa separator jar 'epelltlons o/Ihe clunc••

IF ( (selector' (= I relOp ) e,) OR ... ) THEN e,
ElSE (NULL Ie,)

Notes

-- Keywords are best for multiple,
.. Semicolons separate choices.
.. The proc can be computed.
.. 5File.Reat4fi/e. b. kl (object nou
_. {.and k may be trash (see default
.. ikewise. If Lj. and k are in that
oo

SEL~f{J]~OM
<7 - >{ ... }.

An IF with resullS must have an I

_. SELECT expressions are also pOS!
.• 5l:INT-.A!); IF 1<.7 THEN {... t EI
··7.8= > or =71 =8= >{ ... } is the
ENDCASE=>\ ...} is the same hel
Redundant: chOices are exhausti
•• Assume r. REF ANY in this exam
•• r{ntis declared in this choice onl

IN [7 ..81=>{...};
SOT (=8= >f. ..};
ENOCASE=>ERROR:
LETv'-e IN
WITH r SELECT FROM
safeChoiee ELSE ... endChoice
rInt: REF INT= >RETURN[Gc:d(rlntt'17~;
IF ISTYPENOTNILlv'. tl THEN LET a: t"NARROWlv', tl IN e,
rReal: REF REAL = >RETURN(FlooriSin rRealt ;
ENOCASE = >RETURN[IF r= NIL THEN ElSE
Only the REF ANY , is known he
OPEN v --e, IN LET n'-($1Ii1 )IIIL). type -v'.
selector' :'(e,.TAG I ell) IN witbChoice ELSE ... ~
nr: REF Node"- ... ; WITH dn- -nr SELECT FROM .• See rule 52 for the variant record
- ~_
betUj'aulttd.%ctpt}i>raCOMPIJ'TED vaflClllL
bmary= >{nr-dn.b}:
dn is a Node.billlllY in this choice
unary = >{nr-dn.a};
dn is a Node.unary in this choice,
IF selector' = a, THEN OPEN
ENOCASE=>{nr"NIL};
dnisjust
a Node here.
,
(BINop{n', LOOPHOLEIv .type 1n,J] I I BINop{n', v'l) IN e,
oo
oo

afeSelect :: .. WITH e SELECT FROM
safeChoice: _. endChoice"
:IfeChoice::= n: t =>e,
ithSelect ::= WITH(n, -- et! ell
SELECT ( I eu) FROM
withChoice: _. endChoicell
T1w -- may be wnllm as:.

=

ithChoice :: n, = > e, I
n" n,.!.. => e,

=

¥I ..
oo

oo

oo

,

I

lpe ::
typeName I builtInType typeCons
'lJIIName ::- n.t typeName. n,
typeName leI I n, typeName

11119. 15. ]6, 40.1. 49.

_a

-Ill

,yptNaIM ""'" /)II an oJltlllll" typo. t fff:lJnrI'C or.1I1UrITC.

=

Legal only as !IJst Iype IIJ II fff:lJnI1'C or UIUOfITC.

lescriptorTC :: ..
?LoNG DESCRIPTOR FOR varTC"
varTC must be an lImIY typo.

=

fiC :: REF (varTC'" )
nTC :: .. LIST OF varTC"
JinterTC:: .. ?LONG ?ORDERED?BASE
POINTER ?subranjeU?(TO varTC") I
POINTER TO FRAME I n I

MKXFERTYPE~.

flavor-xferl

domain-fields.., range-fieklst

MKARRAvldomain-t" range-t,1
MKSEOUENCe(domain-ta&. range-tl

TyPelndex: TYPE-IO..256);
BlnaryNode: TYPE-Node".binary:

-. A subrange type.
_. A bound vanant type.

HV: TYPE-Interface.HistValue PAINTED
RECORiJ( ...1
Enumerate: PRoc(
I:RL,
p: PRoc(X: REF ANY) RETURNS [stop: SOOLJ]
RETURNSlstopped: SOOLI;
p2:PROCESS RETURNs{i:INTI"FORK stream.Get;
falled: ERROR [reason: ROPE -CODE;

oo

See 13 f9ruse.

Vec: TYPE = ARRAY [O.. maxVecLen) OF REF TEXT;
Chars: TYPE- RECORD (text: PACKED SEQUENCE -- A record wi~ Just a sequence in i
ch.text(ll or chI~ refers to an eiem
len: (O•.LAST(INTEGERII OF CHAB.I; ch: Chars:
v: Vec-ALL(NIL);
dV: DESCRlPTOR FOR ARRAY OF REF TEXTDESCRIPTOR{vl;
ROText: TYPE-REF READONL YTEXT:
-- NARROw(rl,/lr.u. ROTltxtJ? is a
RL: TYPE-UST OF REF READONL Y A.NY; r1:RL; •• READONLYTEXT (or elTOr).
UnsafeHandle: TYPE-LONG POINTER TO Vee":
oo

MKARRAYDESCR(arrayType-varTC)
MKREF[target-( urTC I ANY»)
MKLIST{range-,arTC]
MKPOINTER[target-'arTCI I
MKINSTANCETYPElnl

Sublllll~ only IIJ II reIim.,TC: 110 typIN01II",'1 all tL
~al:iYeTC ::- typeName" RELATIVE t
MKRELATlvelrange-t.
1_ /)II a poutUr or dacnptor type typoN_ a ba8II (JOUIler type

ICOrdTC :: =?access" (
'?MONITORED RECORD fields" I
MACHINE DEPENDENT RECORD
(mdFields J fields") )
dFields ::,. I( ~~ pos), ... : "[II SO. 52.
. access" t)....1
(tields"1 mdFieIds,ll NULL))' _
.,ENOCASE

•• A type from an interfa::e.
•• A bound sequence: only in SIZE.

vartrJIIL

lultlnType :: .. INT I REAL I TYPE I ATOM I MONITORLOCK I CONDmON I
?t.;NCOUNTED ZONE I MDSZone I LONG CARDINAL L?LONG UNSPECIFIED - S.. Tabl, 42.
f'Il'E only as IIIJ a b or an IIJltrfi>e,. Ii. I'NTEGER. CARDINA NAr. TEXT. STRING. BOOL. CHAR are pret/4/11111l.
1peCons :: .. sub range" I paintedTC'"I transferTC" , arrayTC"" seaTC" I descriptorTC'" ,
reITC'"llistTC" I pointerTC"lrelatiVeTCII I recordTC50 I unionTC') I enumTO'1 default1'O'
uTC :: .. (I READONLYI VA.R tlANY
(VAR I READONLY I VARHI ANY
In fl. 4548. ANY only IIJ rejtc. VA only", 1IJ1tI:{o&. dtcL
,aintedTC :: .. typeName PAINTED t
REPLACEPAINT{in: t, from: typeNamel
'lIIISferTC :: ".?safety· xfer ?drType
:Cer :: PROCEDURE I PROC~PORT I
PROCESS I SIGNAL I ERROR PROGRAM
rType:: - ?fields. RETURNS e1ds.1 fields.
No domtwa}i>r PROCESS. 111 J, 41.
elds ::= Idu .... I I It, ... I' ANY
ANY only IIJ drTypo. 11142. Jo, S1.
rrayTC :: .. ?PACKED ARRAY ?t, OF t,
!CITC ::=?PACKEDSEQUENCE tag" OF t

P: PRocl b: Buffer'.Handle,
i: INT"TEXT(20I.SIZE I;

typeName.SPECIALIZE(el I typeName . n,

baseType-typeName)

Cell: TYPE-RECORiJ(next: REF Cell. val: ATOM];
Status: TYPE-MACHINE DEPENDENT RECORD [
Don't omit the field positions.
c:hannel (0: 8_10): 10..nChannels),
-- nChanneis < 8.
device (0: 0..3): DeviceNumber,
DeYiceNu";&, held in S 4 bilS.
MKMDRECORDlmdFleids I fields!
stopCode (0: 11.. 15): Color, fill (0: 4_7): SOOL, .~ No gaps allowed, but any orderin'
MKMOFIELOS(LisT( ( usTf ([$D, (IOSI ), ... I ' t ), ". ) J
coriunand (1: 0..31): ChannelCommand I;
Bit numbers ~ 16 OK; fields can (
MKPOSlTION(tirstWord-e" firstBit-e,.lastBit-e,1
-- word boundaries only if word·a/;
MKUNtONlselector-tag, varianlS-usTf
Node: TYPE- MACHINE DEPENDENT RECORD ( •• rands is a union or variant part.
type (0: 0..15): Typelndex, rator(l: 0.. 13): Op"'. .. This is the common part.
(I labels-UST( $a. ...1, value-fields I), ·..1)
Both union and tag have pas.
rands (1: 14..79): SELECT n (1: 14.. 15): • FROM
Ltr'lQi only as!lJst IJIP" IIJ a rer:owtrC or UIIIOIITC.
Type of n is {nolllllY: UNlI'Y, binflr.
nonary=>O,
unary = >[a (1: 16..47): REF :-rode),
~:: (n (pos,l1I) : ?access",
I ( I $D, ((lOS I NIL) II $COMPUTED' I $OVERLAID) ,
-- Can use same name m several var
COMPUTED I OVERLAID) (t .)
( t I TYPEFROMLABELS ) )
At least one variant must till 1: 14
buwy= >fa (1:16..47)' b(1:48 ..79): REF :-rodel
11144. 52•• oJy //I uIIWIITC'Z.
ENOCASEI;
lumTC :: .. {n, ... } I
MKENUMERATION( LI~Sa. ...111
Op: TYPE-{plus, minus, times. divide };
MACHINE DEPENDENT {( (n I) {e} I n),!_} MKMOENUMERATtON(UST( [(Sa I NIL), ell ISa. 11), ... 11
COlor: TYPE- MACHINE DEPENDENT {
A Color value takes 4 bits: vee""
red(0), green. blue(4), (l5)}; c: Color;
-CaultTC ::..
CHANGEOEFAULT(type-t. (
- Except as noted, a constructor or application must mention each name and give it a va
Q: TYPE- RECORD(
•• Otherwise there's a compile-time,
t "I
proc-)IIIL, trashOK-FALSEII
l .. e I
proc-lNUNE AIN e. trashOf{-FAlSEII I: INT.
Oli-] trash i(not in argBindi
t .. e 1_ TRASH I
proc-INUNEA IN e. trashOK-TRUEIl
J: INT",
No defaulting or trash for j.
t .. TRASH
proc-t.Trash. trashOK- rRL'EI)
k: INT"3,
Q(). Q(k-#eave k=3.
!kfauJtTC legal only as 1M type IIJ a dtclllJ 1I!Jot# or j/,ItI' (II: I • e~ IIJ II TYPE burduI,-'. or IIJ NEW. NOltlM ,."",nall.
1: INT" 31 TRASH,
As Ie, out I-TRASH! trashes L
fRASH "..y be wnt/t!II as NULL.
m: INT"TRASH ];
Q(I. Q(m- trash m.
MKRECORo( fields I I

oo

oo

=

oo

oo

=

oo

oo

oo

oo

m

oo

oo
oo
oo

.... ::= letter (letter di 't

.. But not one of the reserved words in Table 31.
- tNT literal. decimal if radix 01Illtted or D. octal if B.I
-- INT literal in hex: must start with diglL ,
REAL as a scaled decimal fraction: note no trailing dol, I
•• With an e~ponent, the decimal jlOint may be omitted)
.. CHAR literal: the C form specifies the code in octal. I
I ('exteDdedChar), ,••1-- RoPlt.ROPE. TEXT. or STRING. I
- ATOM llteral.
- Opuonally Signed decimal exponenL

era! ::.. n~ D B ) ?Durn ) I
jjgit (digit A
._ ( !:!Ih) 'hiurn I
?num. num .exponent
lum exponent I
extendedChar I digit !•• C I
'. extendedChar ... "?L_I In
,ponent :; "7 c,mv?( + ) ) num
lID ::- diglt. ••
teDdedChar :: space I \ exterunon I anyCharNot'"Or\
tellSion ::= digit, digit, diglt.1
The character WIth code digit, digit, digit, B.I
(!!It11 dID I (lID I (l2IID I
-- CR, '\015 I TAB. '\0111 BACKSPACE. '\010 I
(!If) I (!I!J "1·' \
.. FORMFEED. '\0141 UNEFEED. '\OU I '1" I \
oo

m, xl. xS9y.longNameWithSeveralWords: INT:
n: INT-l+UD+2B3+2000B
+lH+OFFH:
rl: REAL -0.1 +.1 + LOEI

+ lEI:

.ll: ARRAY rO..310FCHAB.-(,x, '\:-r. '\', '\1411;
a: ROPE- "Hello. \N._ 'u'l,fGoodbye\F";
a2: A.TOM-$NameInAnAtomLlteral:

-- = 1+U+I024+1024
+l+25S
.• = 0.1+0.1+0.1
oo

•• +0.1

=

oo

,tIJ1ion: item I item = choose one; ?item= zero or one Item: terminals: SMALL CAPS. underlined or punctuation other than bold O?l (parens are terminals only in rules 19. 25. 5l.1, .54,1 only in 55),
Item s _ = zero or more ltelllS. separated by 5: Item s!_ one or more Items. separated by 5: WIth s= ":", a trailing ";" is optional: s is one of: empty ..... ;" IN ElSE OR.

=

breviQled non·lerminals: b= binding": d=declarauon·': e=expresslOn": a=name»: s=statement": t=type"'.
'runents: =00501ele: =ernclenc" hXll, = ~r~a:~: :: mac;;lr.e Ii [trans: Transaction.Handle).
juniper >[trans: Juniper.Transaction

=

+-

NIL],

ENDCASE):

Used to unify the two types of transaction. for Open only.
OpenFailed: SIGNAL [why: OpenFailure. fileName: ROPE) RETllRNS [retry FileName: ROPE):
OpenFailure: TYPE = { fileNotFound. illegalFileName. fileAlreadyExists. cantUpdateTiogaFile.
wrongTransactionType, unknownFileCapability. notlmplementedYet };
2

This signal is raised by the various file stream creation procedures.

=

{none. newOnly. oldOnly}:
CreateOptions: TYPE
See description of Open below.
AccessOptions: TYPE = {read. append. write. overwrite}:
Used at the time a stream is created to specify the set of operations allowed on a stream. Disallowed
operations raise lo.Error[NotImplementedForThisStream] when called. The characteristics of each
option:
read: PutChar. PutBlock. SetLength are disallowed. and the initial streamIndex is O.
overwrite: all operations are allowed. the file is truncated to ·zero length at stream creation time.
and the initial stream Index is O.
append: GetChar. GetBlock. SetLength. SetIndex are disallowed. and the initial streamIndex is
fileLen.
write: all operations are allowed. ~nd the initial stream Index is O.
CloseOptions: TYPE = CARDINAL:
CloseOptions detennine optional processing. during Flush and Close calls.
If
commitAndReopenTransOnFlush. then Flush "checkpoints" the transaction being used by the stream.
If truncatePagesOnClose. then Close causes extra pages of the file to be freed. If finishTransOnClose.
then Close causes the transaction to be committed or aborted. according to the abort flag to Close.
noCloseOptions: CloseOptions = 0:
commitAndReopenTransOnFlush: CloseOptions
1:
truncatePagesOnOose: CloseOptions
2:
finishTransOnClose: CloseOptions = 4:
defaultOoseOptions: CloseOptions = truncatePagesOnClose + finishTransOnClose:

=

=

RawOption: TYPE = BOOL;
This parameter detennines the mode of access to Tioga fonnat files. If raw
FALSE and file is in
Tioga format. then if accessOptions = read. read only the plain text portion of the file (ignore "looks"
and nodes with the comment property): if accessOptions # read or overwrite. raise OpenFailure
[cantUpdateTiogaFile]. If raw = TRUE or file is not in Tioga format. then operate on the entire file.

=

StreamButTerParms: TYPE = RECORD [
bufferSize: INT [2 .. 127].
Specifies the number .of pages of VM used by the stream for buffering. Juniper streams
always use 1 page of buffering.
bufferSwapUnitSize: INT [1 .. 32]];
Specifies the number of pages in each uniform swap unit of the stream buffer.
[bufferSize: 25. bufferSwapUnitSize: 5];
defaultStreamBufferParms: StreamBufferPanns
Good for most purposes.
[bufferSite: 2. bufferSwapUnitSize: 1];
minimumStreamBufferParms: StreamBufferParms
Good when opening a stream just to create a file or set its length.

=

=

Open: PROC [
fileName: ROPE.
accessOptions: AccessOptions ... read.
createOptions: CreateOptions ... none.
closeOptions: CloseOptions ... defaultCloseOptions.
transaction: Trans ... Ouniper(]],
raw: RawOption to FALSE.
createLength: I~ ... 5 • bytesPerPage.
streamBufferParms: StreamBufferParms .. defaultStreamBufferParms]
RETUR!'IS [STREAM]:

! Open Failed with why =
jileNotFound: crealeOptions = oldOnly and file does not exist (including server not found

3

when fileName is a foil path name).
illegalFileName: syntax or other error caused directory lookup to fail.
fileAlreadyExisls: crealeOplions = newOnly and file already exists.
canlUpdateTiogaFile: raw = FALSE. accessOptions #' read. and file is in Tioga format.
wrongTransactionType: transaction is a non-n"'li Pilot transaction but fileName is a Juniper
file, or vice-versa.
notlmplementedYet: CIFS access is implied but accessOplions #' read.
! Juniper.Error with why = transaclionResel. notDone: don't know how 10 handle these.
! CIFS.E"or with code #' ilIega/FileName, noSuchFile. noSuchHost: don'l know how 10 handle
these.
! Volume.lnsujficientSpace: couldn't create file on local volume as requested

Create a new stream on the file specified by fileName (a full path name).

=read then createOptions =oldOnly are assumed.
If createOptions =none or newOnly and the tile specified by fileName does not exist, then create
If accessOptions

it, with initial size (in pages excluding leader page) of createLength/bytesPerPage (rounded up),
and initial length (in bytes) zero.

If fileName specifies the server "Juniper" and transaction either has pilot variant and contains
Transaction.nullHandle or has juniper variant but contains NIL (Ouniper{]] produces this), then
call Juniper.UserInit(], and create a new transaction by calling Juniper.BeginTransaction.
StreamFromOpenFile: PROC [
openFile: cIFS.OpenFile,
accessOptions: AccessOptions to read,
closeOptions: QoseOptions to defaultCloseOptions.
transaction: Transaction.Handle to Transaction.nullHandle.
raw: RawOption to FALSE.
streamBufferPanns: ·StreamBufferParms to defaultStreamBufferParms]
RETURNS [STREAM]:

! OpenFailed with why =

notlmplementedYet: accessOptions #' read

Create a new tile stream on the open tile.
StreamFromCapability: PROC [
capability: File.Capability.
accessOptions: AccessOptions to read,
closeOptions: CloseOptions to defaultCloseOptions.
fileName: ROPE to NIL.
.
transaction: Transaction.Handle to Transaction.nuUHandle.
raw: RawOption to FALSE.
streamBufferParms: StreamBufferParms to defaultStreamBufferPanns)
RETURNS [STREAM):

! OpenFailed with why =
cantUpdate TiogaFile: raw = FALSE. accessOptions #' read and file is in Tioga formaL
unknownFileCapahility: no file identified by capability is present on the local disk volume.

Create a new stream on the file identified by capability (note that StreamFromCapability adds
permissions to capability as required to perform the accesses as specified in accessOptions).
fileName is stored in the stream, for diagnostic purposes when a stream error occurs.
CapabilityFromStream: PROC [
self: STREAM)
RETt:R:--;S [File.Capability]:
! IO,E"orfNotImplementedForThisStreamJ: self is not a stream on a Pilot file
4

Return the file capability for the file underlying self. This capability has the pennissions that are
necessary to perfonn stream operations.
StreamFromLFH: PRoe [
lth: Juniper.LFH.
accessOptions: AccessOptions .. read.
c1oseOptions: CloseOptions .. defaultCloseOptions.
fileName:. ROPE" NIL.
transaction: Juniper.Transaction.
raw: RawOption .. FALSE]
RETURNS [STREAM];
! OpenFailed with why =
cantUpdateTiogaFile: raw = FALSE. accessOptions #" read. and file is in Tioga formaL
unknownFileCapability: no file with the given LFH is pre:.ent on Juniper.

Create a new stream on the Juniper file identified by Ith.
diagnostic purposes when a stream error occurs.

fileName is a debugging aid. for

END.

What STREAM operations do when applied to a file STREAM
Basic STREAM prots
IO.GetChar: PRoe [self: STREAM] RETURNS [CHAR]
If stream Index = file Len then ERROR [o.EndOtStream. Else return file[streamlndex]. and set
streamIndex .. streamIndex + 1.
IO.PutChar: PRoe [self: STREAM, char: CHAR]
If stream Index = fileLen then fileLen .. fileLen + 1. Then set file{streamIndex] .. char.
stream Index .. stream Index + 1.
IO.GetBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT .. 0, stopIndexPlusOne: NAT ..
LAST[NAT]] RETlJRNS [nBytesRead: NAT]
Equivalent to (but faster than)
stoplndexPlusOne .. MIN [block.maxLength. stoplndexPlusOne);
nBytesRead: NAT" MIN{fileLen-streamlndex, stop[ndexPlusOne-startlndex]:
FOR i: NAT IN [O•• nBytesRead) DO block[startIndex+i] .. GetChar{self] ENDLOOP:
IF nBytesRead # 0 THEN block.length .. startlndex + nBytesRead:
RETURN(nBytesRead]

,

IO.PutBlock: PRoe [self: STREAM. block: REF REAOONL Y TEXT, startlndex: NAT .. O.
stoplndexPlusOne: NAT" LAST[NAT))
Equivalent to (but faster than)
IF stop[ndexPlusOne > block.maxLength THEN stop[ndexPlusOne .. block.length;
FOR i: NAT IN [startlndex ..stoplndexPlusOne) 00 PutChar{self. block[i)) ENDLOOP:
IO.UnsafeGetBlock: UNSAFE PRoe [self: STREAM. block: 10. Unsafe Block] RETURNS [nBytesRead:
INT]
Equivalent to (but faster than)
IF block.startIndex <0 OR block.stopIndexPlusOne < 0 THEN
ERROR 10.Error(Badlndex);
nBytesRead: l:--IT .. MIN[fileLen-streamIndex. block.stoplndexPlusOne-block.startlndex):
FOR i: INT IN [O.. nBytesRead) 00
block.base't[block.startIndex + i) .. GetChar{self] E~DLOOP:
RETt.:RN{ nBytesRead]
IO.UnsafePutBlock: PRoe [self: STREAM. block: IO.UnsafeBlock]
5

Equivalent to (but faster than)
IF block.startlndex <0 OR block.stoplndexPlusOne <0 THEN
ERROR 10.Error[Badlndex):
FOR i: (NT IN [block.startlndex.. block.stoplndexPlusOne) DO
PutCh~1sel£ block.baset{i)) ENDLOOP:
(o.CharsAvail: PROC [self: STREAM] RETL'RNS [BOOL]
Return TRUE.
[0. EndOf: PROC [self: STREAM] RETURNS [BOOL]
-Return streamIndex = fiIeLen.
IO.Flush: PROC [self: STREAM]
Force all stream writes since the time of stream creation or the preceding Rush to be written to
disk. If commitAndReopenTransOnFlush then first commit trans. then begin a new
transaction as trans.
IO.Reset: PROC [self: STREAM]
If accessOptions # append then set streamIndex

+0

O.

(o.Close: PROC [self: STREAM, abort: BOOL +0 FALSE]
If NOT abort, then force aU stream actions since stream creation or the preceding Rush to be
written to disk: otherwise discard them. If truncatePagesOnClose. then discard unused pages
from end of file. If finishTransOnClose, then commit or abort trans depending on the state of
abort. Invalidate self (aU operations on self other than Rush. Reset. and Close will raise
ERROR IO.Error{StreamCtosed]: these three do nothing).
Less basic STREAM proes
IO.PutBack: PROC [self: STREAM. char: CHAR]
If streamIndex = 0 then ERROR lo.Error{lllegalPutBack]. Otherwise. set streamIndex +0
stream Index - 1. and if file[streamIndex] # char then ERROR (o.Error{lllegaiPutBack].
IO.PeekChar: PROC [self: STREAM] RETURNS [char: CHAR];
Equivalent to:
c: CHAR +0 self.GetChar{]; self.PutBack[c); RETURN [c];
File-specific STREAM proes
IO.GetIndex: PROC [self: STREAM) RETURNS [INT]
Return streamIndex.
IO.Setindex: PROC [self: STREAM. index: INT]
ERROR IO.EndOfStream if index > tileLen. Set streamIndex

+0

index.

lo.GetLength: PROC [self: STREAM] RETURNS [INT]
Return file Len.
[o.SetLength: PROC [self: STREAM, length: INT)
Set fileLen +0 1. then set stream Index +0 \1IN[streamIndex. file Len). The contents of
file{oldFileLen .. fileLen) are undefined.

Change Log
Created by MBrown on 7-Dec-81 10:33:20
. By editing FileByteStream.
Changed by MBrown on March 26, 19824:41 pm
Added "raw" parm to stream create operations.
6

Changed by MBrown on August 23, 1982 10:25 pm
Handle -> STREAM (-> Stream in proc names). introduce FileIO.OpenFailed. CIFS access in readonly
mode. initial file size in Open. buffer pages and swap units. Format this file using Tioga nodes.
Changed by MBrown on October 23. 19829:59 pm
Default transaction to Open is now {juniper[]]. since this does not require the average user tll import
Transaction (to use nul/Handle). Format to use cu"ent Cedar style.
Changed by MBrown on January 6. 1983 8:15 pm
Attempted to reduce the confosion over what is comment and what is not comment in the inter/ace.
and to improve the explanation of AccessOptions.

7

10.mesa
Top-level stream and 110 interface for Cedar
Last edited by: Teitelman on January 12. 1983 3:01 pm
Note: this interface is heavily structured using Tioga Nodes. ThUs. you can use the level clipping to
obtain a table of contents, and to successively refined levels of detail in the areas you are especially
interested.
DIRECTORY
Ascii USING [CR. SP, TAB. LF. BS. ControlA, ControlX. FF. NUL. ESC. DEL, BEL),
Atom USING [Prop List).
Rope USING [ROPE),
RTBasic USING [TV, Type].
System USING [GreenwichMeanTimej.
Time USING [Current)

10: CEDAR DEFINmONS
IMPORTS Time

= BEGIN

Types

=

STREAM: TYPE
REF STREAMRecord:
STREAMRecord: TYPE = RECORD(
streamProcs: REF StreamProcs. .- see below
streamData: REF ANY, _. dala private to slreamProcs
prop List: Atom.PropList- .. NIL, .- permits associating arbitrary information with stream. see StoreData. Lookup_
backingStream: STREAM .. NIL·- for use with layered streams.
);
Handle: TYPE
STREAJ.\{: - for backward compatibility
ROPE: TYPE = Rope.RoPE:
TV: TYPE = RTBasic.TV;
Type: TYPE = RTBasic.Type;
Base: TYPE = (2.. 36]:
GreenwichMeanTime: TYPE = System.GreenwichMeanTime;

=

Creating Streams
The following procedures enable the user to create input and/or output streams to various entities such

as viewers, files. ropes, as well as streams that are layered on top of another stream, the backing stream.
so as to modify or augment the behaviour of the backing stream. such as edited streams. dribble streams.
filtered comment streams. etc. All of these streams are defined in terms of a general mechanism for
implementing streams, CreateProcsStream. which is described below under the section Defining New
Streams.
CreateViewerStreams: PROC [name: ROPE) RETt.:RNS [in: STREAM, out: STREAM];
creates a new viewer with indicated name. and returns two streams "connected" to that viewer. one
for input and one for output. The input stream is an edited stream. Note that
ViewerIO.CreateViewerSIreams. ..

enables creating streams that are connected to an existing viewer. or specifying that the input
stream is not an edited stream. e.g. so that the client can Ihen specify his own deliverWhen
procedure when creating an edited stream on lop of the input stream.

CreateFileStreJIm To create a stream for reading/writing on a jile use FileIO.Open.
CreateMessageWillllowStream To create a stream for writing to the MessageWindow, use
ViewerlO. CreateMessage WindowS Iream.

CreatelnputStreamFromRope, RIS: PROC [rope: ROPE, oldStream: STREAM" NIL] RETURNS [stream:
STREAM]:
stream gets chars from user's rope. If oldStream is non-NIL. it is reused rather than al/ocating
space for a new stream.

CreateOutputStreamToRope. ROS: PROC RETURNS [stream: STREAM]:
stream puts chars into a rope which can be retrieved via GetOutputStreamRope, described below.
Fine point...
in order to perform this operation efficiently, a REF TEXT is obtained from a pool of scratch
REF TEXTs. As a result, it is a good idea to close the stream when it is no longer going to
be used in order to return the scratch structure to a common pool. However. if you do not,
e.g. if an error occurs. all Ihat will happen is that the structure will be garbage collected when
it is no longer referenced. and new scratch structure will be allocated to take its place in the
pooL

CreateInputStreamFromText: PROC [text: REF REAOONLY TEXT, oldStream: STREAM" NIL]
RETURNS [stream: STREAM]:
slream gets chars from user's REF TEXT. If oldStream is non-NIL. it is reused rather than
al/ocating space for a new stream.

CreateOutputStreamToText: PROC [text: REF TEXT, oldStream: STREAM .. NIL] RETURNS [stream:
STREAM]:
stream puts characters into text. If oldH is non-NIL it is reused rather than allocating space for a
new stream.

CreateEditedStream: PROCEDURE [in: STREAM, echoTo: STREAM. deliverWhen: DeliverWhenProc ..
IsACR] RETURNS [stream: STREAM);
creates a layered inputstream on top of in which buffers input characters and allows the user to
perform character editing with tA, tW, tQ. Typing a DEL will cause CreateEditedStream to
raise IO.Signa/{Ruboutj. Default-is to bUffer to carriage return. Input characters are echoed to
and erased from echoTo. ChangeDeliverWhen can be used to change buffering condition.

=

DeliverWhenProc: TYPE
PRoc[char: CHAR, stream: STREAM] RETlJRNS(BOOL];
IsACR: DeliverWhenProc; -- returns TR U E for CR.
ChangeDeliverWhen: PROC [self: STREAM. proc: DeliverWhenProc] RETURNS (oldProc:
DeliverWhenProc];
currently implemented by Edited Stream and Viewer Edited Stream (See ViewerlOj.

GetBufferContents: PROC [self: STREAM] RETURNs[buffer: ROPE):
returns contents of the buffer without disturbing. For use in conjunction with
DeliverWhenProcs which might need to see what has been typed in order to decide
whether to terminate. e.g. parenthesis balancing. etc. Currently implemented by Edited
Stream and Viewer Edited Siream.

CreateDribbleStream: PROCEDURE [stream: STREAM. dribbleTo: STREAM, flushEveryNChars: INT ..
-1] RETURNS [s: STREAM]:
creates a layered stream. s. on top of stream. such thai characters read from/printed to s will be

2

read from/printed to stream. and also output to dribbieTo. If jlushEveryNChars is
automatically call Flush on dribb/eTo every nChars.

>O.

will

CreateBufferedOutputStream: PROC [stream: STREAM. deliverWhen: DeliverWhenProc .. IsACR,
bufferSize: NAT" 256] RETURNS [5: STREAM];
creates an output stream on top of stream such that characters are buffered unlil (a) the bujJerSize
is exceeded. or (b) deliverWhen{charJ is TRUE. or (c) an explicit Flush is performed. at which
point the characters are output to stream using PutB/ocle.

CreateFilterCommentsStream: PROCEDURE [stream: IO.STREAM] RETURNS [s: STREAM]:
creales a input Slream on top of stream such that any comments are filtered out. i.e. the characters
compriSing the comments are not returned by GetCharfs/. A comment consists of that sequence of
characters beginning with - and ending with -- or a CR. In the laller case, the C R is nol
considered to be part of the commenL

AppendStreams: PROC [in: STREAM, from: STREAM. appendToSource: BOOL" TRUE]:
modifies 'in' so thai an attempt to read characters from 'in' will cause the characters to be
obtained from trom' until 'from' runs dry. at which point 'in' is returned 10 its previous state.
N ole that il is permissible to nest, Le. concatenate. more than one stream in this fashion.
If appendToSource = TRUE then modification is done to the rool stream. Le. descends through
non-NIL backingstreams. For example. if in is an edited stream. then this will cause characters
to be inserted into buffer. from which they can be backspaced over. exactly as though they had
been typed. rather than delivered to the client immediately. If in is a dribbleStream. then the
characters wi/I be dribbled etc.

DoWhereStream: STREAM:
output stream that simply discards its characters.

Unformatted stream procedures:

GetChar. PutChar, Close, etc.

Note: Not all of the following are implemented for all streams. e.g. GetLength is not implemented (does
not make sense) for a keyboard stream. If an operation is invoked that is not implemented. the
Error[NotImplementedForThisStream) is raised. However, many operations are defaulted even when they
are not implemented. See discussion below of exactly which operations are implemented for which
streams.)
Input Procedures: GetChar. EndOf. CharsA vail, GetBloc·k. Backup, PeekChar, SetEcho, ..,

GetChar: PRoc[self: STREAM) RETURNs[CHAR)

= INLINE {RETURN{self.streamProcs.getChar[self1)};
EodOf: PRoc[self: STREAM] RETUR~S [BOOL1
= INLINE {RETURN[self.streamProcs.endOtlself]]}:
true

if reading from this stream would raise an endofttream error.

CbarsAvail: PRoc(self: STREAM) RETURNS [BOOt]
= [NLINE {RETURN[self.streamProcs.charsAvail(self]]}:
true if se/f.GetChar(] would return a character without waiting.
Note: ..•
For most streams. EndOfis equivalent to -CharsAvaiL and injac!. ifCharsAvail is not
specified. a default procedure is supplied which will returns as its value NOT EndOj.
However. note that EndOf is a/ways FALSE for a keyboard stream. i.e. it is always ok to try
to read from a keyboard stream. even when CharsAvail is FALSE. Le. there are no more
characters available now.

GetBlock: PROc[self: STREAM, block: REF TEXT. stanIndex: :'IIAT .. 0, stopIndexPlusOne: :'IIAT ..
3

LAST{NATJ] RETIJRNS(nBytesRead: NAT]
= [NLINE {RETuRN(self.streamProcs.getBlock[self. block. startIndex. stoplndexPlusOne]]}:
value is number of characters actually returned Equivalent to. but more efficient than. n calls to
getChar. ..
for those streams that provide an .implementation for getBlock. e.g. file streams. Otherwise. the
getBlock is exactly the same as. i.e. is accomplished by, performing n calls to GetChar. See
discussion of default procedures below.
UnsafeGetBlock: UNSAFE PRoc[self: STREAM. block: UnsafeBlock] RETuRNs(nBytesRead: INT]
= UNCHECKED INLINE {RETURN[self.streamProcs.unsafeGetBlock[self. block]]};
value is number of characters actually returned The type UnsafeBlock. ••
is defined below in the section to Private and Semi-private types. ..
Backup: PROC [self: STREAM. char: CHAR]:
Used when input went too far...
.
Note that Backup is an operation on the input stream. It modifies self so that the next
getChar[self] will return the same character and leave self in the state it was in before the
Backup. The implementor is only required to implement Backup for those situations where
char is in fact the character that was last read by getChar. (The character argument is
required in order to provide a generic implementation for the operation. i. e. when the
particular stream does not implement Backup itself).
PeekChar: PRoc(self: STREAM] RETURNS [char: CHAR1;
does a GetChar followed by a Backup, i.e. effectively looks at the next character without actually
reading iL
SetEcho: PRoc(self: STREAM. echoTo: STREAM] RETURNS [oldEcho: STREAM]:
causes every characler readfrom stream 10 be echoed to echoTo ifnon-NIL
Output procedures: PutChar. PutBlock. Flush. EraseChar. GetOutputStreamRope...,
PutChar: PRoc(self: STREAl\i, char: CHAR]
= INLINE {self.streamProcs.putChar[self. char)};
PutBlock: PRoc(self: STREAM. block: REF READONLY TEXT. startIndex: NAT" O.
stopIndexPlusOne: NAT" LAST[NAT]]
= INUNE {self.streamProcs.putBlock[self. block. startIndex, stopIndexPlusOne)}:
UnsafePutBlock: PRoc(self: STREAM. block: UnsafeBlock}
= INLlNE {self.streamProcs.unsafePutBlock[self. block)}:
Flush: PROC [self: STREAM}
= INUNE {self.streamProcs.flush(self]}:
causes characlers that have been output to stream. but not yet sent. e.g. because of buffering, to be
sent
EraseChar: PRoc(self: STREAM. char: CHAR]:
erases char from output stream, e.g. erases the bils from the display...
Note that EraseChar. is an operation on the output stream. Whatever the corresponding input
stream might have done about the character that IS being erased is an entirely separate
operation EraseChar just specifies what is to be done to the output stream.
CurrentPosition: PRoc(self: STREAM} RETURNS[position: [NT};
number of characters output since last CR.
Newline: PROC [self: STREAM}
= [NLINE {IF self.CurrentPosition[] # 0 THEN self.PutChar[·\nJ}:
outputs a CR unless already at beginning of the line.
SpaceTo: PROC (self: STREAM. n: [NT, nextLine: BOOLEA:'II .. TRUE);
spaces to position n. If current position already beyond nand nextLine is TRUE. then new line
and n spaces.
GetOutputStreamRope: PROC [self: STREAM] RETt:R:-.lS (ROPE);
used in conjuction with the CreateOulputSlreamToRope to get the resulling rope

4

Miscellaneous Procedures: Reset. Close. UserAbort. GetIndex. SetIndex, GetLength, SetLength
Reset: PRoc[self: STREAM]
= !NLINE {self.streamProcs.reset[selt]};
restores Ihe stream to a clean state. e.g. may.flush or restore internal buffers. typically invoked
.
following an error.
Close: PRoc[self: STREAM. abort: BOOL" FALSE]
= INUNE {self.streamProcs.close[self. abort]}:
UserAbort: PROC (stream: STREAM] RETURNS [abort: BOOLEAN]:
If unimplemented for corresponding stream or backing stream. returns FALSE. TR UE means user
indicated desire to abort operation. It is up to program to take the apPrt:?priate steps, which
should culminate in raising IO.UserAborted. Currently implemented for ViewerStreams, TRUE if
user types control-Del to the viewer. or if the viewer is connected a userexec. can also be set by
clicking STOP.
SetUserAbort: PROC [stream: STREAM];
sets the user abort. i.e. provides a programmable way to abort (the operation currently running in)
an exec. Generates an error if not implemented for the corresponding stream. Currently only
implemented for ViewerStreams.
ResetUserAbort: PROC [stream: STREAM] :
tum the abort bit off, if implemented. Otherwise. nop.
GetIndex: PRoc[self: STREAM) RETURNS [index: [NT)
INLINE {RETURN(self.streamProcs.getIndex[selt])};
Setlndex: PRoc[self: STREAM, index: [NT]
= INUNE {self.stream.Procs.setIndex[self. indexl}:
GetLength: PRoc[self: STREAM] RETURNS {length: INT]:
SetLength: PRoc[self: STREAM. length: [~'T];

=

Formatted stream procedures:

Put. PutF. PutList. PutRope, PutTV, PutType, ..•

Put: PROC [stream: STREAM. vi. v2. v3: Value" [nul1(]]]:
The basic output routine. handles any type via Values, defined later. Provides convenient default
behaviour for simple output, i.e. outputs integers and cardinals in decimal. time using both date
and time. etc. Example: s.Put{int{x+ y]. ropel" is greater than "}. int{xD would produce "8 is
greater than 5: for x = 5 and y = 3. For more control over the output...
use PutF. described be/ow. which allows specification offield Width. base. etc.
Put only takes three value arguments...
so that the procedure cail can be "fast" (i.e. take II or fower words on the stack). PutList can
be used for calls specifYing more arguments at the expense of the ailocation of space for the
LIST. or the user can write several calls to Put.
PutF: PROC [stream: STREAM. fonnat: ROPE .. ~[L. vI. v2, v3, v4, vS: Value .. (nuU(]]];
produces output acconJing to a collection of values and a format control string which can include
embedded format codes. For example: s.PutFl"%d is greater than %d". int{x+ y). int{x}} is
equivalent to the above calion Put. For more discussion. see section "PF Package".
format = NIL is eqUivalent to "%g%g%g... " which means 10 prif!,t each value Ihe same as would
_ be printed by Put.
Note that PutF is a slow procedure cail. i.e. its arguments require more than II words on the
stack.
PUIF may raise signa/s. RESUME will always work and will either do
nothing or print "#' #' #' #' #,".
PutList, PutL: PROC [stream: STREAM, list: LIST OF Value);
for outputting more than three quantilies via a single call to Put.
PutFList, PutFL: PROC (stream: STREAM. fonnat: ROPE .. ~IL. list: LIST OF Value]:
PutFToRope. PutFR: PROC [fonnat: ROPE ... ~[L. vi. v2, v3. v4. v5: Value" [nuU[]]] RETt.:R!.'IS [r:
ROPE]
5

= INLINE
{stream: STREAM" CreateOutputStreamToRopeO; stream.PutF[fonnat. vl. v2. v3. v4. vS]; r ..
stream.GetOutputStreamRopeO; stream.CloseO:

}:
PutText: PROC [self: STREAM. t: REF REAOONLY TEXT]
INLINE {self.PutBlock[t]};
much more efficient than seIf.Put{text{tJJ:
PutRope: PROC [self: STREAM. r: ROPE];
much more efficient than seIf.Put{rope{rD:
PutTY: PROCEDURE[stream: STREAM. tv: TV. depth: INT .. 4. width: INT .. 32, verbose: BOOL ..
FALSE];
depth and width control the cutofffor printing of the tv. verbose specifies whether to print
additional information. e.g. the octal value for global frames. etc. stream.Put{tv{x]] is equivalent
to stream.PutTV{x}. and is the proper way to print tvs for most applications..
PutType: PROc[stream: STREAM. type: Type. depth: INT .. 4. width: INT .. 32, verbose: BOOLEAN ...
FALSE];
If verbose is FALSE. just the name of the type is printed If verbose is TR UE. the undertype is
also jJrinted for named types. For example. if x is of type BreakProc. then stream.PutType{x.
FALSE] prints: IO.BreakProc. whereas slream.PutType{x. TRUE] prints as: IO.BreakProc
PROC {c: CHAR] RETURNS {1O.BreakAction].
In addition. the range type is printed for undertypes that are refs or pointers. For example. if x is
of type STREAM. stream.PutType{x. TRUEJ prints as: IO.STREAM = REF
IO.STREAMRecord: (and on the next line) IO.STREAMRecord: TYPE = RECORD f. ..J:
stream.Put{type{x]J is equivalent to stream.PutType{type]
PutSignal: PROC [stream: IO.STREAM. signalTV. argsTV: TV .. :-.lIL];
Prints the indicated signal on stream. If signalTV = NIL, prints the "current" signaL i.e. for use
inside of a catch phrase.

=

=

Procedures for constructing Values: atom. bool. card, char, into real. refAny, rope. tv •...
saves writing two extra brackets. the type Value is defined in section 4.

atom: PROC [v: ATOM] RETURNS (Value]
= INUNE {RETURN((atom[v]])};
bool: PROC (v: BOOL] RETURNS (Value)
= INUNE {RETURN([boolean[v]]]}:
card: PROC [v: LONG CARDINAL] RETt.JRNS [Value]
= INLINE {RETURN([cardinal(v]]]};
char: PROC (v: CHAR) RETURNS [Value]
= INUNE {RETURN([character{v]]]}:
int: PROC [v: INT] RETURNS [Value)
= INUNE {RETURN[[integer{v]]]}:
real: PROC [v: REAL] RETUR.."IS [Value]
INUNE {RETURN([real[V]]]}:
rerAny: PROC [v: REF REAOONLY Al'4'Y] RETURNS [Value]
= INUNE {RETURN([refAny[v]]]};
rope: PROC [v: ROPE] RETURNS (Value]
INUNE {RETURN([rope[v]]]};
string: PROC [v: LONG STRING] RETt:RNS [Value]
INLI:-.lE {RETURN([string[v]]]};
text: PROC [v: REF REAOONLY TEXT] RETURNS [Value)
= INLINE {REn..rRN{[text{v]]]}:
time: PROC [v: GreenwichMeanTime .. Time.Current[]] RETURNS [Value]

=

=
=

6

= lNLINE {RETUR!'f{[time[v))]}: -- i.e. time[] is the current time
tv: PROC [v: RTBasic.TV] RETt:RNS [Value]
= lNLINE {RETURN([tv[V)]]}:
type: PROC [t: RTBasic.Typej RETURNS [Value]
= Il"LINE {RETURN[(type[t)]]};
Parsing the input stream: GetCedarToken, GetToken, GetInt, GetReal, GetRefAny, ...
Parsing the input stream as a sequence or characters: GetSequence
CharProc: TYPE = PROC [char: CHAR] RETURNS [quit: BOOL

~

FALSE, include: BOOL

~

TRUE];

GetSequence: PROC [stream: STREAM. charProc: CharPr<;>e .. UneAtATime] RETURNS[ROPE):
reads characters from stream until EOF or quit is TRUE. including those characters for which
include is TRUE. For example. the definition of LineAtATime is RETURN{char = CR. FALSE}.
Thus s. GetSequence{j will read to the next CR and return the characters read as a rope.
LineAtATime: CharProc:
EveryThing: CharProc:
definition is {RETURN[FALSE, TRUE]} i.e. in.GetSequence[EveryThingJ returns the contents of in.
Parsing the input stream as a sequence or Cedar Tokens: GetCedarToken
GetCedarToken: PROC [stream: STREAM] RETURNS[ROPE];
uses CedarScanner to scan the input stream for the next mesa token. which is returned as a rope.
e.g. for the stream IO.RIS{'1$foo. a.b. 3.21". successive calls on GetCedarToken would return the
nine tokens '1" "$foo" "." "a" "." "b" "." "3.2" and "]". GetCedarToken automatically filters
out all comments. For convenience in use with the interpreter. & is treated as a regular character.
rather than causing a syntax error. i.e. "&23" will parse as a single token.
GetAtom, GetBool, GetCard, Getlnt, GetReal, and GetRope described below provide ways of
parsing the input stream into objects of the corresponding type. If the client knows what type of
object is next expected. he can use the input routine for that type, e.g. i: INT .. stream.Getlnt[].
rather than calling GetCedarToken and then converting the resulting rope to the corresponding type.
GetRefAny provides a compromise between these two positions by returning an object that is a REF
to the corresponding type, e.g. REF INT. REF BOOl. etc. The client can then discriminate on the
type of the REF.
.
Basic input routines for each value type: GetCard. GetInt, GetReal, ..,

Example: i: INT

t-

stream.Getlnt[J;

Note: all of the follOWing procedures use the CedarScanner to obtain the nexltoken. If the token is
of the appropriate 'kind: the co"esponding value is returned. otherwise, raise SyntaxError with an
appropriate message.
SyntaxError: ERRoR[stream: lO.STREAM. msg: ROPE" NIL):
GetAtom: PROC [stream: STREAM) RETURNS [ATOM]:
raises SynlaxError if next token is not an atom
GetBool: PROc[stream: STREAM) RETURNS(BOOLEAN]:
returns TRUE if next token is TRUE. FALSE if FALSE. otherwise SyntaxError.
Note: if you are planning on using GetBool to ask for confirmation:
UserExec.ExecConfirm and UserExec. ViewerConfirm provide convenient and standard ways of
asking for confirmation. These procedures a/so post menu buttons and handle the case where
7

the user has typed ahead before the need for confirmation arose.
GetCard: PROC [stream: STREAM] RETURNS [LONG CARDINAL]:
GetInt: PROC [stream: STREAM] RETURNS [I:\'T]:
Get Real: PROC [stream: STREAM] RETURNS [REAL]:
GetRope: PROC [stream: STREAM] RETURNS [ROPE];
raises SyntaxE"or if next token is not a rope.

GetId: PROC [stream: STREAM] RETURNS [ROPE];
raises SyntaxError if next token is not an identifier.
Reading Ref Anys: GetRefAny, GetRefAnyLine
GetRefAny: PROC [stream: STREAM] RETURNS [REF ANY]:
Use cedar scanner to parse the input stream. then return the resulting token as a REF to the
appropriate type. e.g. REF INT. REF REAL. REF BOOL. ATOM. ROPE. or LIST OF REF
AN Y. etc. t in fronl of an object is ignored in order thai read and print be inverses. e.g. t 3 will
produce NEW[INT #- 3]. Identifiers are read in as atoms. e.g. foo will produce $foo. The input
syntax for lists is ( followed by a sequence of tokens terminated by). e.g. (a b c) will read in as
LIST[$A. $B. SC]. Commas are permitted (and ignored) between elements of a list.
GetRefAnyLine: PROC [stream: STREAM] RETURNS[LIST OF REF ANY];
calls GetRefAny. constructing a list of the values returned. until an object is immediately followed
by a CR...
e.g. if user types Faa FIE FUM{cr} returns ($FOO. $FlE. $FUM). Ifuser types Faa FIE
FUM{sp}{cr} continues reading on next line. Useful for line oriented command interpreters.
(Note that a CR typed inside of a list simply has the same effect as a space. i.e. terminates
the previous identifier. but not the read operation).
Parsing the input stream as a sequence of arbitrary tokens: GetToken
GetSequence parses the input stream into a sequence of characters. e.g. the next line. The application
then typically has to parse this sequence into smaller units. called tokens. GetCedarToken is one way to
do this. However, occasionally the user may not need the full power of the cedar scanner, or may wish
to employ some other algorithm. The charProc argument of GetToken described below provides for a
limited form of parsing by dividing all characters into three classes: {sepr. break. other}.
A sepr character is a character that separates tokens. Sepr characters never appear in tokens. For example.
for most applications. SP would be a sepr.
A break character is a character that is a token all by itself. For example, for some applications. ] might
be a break character.
other characters are everything else.
BrealcProc: TYPE = PROC [char: CHAR] RETURNS [CharClass);
CharClass: TYPE
{break. sepr. other}:

=

GetToken: PROC [stream: STREAM. breakProc: BreakProc .. TokenProc] RETt.:RNS[ROPE];
skips over characters which breakProc says are seprs. and then reads until it encounters either a
break or sepr. If break is the first thing enco.untered. return a token consisting of the single
break character. otherwise return the sequence of other characters read before the first break or
sepr.
Thus each time you call GetToken. you get back a rope consisting of either one or more other characters.
or else a rope consisting of just a single character that is a break character.
For example. suppose your application involved parsing an input stream into a sequence of identifiers

8

separated by commas. where you want to make sure that there is a comma between each identifier. but
don't care whether there are any spaces before or after the comma. Here is what you might write:
YourProc: BreakProc

= {RETURN[IF char = " THEN break ELSE IF char = SP THEN sepr ELSE other]};

Successive calls on GetToken using this BreakProc would alternately return identifiers and ..... ,
Since it is a good example of the use of GetSequence. here is the definition of GetToken:
GetToken: PROC[stream: STREAM. breakProc: BreakProc) = {
anySeen: BOOL +- FALSE:
-proc: CharProc = {
SELECf breakProc[char) FROM
break = > {include +- NOT anySeen; quit +- TRUE}:
sepr => {include +- FALSE: quit +- anySeen}:
other -=> {include'" TRUE: quit +- FALSE; anySeen +- TRUE}:
ENDCASE = > ERROR:
};
RETURN[GetSequence[stream. charProc)]:
};
The following procedures may be useful in conjunction with GetToken.
WhiteSpace: BreakProc:
Returns sepr on SP. CR. LF. TAB, other for all others
IDProc: BreakProc:
Returns sepr for SP. CR. ESC. LF. TAB, comma, colon. and semicolon.
and other for all others. i.e. s.GetToken[ldProc] is approximately the same as the old

s. GetRope[j.
TokenProc: BreakProc:
Returns sapr for SP. CR. ESC. LF. TAB. comma. colon. a,!d semicolon.
break for {, ]. (. ). {.}. ": •+, '-. ''''; /, '@. '~.
and other for all others. i.e. s.GetToken/TokenProc] is approximately the same as

s.GetCedarTokenfJ (but real numbers. quoted lilerals. quoted text. elc. are not handled the same).
SkipOver: PRoe [stream: STREAM. skip While: BreakProc ... WhiteS pace):

skips over all seprs. or until it reaches the end of the stream. If skip While = NfL. no characters
are skipped.

Stream Property Lists
The stream's property list can be accessed and used by the client for storing and retrieving data associated
with a particular key. the same as with an atom's propeny list. The procedures StoreOata. LookupOata.
and RemoveOata correspond to PutProp. GetProp. and RemProp.
StoreData: PRoe [self: STREAM, key: ATOM. data: REF ANY]:

adds an entry to property list. or replaces existing one,
.-\ddData: PRoe [self: STREAM. key: ATOM, data: REF ANY] :
like StoreData. except adds iL to front of property list, even if s.omething already there. i.e. so can

use property list as a push down list.

9

LookupData: PROC [self: STREAM. key: ATOM] RETURNS [REF ANy1;
returns first occu"ence of key
RemoveData: PROC [self: STREAM. key: ATOM]:
removes first occurrence of key from property list

Derming new kinds of streams
A stream is defined by specifying a collection of procedures which implement the various operations that
a stream must support, such as reading or printing a character. erasing a character. closing the stream.
changing its echoing. etc. Not all of the procedures need to be specified. For example. all procedures
relating to output need not be defined for an input stream. Similarly. some operations that are not
defined can be carried out in terms of others that are. e.g. if the GetBlock procedure is not specified, a
call to GetBJock will be automatically transformed into n calls to GetChar. etc. Finally. if the stream is
layered on top of another stream. it will automatically inherit the latter streams definitions for those
procedures that are not explicitly specified. For a more complete discussion of what it means to default
a stream procdure. see the discussion below following the definition of CreateProcsStream.

The following is an example of defining a new kind of stream.

An example: derming a stream to the Message Window
The application is to define a stream which can be used for output to the Viewer Message Window.
Since the MessageWindow interface allows one to display ropes. the idea is to dump the characters into
a rope, and then display the rope in the message window when a Flush is executed. We can write
characters into a rope using a Rope Output Stream, described above. Furthermore. if we make the Rope
Output Stream be the backing stream for our Message Window Stream. we do not even have to define
PutChar, but can simply allow for that operation to be executed by a call through to the Rope Output
Stream's PutChar. All we have to do is to define what Flush and Reset mean:
MessageWindowStreamProcs: REF StreamProcs .. NIL: -- the block of procedures for the stream.
[nitialized the first time one of these streams is created.
CreateMessageWindowStream: PROCEDURE RETURNS [STREAM] = {
IF MessageWindowStreamProcs = NIL THEN MessageWindowStreamProcs ..
CreateRefStreamProcs(
flush: Message WindowStreamFlush,
reset: Message WindowStreamReset.
name: "Message Window"
]; -- initialize the block of procedures
RETURN{IO.CreateProcsStream[streamProcs: MessageWindowStreamProcs, backingStream:
IO.ROS{]. streamData: NIL]]:
}; -- of CreateMessageWindowStream

={

MessageWindowStreamFlush: PRoc(self: STREAM]
r: ROPE .. self.backingStream.GetOutputStreamRope{]: -- get the characters that have been
printed.
i: INT .. 0:
self.backingStream.Reset[]; -- reset the rope output stream.
WHILE (i .. Rope.Find[sl: r. s2: "\n". posl: i)) # -1 00
r .. Rope.Replace[base: r. start: i. len: 1. with: ""]: -- change crs to spaces (since message
window is only one line high!)
ENDLOOP:

10

MessageWindow,Apptmd{message: r. clearFirst: TRUE]; -- display the rope
};

MessageWindowStreamReset: PRoc[self: STREAM] = {
self.backingStream.Reset(]; -- reset the rope output stream.
MessageWindow.Clear(]: -- clear the message window.

}:
CreateProcsStream: PRoc[strearnProcs: REF StreamProcs. streamData: REF ANY, backingStream:
STREAM .. NIL] RETURNs(stream: STREAM]:
the general mechanism for implementing streams.
streamProcs is intended 10 be the result of a call to CreateRefStreamProcs (described below).
CreateRefStreamProcs is responsible for inserting the appropriate default procedures for those
operations not explicitly implemented by the stream. See discussion of default operations below.
backingStream is used when building a layered stream: those operations nol defined in
streamProcs will be automatically inherited from (passed down to) the backingSlream.
Note: if no backingStream is specified. the minimum required to implement a stream to be used for
input is getChar and endOf. The minimum required to implement a stream to be used ror output is
putChar. Everything else can be defaulted...
In other words. if these operations are implemented. the only way of encountering the signal
NotimplementedForThisStream is if the client explicitly calls GetIndex, SetIndex. GetLength,
SetLength. GetunsafeBlock. or PutUnsafeblock when they are not implemented. or if the client
attempts to obtain input from a stream intended to be used only for for output or vice versa. All
other procedures will be handled via the defaults described below.
CreateRetStreamProcs: PROC[
getChar: PRoc[self: STREAM) RETURNs[CHAR) .. NIL,
endOf: PRoc[self: STREAM) RETURNS(BOOL) .. ~IL.
charsAvail: PRoc[se1f: STREAM) RETt:RNS[BOOl) .. NIL.
getBlock: PRoc[self: STREAM, block: REF TEXT. stardndex: NAT. stopIndexPlusOne: ~AT)
RETURNs(nBytesRead: NAT) .. NIL,
unsafeGetBlock: UNSAFE PROc[self: STREAM. block: UnsafeBlock) RETURNs(nBytesRead: INT] ..
NIL,
putChar: PROC(self: STREAM. char: CHAR] .. NIL,
putBlock: PROC(self: STREAM, block: REF REAOONLY TEXT. stardndex: NAT, stopIndexPlusOne:
NAT] .. NIL,
unsafePutBlock: PRoc[self: STREAM. block: UnsafeBlock] .. NIL.
flush: PRoc[self: STREAM) .. NIL.
reset: PRoc(self: STREAM] .. NIL.
close: PRoc(self: STREAM, abort: BOOL .. FALSE] .. NIL,
gedndex: PRoc[self: STREAM] RETURNS [I NT] .. NIL,
setIndex: PROc[self: STREAM. index: INT] .. NIL.
getLength: PRoc(self: STREAM) RETUR~S [length: INT) .. NIL,
setLength: PRoc(self: STREAM. length: INT) .. NIL.
backup: PRoc[self: STR.2AM. char: CHAR) ... ~[L,
userAbort: PROc[self: STREAM) RETt:R~s[abort: BOOL) .. ~IL.
setUserAbort: PROC[self: STREAM) ... :-.ilL.
resetUserAbort: PRoc[self: STREAM) .. :--IlL.
setEcho: PRoc[self: STREAM. echoTo: STREAM) RETt:RNS [oldEcho: STREAM] .. :--IlL.
eraseChar: PRoc[self: STREAM. char: CHAR) ... :-.ilL.

11

currentPosition: PRoc[self: STREAM] RETURNS[position: [NT] .. NIL.
name: Rope.ROPE .. NIL --used for printing the slream itself as a ref any.

J
RETURNS [REF StreamProcs);

creates a REF streamprocs, supplying appropriate defaults for the NIL procedures. Intended to be
performed only once for each different stream class and the resull saved. i.e. all instances of this
stream can share the same streamProcs.
Wlurt it IIWIns to default II St1'etIm opemtion

The default procedure is to first check if there is a backingStream. and if so. call the corresponding
operation in the backingStream. If no backingStream is specified. the default procedure is as follows:
CharsAvail: check whether endOf was specified. and if so return -endOt{handleJ. otherwise raise
signal NotlmplementedForThisStream as described below
EndOr: check whether charsAvail was specified. and if so return -charsAvail(handle]. otherwise raise
signal NotlmplementedForThisStream as described below
GetBlock: implement via n Calls on GetChar
PutBlock: implement via n calls to PutChar
Flush. Reset: Nops. do not signal
Close: if abort

= NIL. call Flush. otherwise. call Reset do not signal

Backup: replace. i.e. ambush. the stream's original StreamProcs by a different set of procedures in
which getChar. getBlock. endOf. charsA vail. and reset have different definitions when the stream is
in the "backed up" state. The remaining procedures call through to the original procedures. When
the character has been consumed. the streams original procedures are restored. Note that this causes
the stream to run more slowly only when in the backed up state.
SetEcho: similar to Backup. Le. ambushes the getChar and getBlock procedures. causing them to also
output to the indicated handle. This causes all procedure calls in the stream to run more slowly due
to the extra level of procedure call and lookup;
CurrentPosition: ambushes the streams putChar and putBlock procedures. and counts the characters
as they go by. Since this does not occur until the first call to CurrentPosition. characters that were
output before this call will not be counted. i.e. the first call to CurrentPosition will always return O.
and subsequent calls until the first CR is seen will return the number of characters output since the
first call:
EraseChar: output \ followed by the character. Defaulting EraseChar does not affect the perfonnance
of the stream on other operations.
For all other cases. the default procedure is to raise SIGNAL Signal[NotImplementedForThisStream]
(Le. client can resume) . if the corresponding operation does NOT return a value (i.e. is executed for
effect only. such as putChar). or raise ERROR Error[NotimplementedForThisStream] if the
corresponding operation requires a return value. such as getChar.
In general. the decision about whether or not to implement a particular operation for a stream. must
be made on the basis of perfonnance and frequency of use versus convenience For example. if the
stream implements backup itself. it can include the necessary code in its own getChar. getBlock, reset.
etc., so that these procedures will continue to run fast. even when the streeam is backed up. However.
it is more work for the implementor. For example, viewer streams implement SetEcho. but
InputRopeStream does not. Similarly. an edited stream implements backup but viewer stream does
not. on the grounds that most calls to a viewer stream that involve parsing and backing up will instead
be going to an an edited stream.

12

AmbushProcsStream: PRIVATE PROCEDURE[self: STREAM. streamProcs: REF StreamProcs,
stream Data: REF ANY, reusing: STREAM to NIL] ;
used to build a layered stream on top of another stream. for those cases where the desired effect
is 10 have any program that has hold afself to see the new behaviour. Implemented by
smashing self to point to the new pmcs and data. with a backing stream that contains the
same data. procs. etc. as self originally did. ifreusing is non-NIL. it is reused and no
allocations are performed. Typically,reusing is saved on the property list of a stream which is
going to be ambushed and then unambushed repeatedly.
UnAmbushProcsStream: PRIVATE PROCEDURE[self: STREAM):
inverse of AmbushProcsStream. i.e. elevates Ihe backing stream to self. Nop if no backing
stream.

Derming new stream operations
CreateRetStreaQlProcs takes as arguments 22 predefined operations on a stream. Suppose we want to
define new operations which might not appear in this interface which are to be (optionally) implemented
by a various kinds of streams. The procedure Implements allows us to do this. It is used to provide a
generic implementation for AppendStreams for all streams that do not implement this operation (currently
no stream does), to implement ChangeDeliverWhen for both edited streams and viewer edited streams
(see ViewerlO), and also the mechanism used to supply the default behaviour for Backup and
CurrentPosition described above. For examples of its use, see IOlmpl.
Implements: PRIVATE PROC [self: STREAM, operation. via: PROC ANY RETURNS ANY):
used to supply the implementation of an operation other than those specified as arguments to
CreateRejStreamProcs. operation' is the generic procedure. and Via is the implemenLing
procedure for this stream class. Via is checked (using Ihe RT inter/aces) to make sure it is of the
cOm!ct type. (The names of the argumenLs as well as the return values must agree.) If it is not.
Ihe signal IO.Error[ProcedureHasWrongType) is raised. If the type is con-ecl. Via is saved an the
property list of the streamProcs. so that the type checking need be done only once for each
stream class. Subsequent ca/ls to Implements for the same stream class are essentially nops.
When the 'operation' is invoked. 'via' will be called with the same arguments as Ihe generic
procedure was called with.
For example. ifCreateRefStreamProcs did not take setLength as an argument. this operation
could be implemented for a particular stream class by per/orming:
stream.lmplements[SetLength. MySetLengthl where MySetLength is of type PROcrself:
STREAM, length: INT].
UncbeckedImplements: .• Even more - PRIVATE PROC [self: IO.STREAM. operation. via: PROC ANY
RETUR!'IS ANY, data: REF ANY to NIL, procRef: REF ANY, key: ATOM):
.
used by implements. Calling directly and specifying procRef and key enables avoiding use of RT
inter/aces
LookupProc: PRIVATE PROC [self: STREAM, operation: PROC ANY RETUR!'IS ANY] RETURNS(proc:
REF ANY]:

PF (PrintFormatted) Package
Concept
PutF (and PutFR and PutFList) produce output according to a collection of Values and a fonnat control
string which can including embedded format codes. The Values that are the arguments to PutF are
13

associated with the format codes in the order that they appear in the format string. For example:
h.PutF["This is %g in a 5 position field: 1%5dl". 'rope[" an integer"], int[17]];
would produce the result:
"This is an integer in a 5 position field:

I

171".

If a format code is encountered which is not recognized. the signal IO.Signal[UnknownFonnat] is raised.
If there are not enough format codes to match the values supplied as arguments, or not enough values
then m
'
PreDermed Format Codes
T,he Value refAny is accepted by all formats: if dereferencing yields a value of an acceptable type, it is
printed directly. Otherwise. if %g or %h are used. [O.PrintRefAny is called. If some other code was used.
the Signal IO.Signal[UnprintableValue) or IO.SignalrrypeMismatch] is raised. If this signal is RESUMEd,
some •# characters are printed.
In the following descriptions, "number" means a Value that is either card. char, int. real, or time.
CHARACTERS passed to a number routine print as their Ascii code.

"string" means a Value that is either a string, rope, text. boot, or a number. BOOLEANs passed to a
"string" routine print as TRUE or FALSE and CHARACTERs print as characters.
%e: accepts numbers. Like Fortran E format. prints in "scientific notation" (mantissa and exponent).
%f: accepts numbers. Like Fortran F format. prints in "fixed point" format.
%g: accepts all values. Prints whatever you give it sensibly. When in doubt. use %8.
%h: like %g. except that control characters (code < 4OB) print as "t.

%1: accepts ROPEs. Changes looks for ViewerStreams. is a NOP for all other streams so that the client
does not have to know whether he is printing to a viewer or a file or whatever. The value is interpreted
as a sequence of looks, e.g. h.PutF["Make this %lbold%l for emphasis", rope["b"), rope("B]] will print
"Make this bold for emphasis". (Note that B means remove the bold look because it is shift-b.) The
character space has the same interpretation as for tioga. i.e. removes all looks.
%r: accepts numbers, interprets as time interval in seconds, and prints as HH:MM:SS
%t: accepts numbers and Time[], prints in usual date format with time zone (e.g. " PDT")
The following formats apply to all numbers (and to BOOLEANs with the conversion TRUE ~ 1 and FALSE
0). (To print a POINTER, LONG POINTER, REF. etc. value as a number, PUN it into a number of the
correct length before converting to a Value.)

=

%b: print in octal.
%d: print in decimal.
%X: print in hex.
Field Width Specifications
Information about printing a particular value can be inserted betwefOn the "%" and the code letter. Is
this true for all control codes??? Field width. left or right justification. and zero filling can be controlled.
The default is to print the value in its entirety. with no spacing on either side. If a number is present
between the "%" and code (e.g. "%6d"), it is interpreted as a minimum field width. useful for printing
columns. etc.
Extra spaces are inserted before the number (right adjusted) to fill out to the indicated number of spaces.

14

unless a "-" precedes the number (e.g. "%-6d") to indicated filling with spaces on the right (left-adjusted).
If "-" is not present. a "0" may be inserted (e.g. "%06d") to indicate right-adjustment and filling with
zeroes rather than spaces. In any case the field width is a minimum. not a maximum. Should the size
of the output exceed the field width. it is printed in its entirety.
A fiet~ width may have the form xx.yy. viz: "%12.4g". These specifications are interpreted by the
floating point number printing routines. Other types of conversions ignore the "fraction".

Defining new format codes
.

.

Users may specify their own procedures to interpret codes following the "%" via SetPFCodeProc. For
example. h.SetPFCodeProc{,z. ZProc] will cause subsequent references to "%z" to call ZProc. Predefined
codes (e.g. d. e, t) may be redefined. Only alphabetic (['a.:z]) code characters are legal. case does no
matter.
SetPFCodeProc: PROC [stream: STREAM. char: CHAR, codeProc: PFCodeProc]:

when 9Gchar is encountered. codeProc is called wilh format = ??'!. and val = the Value that
corresponded 10 this control code.

=

PFCodeProc: TYPE
PROC [stream: STREAM, val: Value, format: Format. char: CHAR]:
Format: TYPE = RECORD [form: ROPE. first: (NT];
.
Another way of defining new commands is via SetPFStarCodeProc. PFStarCodeProcs differ from
PFCodeProcs in that they do not take arguments, Le. none of the Values that comprise the arguments
to the output procedure are associated with this PFStarCode. PFStarCodes are indicated in the format
string by preceding the code with a • instead of a %, and then following it immediately with the code
letter (non-alphabetic characters following • print as themselves, e.g. " ••" prints as .),
Undefined StarCodes also raise [O.Signal[NoumplementedForThisStream).

=

PROC [stream: STREAM, char: CHAR];
PFStarCodeProc: TYPE
SetPFStarCodeProc: PROC [stream: STREAM. char: CHAR, codeProc: PFStarCodeProc];

PrintProcs
PrintProcs allow the client to specify an alternative way of printing an object of a specified type. Usually
this is employed to summarize the object in some useful way. For example, a viewer is an object of type
REF ViewerClasses.ViewerRec where ViewerRec is a RECORD consisting of nineteen fields! Printing
this object without a PrintProc would thus produce copious amounts of information. most of which is
probably not of interest to the user who simply wants to see which viewer it is. Instead. we can define
a printproc which prints a viewer showing just its class and name as follows:
ViewerPrintProc: IO.RetPrintProc = {
h: REF REAOONLY ViewerClasses.ViewerRec .. NARROW[ret];
stream.PutF[" {Viewer - class: %g. name: %g}". atom[h.class.flavor). rope[IF
Rope.Length{h.name) # 0 THEN h.name ELSE "(no name)"]];
};
We register this printProc via:
AttachRetPrintProc[reIType: CODE{ViewerClasses. Viewer), retPrintProc: ViewerPrintProc);
Following this. the viewer for the initial UserExec would print as:
{Viewer - class: Typescript. name: Work Area A: Executive}

1S

AttachRefPrintProc: PROC [refl'ype: RTBasic.Type, retPrintProc: RetPrintProc];
Used to register a procedure to be caJ/ed for printing an object of the specified ref type. The
procedure will be caJ/ed with the corresponding ref and a stream. If the class of refl'ype is not ref
or list, raises IO.Signai[NotARefl'ypej.
RefPrintProc: TYPE = PROC [ref: REF READONLY ANY, stream: STREAM. depth: INT
INT ~ 32. verbose: BOOL ~ FALSE];

~

4, width:

Occasionally it is useful to define a printproc for a non-ref TYPE. In this case, the client can define a
PrintProc which is a given a tv d~ribing the corresponding object. Here is an example of a PrintProc
which will print an object of type System.OreenwichMeanTime as a time. rather than a LONG
CARDINAL (which is the type of System.OreenwichMeanTime).

={

TimePrintProc: TVPrintProc
t: System.GreenwichMeanTime:
t ~ LOOPHOLE[AMBridge.TVToLC[tv]]; -- get the "time" out of the tv.
stream.Put[time[t]];
};

AttachTVPrintProc[type: CODE[System.GreenwichMeanTime]. tvPrintProc: TimePrintProc.
canHandleRemote: FALSE];
AttachTVPrintProc: PROC [type: RTBasic.Type, tvPrintProc: TVPrintProc. canHandleRemote: BOOL
.. FALSE]:

More general print proc mechanism for use with any type. The procedure will be called with a tv
for the corresponding object and a stream. IF canHandleRemote is TRUE, the printproc will
also be invoked on remote tvs. otherwise not.

TVPrintProc: TYPE = PROC [tv: RTBasic.TV. stream: STREAM, depth: INT .. 4, width: INT .. 32,
verbose: BOOL .. FALSE]:

Signals and Errors
UserAborted: ERROR [abortee: REF ANY .. NIL, msg: ROPE" NIL]:
the ~andard error to be raised by an application to indicate that the user has aborted. Replaces
UserExec. User Aborted.
EndOfStream: ERROR [stream: STREAM];
auempt to do a getChar at end of stream, or attempt to do a setindex beyond end of stream.
Separate error for convenience.
Error: ERROR [ec: ErrorCode. stream: STREAM]:
ErrorCode: TYPE = {
NotimplementedForThisStream.
a signaL if the corresponding operation does not return a value. e.g. SetEcho. SetLength. etc..
and not resumable. i.e. an ERROR, if the operation does return a value. e.g. GetLength.
IllegalBaclcup,
attempt to do a second backup without having done an intermediate getChar. or attempt to
backup a character other than the one just read.
SyntaxError,
raised by GetBool, GetInt, GetCard. GetRea/. GetRefany.

16

StreamClosed.
raised by file stream operations after Close (except Flush. Reset. Close.)

FileTooLong.
may be raised by Set Length

Badlndex
negative length or index to SetLength/Setlndex, or
negative or too-large index to Unsa/eGetBlock/UnsafePutBlock

};

Signal: SIGNAL [ee: SignalCode. stream: STREAM]:
SignalCode: TYPE
NotimplementedForThisStream.

={

a signaL if the co"esponding operation does not return a value. e.g. SetEcho. Set Length. etc.•
and not resumable. i.e. an ERROR. if the operation does return a value. e.g. GetLength.

ProcedureHasWrongType.
Raised by Implements when via is not of the type of operation. Ifresumed. effect is simply not
to implement Ihe operation.

NotAReIType.
Raised by AttachRejPrintProc when rejType is not of class ref or list. If resumed. effect is
simply not to implement the print proc.

Empty Buffer.
raised by EditedStream when altempt to do an eraseChar and nothing is there.

UnmatchedLeftParen. UnmatchedStringDelim.
raised by GetRefAny if endo/stream reached while reading a list or string. If resumed. the effect
is to supply the missing character. e.g. doing GetRefAny on the rope "(ABC" will return the
liSI (A B C) if the ciient resumes the signal UnmatchedLeftParen.

Rubout,
raised by EdiledStream when a DEL is seen.

Unprintable Value. TypeMismatch. UnknownFormat
raised by PF.

}:
ButferOverFlow: SIGNAL[text: REF TEXT] REft;RNS{REF TEXT];
used by text streams. should return a bigger one. with characters copied over. or else can return
same lext with length reset after having done something with chartacters.

Private and semi-private Types
ValueType: TYPE = {
nUll. atom. boolean. character. cardinal. integer. real. refAny. rope.
string. text, time. tv. type}:
Value: TYPE = RECORD [SELECT type: ValueType FROM
null > :--iULL.
atom => [value: ATOM].
boolean => (value: BOOl].

=

17

character => [value: CHAR],
cardinal => [value: LONG CARDINAL],
integer = >[value: INT],
real => [value: REAL),
refAny => [value: REF READONLY ANY),
rope = >[value: ROPE],
string => [value: LONG STRING],
text => [value: REF READONLY TEXT],
time => [value: GreenwichMeanTime],
tv => [value: RTBasic.TV],
type => [value: RTBasic.Type),
ENDCASE);

=

UnsafeBlock: TYPE
RECORD [
base: LONG POINTER, stanIndex. stoplndexPlusOne: INT --bytes-oj;
used in conjunction with UnsafeGetBlock. UnsafePutBlock described above.
Note: slots in the StreamProcs record are allocated to those procedures that are either so basic to the
operation of a stream that nearly every stream will implement them. or else for which performance
is an issue, such as getBlock.. getIndex. ere. Other generic operations such as Backup, Peek Char,
CheckForAbort, SetEcho, EraseChar, Position, are implemented by storing the corresponding
procedure on the streams propeny list. and looking it up (each time) the generic operation is called.
If the stream (or its backing stream) does not supply an implementation, a default procedure is
supplied which will accomplish the operation. {16}

=

StreamProcs: TYPE
PRIVATE RECORD[
getChar: PRoc[self: STREAM) RETURNS[CHAR) ~ NIL.
endOf: PRoc[self: STREAM) RETURNS[BOOL] ~ NIL.
charsA vail: PRoc[self: STREAM) RETURNS{BOOL] ~ ~IL.
getBlock: PROC[self: STREAM. block: REF TEXT, startIndex: NAT, stoplndexPlusOne: NAT]
RETURNs{nBytesRead: NAT] ~ NIL,
unsafeGetBlock: UNSAFE PRoc[self: STREAM. block: UnsafeBlock] RETURNs{nBytesRead: INT]
NIL.

~

putChar: PRoc[self: STREAM. char: CHAR] ~ NIL,
putBlock: PROC[self: STREAM. block: REF READONLY TEXT. startlndex: NAT. stopIndexPlusOne:
NAT] ~ ~1L.
unsafePutBlock: PRoc[self: STREAM. block: UnsafeBlock] ~ NIL.
flush: PRoc[self: STREAM] ~ ~IL.
reset: PRoc[self: STREAM] ~ NIL,
close: PROC[self: STREAM. abon: BOOL ~ FALSE] ~ NIL,
getIndex; PRoc[self: STREAM] RETURNS [INT) ~ NIL,
setIndex: PRoc[self: STREAM. index: INT] ~ NIL.
otherStreamProcs: LIST OF StreamPropeny ~ ~IL. -- used for specifying the implementation of
optionaL generic procedures. See Implements below.
name: Rope.RoPE
];
StreamProperty: TYPE = REF StreamPrbpertyRecord:
StreamPropertyRecord: TYPE
REF ANY. key: ATOM):

= PRIVATE RECORo[operation. via: PROC ANY RETtJR~S ANY. proc:
18

Character constants. Included for convenience.

=

CR: CHAR
AsciLcR;
SP: CHAR = AsciLsp;
TAB: CHAR = Ascii.TAB;
LF: CHAR = Ascii.LF;
BS: CHAR = Ascii.as;
ControlA: CHAR = AsciLControlA;
ControlX: CHAR = Ascii.ControlX;
FF: CHAR = Ascii.FF;
NUL: CHAR = AsciLNUL;
ESC: CHAR = AsciLESC:
DEL: CHAR = Ascii.DEL;
BEL: CHAR = Ascii.BEL;

MisceUaneous
BackSlashCbar: PROC [char: CHAR, stream: STREAM .. NIL] RETURNS [CHAR);
interpreters \ conventions. e.g. maps \n /0 CR. \t to TAB. etc. Raises SyntaxError if \ not
followed by acceptable character. IF char is in {V.. 9}. then stream must be supplied. or else

synlaxerror. If stream is supplied. two more characters aTe read. If these are digits, returns
corresponding characll;r. otherwise. raises SyntaxError.
Zone: PRIVATE ZONE; -- prefixed zone used for storing stream data. stream procs, etc.
END.

Converting from 3.5
The following are some suggestions about how to conven a program using IO.GetRope or
IO.GetToken to the new scheme of things. These suggestions should cover about 95% of the cases.
Let us consider' GetToken first. A old-style call of the fonn s.GetToken[], which defaults the
second argument. can stay the same. But you might want to consider using GetCedarToleen
instead. especially if what you are doing is reading mesa: GetCedarToken will do more
Cedar-like things for real numbers. quoted literals. quoted text. and the like.
GetRope is only a little more complicated. An old-style call of the fonn s.GetRope[], which
defaults the second and third arguments, can be replaced by the new call s.GetToleen[IDProc].
Note that the new call s.GetToleen[] would also probably do what you want. the only difference
being in the treatment of breale characters: for example, the old s.GetRope[] would read @foo as
a single toleen. while the new s.GetToleen[] would read it as two separate toleens. Similarly,
/indigo/cedar/top/io.df would be read as 8 tokens by the new s.GetToken[], but as only one
token by the old s.GetRope[] and the new s.GetToken[IDProc]. All three of these have the same
effect if your desired tokens are always separated by white space.
Be ware l If you use GetRope, you cannot depend on compile error messages alone to tell you
where changes have to be made. The new GetRope means something quite different from the
old GetRope. but any call to the old GetRope that defaults the second and third arguments will
still look OK to the compiler as a calion the new GetRope. Clients of the old GetRope were
just parsing some ran!i0m input into things separated by white space. A client of the new
GetRope should be in the process of parsing the input stream as a sequence of mesa tokens.
Such a client calls the new GetRope when she expects a rope literal to be the next thing in the

19

input stream. and the call to GetRope either returns the corresponding rope or raises an error.
Thus. all calls to the old GetRope must be changed to GetToken as described in the previous
paragraph, and you must search your program to find them all.
If you have defined your own IO.BreakProcs for use with GetToken. the following recipe should
work: change all of the StopAndPutBackChar and StopAndTossChar to sepr. StopAndIncludeChar
to break. and KeepGoing to other. If you have defined your own IO.BreakProcs for use with
GetRope. you should change KeepGoing to other and everything else to sepr. and then use
GetToken in place of GetRope. However, you might want to rewrite in terms of GetSequence
instead.

20

-- Rope.mesa. "Thick" string definitions
Russ Atkinson, August 27. 1982 11:51 am
-----

Table of Contents:
••• Part I: Basic operations and definitions
••'" Part 2: Extended operations and definitions
."'''' Part 3: Miscellaneous definitions ,

-- A Rope is (nominally) an immutable object containg a sequence of characters indexed starting at 0 for
Size characters. The representation allows certain operations to be performed without copying all of the
characters at the expense of adding additional nodes to the object.
-- NOTE: the bit pallern of the text variant is GUARANTEED to be consistent with the built-in Cedar
type TEXT. although the types will not agree either at compile-time or runtime. This means that one can
use objects of type Text or TEXT interchangeably provided that the runtime type is not examined. and
provided that the compiler can be fooled (via LOOPHOLE). Since REF TEXT is roughly compatible with
Mesa LONG STRING. this is a means for passing Rope refs to Pilot routines that expect LONG
STRING. For short STRING you are on your own (see ConvertUnsafe).
DIRECfORY

Environment USING [Comparison):
Rope: CEDAR DEFINITIONS
-- ••• Part I: Basic operations and definitions ••• --

=

BEGIN

ROPE: TYPE

= REF RopeRep;

NoRope: ERROR;
- signalled if rope is invalid variant
-- usually indicates severe illness in the world
-- Note: BoundsFaull = Runtime.BoundsFault
-- It is raised by many of the Rope operations

Cat: PROC [rI. r2. rJ, r4, n. r6: ROPE'" :-.IlL) RETURNS [ROPE]:
-- returns the concatenation of up to six ropes (limit based on eval stack depth)
- BoundsFault occurs if the result gets too large
Concat: PROC [base,rest: ROPE ... NIL) RETURNS [ROPE];
-- the two-rope (faster) version of Cat
-- BoundsFault occurs if the result gelS too large
Compare: PRoe
[sl, s2: ROPE, case: BOOL .. TRUE] RETURNS [EnvironmenLComparison);
-- based on CHAR collating sequence
-- case = >case of characters is significant
Equal: PRoe [sl, s2: ROPE. case: BOOL .. TReE] RETliRNS [BOOL];
-- contents equality of sl and s2
-- case => case of characters is significant

Fetch: PROC

[b~: ROPE.

index: INT .. 0] RETUR!'IS [c: CHAR]:

-- fetches indexed character from given ropes
-- BoundsFault occurs if index is >= the rope size
Find: PROC [sl. s2: ROPE. posl: INT .. O. case: BOOL .. TRUE] RETURNS [INT];

-- like Index. returns position in sl where s2 occurs (starts looking at posl)
-- returns -I if not found
-- case = > case of characters is Significant
Index: PROC
[sl: ROPE. posl: INT .. O. 52: ROPE. case: BOOL .. TRUE] RETURNS [INT];

-----

Returns the smallest character position N such that
s2 occurs in sl at Nand N >= posl. If s2 does not
occur in sl at or after posl. sl.length is returned.
case => case of characters is significant

[s[mpty: PROC [r: ROPE] RETt;"RNS [BOOL]:
-- returns Length{r]
0

=

Length: PROC [base: ROPE] RETURNS [INT];

-- returns the length of the rope (Length{NILJ

= 0)

Replace: PROC
[base: ROPE. start: INT .. O. len: INT .. MaxLen. with: ROPE .. NIL]
RETURNS [ROPE];

-- returns rope with given range replaced by new
-- BoundsFauit occurs if range invalid or result too long
Size: PROC [base: ROPE] RETURNS [INT];

= Length[baseJ

- Size{baseJ

Substr: PROC [base: ROPE. stan: INT .. 0, len: INT .. MaxLen] RETURNS [ROPE];

-- returns a subrope of the base
-- BoundsFauit occurs if the range given is not valid
-- character conversions (RRA sez: why are they here?)

=

Control: PROC [ch: CHAR] RETt.'RNS [CHAR]
INLINE {
RETURN [IF ch IN A.. 'Z] THEN ch - controlOffset ELSE chI
};

r

Upper: PROC [ch: CHAR] RETL'RNS [CHAR]

=

INLINE {
RETURN [IF ch IN ['a.:z] THEN ch - caseOffset ELSE chI

}:
Lower: PROC [ch: CHAR] RETURNS [CHAR] = INLINE {
RETURN [IF ch IN ['A .. 'Z] THEN ch

+

caseOffset ELSE chI

};

Letter: PROC [ch: CHAR] RETlJRNS [BOOL] = INLINE {
RETURN [ch IN (' A.:ZJ OR $:h IN ('a..'z]]

}:

.

Digit: PROC [ch: CHAR) RETURNS [BOOL)

= I~LINE {
2

RETURN [ch IN ['0.:9]]

}:
-- "''''''' Part 2: Extended operations and definitions "'",'" --

Run:

PROC
[51: ROPE, posl: INT .. O. 52: ROPE. pos2: INT .. 0, case: BOOL .. TRUE)
RETURNS [INT]:

-- Returns largest number of chars N such that sl starting at posl
-- is equal to s2 starting at pos2 for N chars. More formally:
-- FOR i IN (O•• N): sl{posJ + if = s2{pos2 + if
-- If case is true. then case mailers.

Match: PROC [pattern, object: ROPE, case: BOOL .. TRUE) RETURNS [BOOL];
-- Returns TRUE iff object matches the pattern. where the pattern may contain
-- '" to indicate that 0 or more characters will match.
.- If case is true. then case matters.
SkipTo: PRoe (5: ROPE. pos: [NT" 0, skip: ROPE] RETt:RNS [INT]:
-- Return the lowest position N in s such that s{N] is in the skip rope
•• and N >= pos. If no such character occurs in s. then return s.length.
SkipOver: PROe [5: ROPE. pOS: INT .. 0, skip: ROPE] RETURNS [INT);
•• Return the lowest position N in s such that s{N] is NOT in the skip rope
-- and N >= pos. If no such character occurs in s. then return s.length.
Map: PROC
[base: ROPE. stan: [NT .. 0, len: (NT .. MaxLen, action: ActionTypel
RETURNS (BOOL);

•• Applies the action to the given range of characters in the rope
-- Returns TRUE when some action returns TRUE
-- BoundsFault occurs on attempting to fitch a character not in the rope

Translate: PROC
[base: ROPE, stan: INT .. O. len: [NT .. MaxLen. translator: TranslatorType .. NIL]
RETURNS [new: ROPE]:
•• applies the translation to get a new rope
-- if the resulting size> O. then new does not share with the original rope!
-- if translator NIL the identity translation is performed

=

Flatten: PROC (base: ROPE. stan: INT .. O. len: (NT .. ' MaxLen] RETURNS [rext]:
•• Returns a flat rope from the given range of characters
-. BoundsFauit occurs if the resulting length would be > LAST{NAT]
FrornProc: PROC
[len: INT, p: PROC RETURNS [CHAR], maxPiece: INT .. MaxLen] RETURNS [ROPE];
•• returns a new rope given a Proc to apply for each CHAR
FromReIText: PROC [5: REF REAOONLY TEXT] RETURNS [rext];
_. makes a rope from a REF READONLY TEXT
.- causes copying
ToReIText: PROC [base: ROPE] RETURNS [REF TEXT];
-- makes a REF TEXT from a rope

3

-- causes copying
FromChar: PROC [c: CHAR] RETuRNS [fext1;
-- makes a rope from a character
MakeRope: PROC
[base: REF, size: INT, fetch: FetchType, map: MapType .. NIL.
pieceMap: PieceMapType .. NIL] RETURNS [ROPE1:
-- Returns a rope using user-supplied procedures and data
-- the user procedures MUST survive as long as the rope does!
PieceMap: PROC
.
[base: ROPE, stan: INT .. O. len: INT .. MaxLen, action: PieceActionType,
map User: BOOL .. TRUE) RETuRNS [BOOL);
-- Applies the action to the given subrope in pieces (max of I piece/Substr.
-- 2 pieces/Concat, 3 pieces/Replace. either I piece/MakeR ope or use user's
-- routine). Returns TRUE when some action returns TRUE.
-- BoundsFault occurs on allempting to /etch a character not in the rope
ContainingPiece: PROC
[ref: ROPE. index: INT .. 0] RETURNS [base: ROPE. stan: INT. len: INT];
-- Find the largest piece containg the given index such that the result is
-- either a text or an object variant.
-- (NIL, O. 0) is returned if the index is NOT in the given rope
Balance: PROC
[base: ROPE. stan: INT .. 0, len: INT .. MaxLen. flat: INT .. FlatMax)
RETURNS [ROPE);
-- Returns a balanced rope. possibly with much copying of components
-- flat ~ MIN[MAX[j1aI,FlatMax]. LAST[NAT]]
-- len ~ MIN[MAX[/en,O]. Size[baseJ-start}
-- start <0 OR start> Size[base] = > bounds fault
- the resulting maxDepth will be limited by 2+ log2{len/flat}
VerifyStructure: PROC [s: ROPE] RETURNS [leaves. nodes, maxDepth: INT};
-- traverse the structure of the given rope; return the number of leaves.
-- nodes and the max depth of the rope extra checking is performed to verify
-- invariants a leaf is a text or object variant a node is a non-NIL.
-- non-leaf variant shared leaves and nodes are multiply counted
Verify Failed: ERROR;
-- occurs when VerifyStructure finds a bad egg
-- should not happen, of course

-- ••• Part 3: Miscellaneous definitions ••• --

=

controlOffset: SAT
100B;
caseOffset: NAT = 'a - 'A:
FetchType: TYPE = PROC [data: REF. index: IST1 RETURNS [CHAR):
-- type offetch routine used to make a user rope

=

. MapType: TYPE
PROC [base: REF, start. len:

I~l.

action: ActionTypej RETCRSS [quit: BaaL" FALSE];

4

-- type of user routine used to map over a subrope
-- returns TRUE ifsome action returns TRUE

ActionType: TYPE

= PROC [c: CHAR) RETURNS [quit: BOOL .. FALSE]:

-- type of routine applied when mapping
-- returns TRUE to quit from Map

TranslatorType: TYPE

= PROC [old: CHAR] RETURNS [new: CHAR]:

-- type of routine supplied to Translale

=

.PieceMapType: TYPE
PROC [base: REF, start. len: INT, action: PieceActionType]
RETURNS [quit: BOOL .. FALSE):
-- type of routine used to piecewise map over a subrope
.- returns TRUE if some action returns TRUE

PieceActionType: TYPE =
PROC [base: ROPE. Start: INT. len: INT) RETURNS [quit: BOOL .. FALSE]:
.- type of routine applied when mapping pieces
- returns TR UE to quit from PieceMap

RopeRep: PRIVATE TYPE

=

RECORD
[SELECT

tag: * FROM
.
text => (length: :'\IAT, text: PACKED SEQUENCE max: CARDINAL OF CHAR].
node = >[SELECT case: * FROM
substr =>[size: INT, base: ROPE. start: INT. depth: INTEGER].
concat > [size: INT. base, rest: ROPE. pos: INT,
depth: [!It'TEGER).
replace >{size: INT, base. replace: ROPE,
start, oldPos. newPos: [NT, depth: INTEGER].
object >[size: INT. base: REF. fetch: FetchType,
map: MapType, pieceMap: PieceMapType)

=

=

=

ENDCASE)
ENDCASE]:

MaxLen: INT = LAST{INT]:
FlatMax: CARDINAL = 24:
Text: TYPE = REF TextRep; •• the smalL flat variant handle
TextRep: TYPE = RopeRep(text); •• useful for creating new text variants
END.

For those who care, this is the official explanation of the RopeRep variants:
Note: NIL is allowed as a valid ROPE.
Note: ALL integer components of the representation must be non-negative.
SELECT

text

x: x FROM

=> {-- [O.. x.length) is the range of char indexes

-- [O.. x.max) is the number of chars of storage reserved
-- all Rope operations creating new text objects init x.length = x.max

5

-- x.length <= x.max is required
_. the bit pal/em of the lextlS IDENTICAL

10

TEXT and StringBody!!!!

};

node

=>

{SELECf

X:X

FROM

substr =>
{.- [O.. x.size) is the range of char indexes
_. x.base contains chars indexed by [O.. x.size)
_. [O.. x.size) in x ==>[x. starl.. x. start + x.size) in x.base
•• Size{x.base] >= x.start + x.base
};

concat =>
{-. [O.. x.size) is the range of char indexes
_. x.base contains chars indexed by [O.. x.pos)
_. [O.. x.pos) in x = = >[O.. x.pos) in x.base
•• x.rest contains the chars indexed by [x.pos..x.size)
_. [x.pos..x.size) in x = = >[O.. x.size-x.pos) in x.base
- x.pos = Size[x.base] AND x.size = x.pos + Size{x.rest]
}:

replace =>
{-. [O.. x.size) is the range of char indexes
_. x.base contains chars indexed by [O.. x.start). [x.newPos..x.size)
•• [O.. x.start) in x = = >[O.. x.start) in x.base
_. [x.newPos.. x.size) in x ==>[x.oldPos..size[x.base]) in x.base
_. x.rest contains the chars indexed by [x.start.. x.newPos)
-- [x.start.. x.newPos) in x => [O.. x.newPos-x.start) in x.base
-- x.size >= x.newPos >= x.start AND x.oldPos >= x.start
_. x.size • x.newPos = Size[x.basel· x.oldPos

}:

object =>
{-. [O.. x.size) is the range of char indexes
_. x.base if the data needed by the user-supplied operations
_. x.fetch{x.base. i] should fetch the ilh char AND x.fetch # NIL
_. x.map[x.base. Sl, len. action]
- implements Map[x. st. len. action]
_. x.pieceMap[x.base. Sl, len. actionI should behave
•• implements PieceMap[x. Sl. len. action. TRUE]
.- it is OK to have x.map = NIL OR x.pieceMap = NIL
};
ENDCASE
ENDCASE

=> ERROR NoRope}
=> ERROR NoRope};

6

Spelling Corrector/Pattern Completer Edited by Teitelman on November 3, 1982 1l:23 am
DIRECTORY

Generator USING [Handle),
Rope USING [ROPE]

SpeD:

CEDAR DEFINmONS

=

BEGIN

General comments
This interface supports two distinct operations. spelling correction and pattern completion. Spelling
correction involves attempting to transform an unrecognized rope. called the unknown. into a known
rope. which is a member of some computable set of ropes. according to various heuristics. e.g. removal
of doubled characters. transpositions. case errors. etc. For example, correct Com pille to Compile (doubled
character). UsrExecImpl to UserExeclmpl (missing character), ViewerOsp to ViewerOps (transposition).
Pattern completion involves transforming the unknown rope into a known candidate or candidates using
specified transformations. (Currently the only pattern supported is *, which matches any sequence of
characters. In the future. all patterns recognized by the Tioga Edit Tool will be supported.)
There are two ways to call this package. In the first case. the client has in hand an unknown rope and
wants to tind the single correct rope that it specifies. The unknown rope may be a misspelling of some
candidate in the source of candidates (see discussion of sources below). or it may be a pattern which
uniquely specifies the desired candidate, e.g. the user might type R·.profile in a context where a file
name was required. knowing that this is sufficient to be unambiguous. [n order to permit the client not
to have to distinguish these two cases. a single procedure, GetTheOne, is provided. In the case that the
unknown is a pattern, GetTheOne calls the pattern matcher, and if the resulting list consists of a single
candidate. retums that candidate, otherwise GetTheOne retums NIL (i.e. if there are zero or more than
one successful matches). If the unknown is not a pattern, then actual spelling correction will be
performed. In either case, if the user's profile has so indicated as described below, the user will be
informed of the action, or confirmation will be requested before the action is taken.
The second use of this package occurs when the client has in hand an unknown and wants all candidates
that match it, i.e.• a list of ropes. Again. the unknown may be a pattern, or simply a misspelling. For
example, the user might type to the userexec Delete ·.mesaS, or Delete Fooo.mesa. In order to permit
the client not to have to distinguish these two cases. there is a single procedure, GetMatchingList, which
handles both cases. If the unknown is a pattern, GetMatchingList returns a list of all candidates that
match the pattern, if a misspelling, GetMatchingList returns a list consisting of the single correct spelling
(if one is found. otherwise return NIL).

sources of candidates for correction/completion
For both GetTheOne and GetMatchingList, the source of candidates can either be a LIST OF ROPE.
or a generator which produces ROPEs. Generators can be easily created using CreateGenerator as
described below. For both cases. an optional filter predicate can be specified which can be used to select
out a subset of the candidates for consideration.

Confirmation and messages for spelling correction
Spelling correction is divided into three classes in order of decreasing certainty: (1) corrections involving
case errors only, (2) corrections in which all mistakes are accounted for. Le., the only mistakes are doubled
characters or transpositions. e.g.• typing compille or compiei for compile (but not compil), (3) corrections
in which there are some (albeit very few) actual errors. Le.. extraneous characters or omitted characters.

(The case of pattern completion is considered to fall between case (1) and (2).) The user can independently
control which classes of corrections confirmation is required for, for which classes he is to be informed.
or even for which classes of corrections the spelling corrector is enabled at all, by appropriate settings
for the parameters confirm, inform, and disabled (which are packaged into a single record of type Modes,
described below). The value of disabled is an enumerated type {never, some Mistakes, allAccountedFor,
patternMatch, case Error, always}. which specifies that corrections are disabled for that class and all classes
that precede it in the enumerated type. For example, if disabled is someMistakes. then compille will be
corrected to compile, but compil won't, because it has a missing character and hence falls into the class
someMistakes. If disabled is always, then the corrector is turned off completely. Similarly, the value of
inform and confirm specify that informing/confirming is requested for that class and all that precede it
in the enumerated type. For example, -if inform is allAccountedFor, then the user will be informed for
corrections of class allAccountedFor as well as those with someMistakes. If informing is requested. but
no inform procedure was supplied in the corresponding call, then simply do not inform the user.
These parameters can be specified by entries in the user profile for Spell.Confirm, Spell.Inform, and
Spell.Disabled. or explicitly passed in as arguments to GetTheOne and GetMatchingList The default
settings are disabled = never, confirm = allAccountedFor, inform = patternMatch.
For those cases for which confirmation is requested. a timeout and a default value for confirmation can
be specified via user profile entries Spell.Timeout and Spell.DefaultConfirm respectively. The default
,1, meaning never timeout. If confirmation is requested. but no confirming
setting for timeout
procedure has been supplied in the corresponding call. then the behaviour is the same as though the
user rejected the correction, i.e. did not confirm.

=

Types, global parameters
ROPE: TYPE

= Rope.ROPE;

=

SpellingList: TYPE

LIST OF ROPE;

SpeliingGenerator: TYPE = REF SpellingGeneratorRecord;
SpellingGeneratorRecord: TYPE = RECORD[clientData: REF ANY, private: REF
SpellingGeneratorPrivateRecord];
SpellingGener.ttorPrivateRecord: TYPE;
Filter: TYPE

= PROCEDliRE{candidateRope: ROPE. unknown: ROPE] RETURNS [accept: BOOLEAN];

-- true means consider the candidate
AbortProc: TYPE

= PRoe;

responsible for checking for an abort condition. and also doing the abort. For example. when
called from UserExecUtilities.GetTheOne, this procedure would be IF UserExec.UserAbort{execl
THEN ERROR UserAborted:
ConfirmProc: TYPE
BOOl]:

= PROe [msg: ROPE, timeout: INT.

defaultConfirm:.BOOL] RETL'RNS [yes:

output rope to your favorite stream. display in. viewer. whatever. then request confirmation. timeout
is how long to wail, in milliseconds. before returning default. If timeout = .J. then wait forever.
Le. user must confirm.
InforrnProc: TYPE

= PROe [msg: ROPE]:

output to your favorite stream. display in viewer. whatever
CorrectionClass: TYPE

= {never. someMistakes, allAccountedFor. patternMatch, caseError, always};
2

=

Modes: TYPE
REF REAOONLY ModesRecord;
RECORD[
ModesRecord: TYPE
inform. confirm. disabled: CorrectionClass.
timeout: INT. -- In msecs. -/ means never time out
defaultConfirm: BOOL -- the defaull value to be used in case a confirmation limes out. i.e.
TRUE means the correction i~confirmed FALSE means it is rejected

=

1;

defaultModes: Modes:
the modes obtained from the userprofile

GetTheOne, GetMatchingList
GetTheOne: PROCEDURE[
unknown: ROPE.
spellingList: SpellingList.. ~IL.
generator: SpellingGenerator .. NIL. -- if both spellingList and generator are non-NIL. candidates
will be taken from generator until it runs out, and then from speliingList. (If both spellingList
and generator are NIL. then the correction will fail immediate/y.)
abon: AbonProc +- SIL,-- NIL > never abort.
confirm: ConfirmProc .. NIL••- NIL => If confirmation is required act as though user said No.
inform: InformProc .. NIL. _. NIL > no outpuL

=

=

tilter: Filter .. NIL.
modes: Modes .. NIL -- NIL means use values in user profile
]
RETURNS [ROPE];
GetMatchingList: PROCEDURE[
pattern: ROPE.
spellingList: SpellingList .. NIL. -- arguments same interpretation as for GetTheOne
generator: SpellingGenerator .. SIL.
abort: AbortProc +- NIL.
confmn: ConfirmProc .. NIL,
inform: InformProc .. SIL.
filter: Filter .. NIL.
modes: Modes .. NIL
]
.
RETURNS lUST OF ROPE);
Note...
the interface UserExecUtUities provides a convenient way of calling GetTheOne and GetMatchingList
by specifying either an ExecHandle or a Viewer. These procedures will specify appropriate values for
abort. confirm. and inform when calling the corresponding procedures in Spell. e.g. if given an
Exec Handle. a Yes No menu will be posted and the user can confirm either via menu or by typing Y
or N.

Spelling Generators
GeneratorFromProcs: PROC [
initialize: PROCEDURE[self: SpellingGenerator) .. SIL.
generate: PROCEDt:RE [self: SpellingGeneracor) RETt:R~S [candidate: REF ANY), -- must narrow
to ROPE or REF TEXT.
3

terminate: PROCEDURE[self: SpellingGenerator]
clientData: REF ANY 4- NIL
] RETURNS [SpellingGenerator];

4-

:-.IlL. -- to be cailed when finished.

Note...
the value of generate must narrow to ROPE or REF TEXT. If the value narrows to a REF TEXT.
a ROPE will be created only for those candidates that the spelling corrector is going to retain across
calls to generate. This enables generate to return a scratch ref text for inspection. and not have to
allocate a new rope for each candidate it generates.
GeneratorFromEnumerator: PROC [
enumerator: "'OOn [self: Generator.Handle],
clientData: p .. _ a T'r'
] 0 "-+0 Tr [SpellingGenerator];
This procedure is useful when you have a procedure that enumerates. e.g. EnumerateGlobalFrames.
and wish to use it to provide candidates for spelling corrector. Simply write an enumerator procedure
which uses Generator.Produce (see Generator intertace for an example) to produce candidates from
inside of the enumerator. and pass this procedure in as the enumerator argument.

File correction!completion.
GetTheFile: PROC [
unknown: Rope.p 0 ......
defaultExt: Rope.o 0"'" 4- T to
abort: AbortProc 4- T tU
confinn: ConfirmProc 4- T to
inform: InformProc 4- T ICl
modes: Modes 4- TID
] o"-+OTr [correct: Rope.o 0"'" ];
If unknown does not have an extension. defaultExt will be used. If the unknown does not have an
extension and defaultExt is NIL, then unknown will only be compared against files with no extension.
If unknown has an extension. and the extension (minus trailing $ if any) is not one of those on
extensionList (defined below), first attempt spelling correction on extensionlist. If this succeeds, see
if the file name is now correct, and if so. return without doing any directory enumeration. Otherwise.
attempt correction considering only files with the indicated extension.
If the unknown extension does not correspond to one of those on extensionlist, attempt correction
considering files with any extension. i.e. both the root and the extension mayor may not be misspelled.
(Note that this differs from the procedure followed if unknown does not contain an extension. and
defaultExt is specified. in that in this case it is assumed that defaultExt is correct. and only files with
the indicated extension are examined.)
In the event of a successful correction. the informing message will contain an extension only if the
unknown contained an extension. However. the value returned. if non-NIL. will always be the full
name of the file.
Here are some examples:
GetTheFile["Mumble.mesa"] =) look at files with extension mesa for a misspelling of mumble
(becauuse "mesa" is on extensionlist)
GetTheFile["Mumble", "mesa")

=)

same as above, except correction message will say Mumble -)

4

rather than Mumble.mesa

->

GetTheFile{" Mumble.msa"]
as in case 1
GetTheFile("Mumble",

=> correct msa to mesa. see if mumble.mesa exists. and if not. proceed

"m~"]

GetTheFile("Mumble.frob"]
on extensionlist.
GetTheFile("Mumblefrob"l

= >only look at files with extension msa

=>

examine all files with non-Null extensions. because "frob" is not

=> only

look at files with no extensions

GetMatchingFileList: PROC [
unknown: Rope.Q O*e: ,
defaultExt: Rope.Q 0*( .. T dJ
abort: AbortProc .. T 10·
confirm: ConfirmProc .. T 10
inform: InformProc .. T10
modes: Modes .. T10
] Q€-+pTf [files: Olr-O_ po*e:);

me extensions
extensionList: SpellingList;
used in spelling co"ection offile names as described below. initialized 10 (mesa. bcd cm. config.
commands. profile, dt doc. press. style. abbreviations). The user is free to add entries to this list.
AddExtension: PROC [ext: ROPE); _. adds ext to extensionLisl.

Miscellaneous
IsAPattem: PROC [unknown: ROPE] RETURNS(BOOLEANJ;
currently true if unknown contains '" not preceded by a '
END.

5

Edited by Teitelman on November 3. 1982 10:45 am
this interface is intended to be fairly stable. and contains various routines used in and implemented by the
userexecpackage which may also be of general use.

DIRECTORY
Rope USING [ROPE].
Spell USING [SpellingList. SpellingGenerator. Modes. Filter],
UserExec USING [Exec Handle],
ViewerClasses USING [Viewer]

UserExecUtilities: CEDAR DEFINmONS

=

BEGIN

Types

=

ROPE: TYPE
Rope.ROPE:
ExecHandle: TYPE = UserExec.ExecHandle:
Viewer: TYPE = ViewerClasses. Viewer:

Invoking spelling corrector
procedures that invoke the spelling co"ector using execHandle to supply convenient defaults for
infonning, confinning, and aborting. If client has an execHandle in hand. this is the right way to
call the spelling corrector.

GetTheOne: PROCEDURE [
unknown: ROPE,
spellingList: Spel1.SpellingList .. NIL.
generator: Spell.SpellingGenerator .. NIL.
exec: Exec Handle.
viewer: Viewer .. :'lilt," -- either exec or viewer should be supplied. If exec #' NIL then uses
ExecConfirm. otherwise if viewer #' NIL. uses ViewerConfirm.

filter: Spell.Filter .. NIL.
modes: Spell.Modes .. NIL
]
RETURNS [correct: ROPE);
calls Spell. Get TheOne. providing arguments for abortProc. confinnProc. and infonnProc that use
the corresponding ExecHandle. Aborting can be performed by either typing control-DEL when
the exec viewer has the input focus. or using the STOP button. Confinnation is performed via
ExecConjirrn. described below..

GetMatchingList: PROCEDURE [
unknown: ROPE.
spellingList: Spel1.SpellingList .. ~IL.
generator: Spel1.SpellingGenerator .. :'IIIL.
exec: ExecHa.ldle.
viewer: Viewer .. ~IL, -- either exec or viewer should be supplied. If exec #' NIL then uses
ExecConfirm. otherwise if viewer #' NIL. uses ViewerConfirm.

filter: Spell.Filter .. :-.fIL,
modes: Spell. Modes .. ~IL
]
"

RETURNS [matches: LIST OF ROPE);

files
CheckForFile: PROC [tile: ROPE] RETURNS [found: BOOLEAN];
returns TRUE iffile is on the local disk
GetTbeFile: PROC [file: ROPE. defaultExt: ROPE +- NIL. exec: ExecHandle.
modes: Spell.Modes +- NIL) RETURNS [correct: ROPE];
First checks to see iffile (or file.defaultExt) exists. and if not. calls SpelL GetTheFile providing
suitable arguments for abortProc. confirmProc and informProc that use the co"esponding
ExecHandle.
GetMatchingFileList: PROC [tile: ROPE, defaultExt: ROPE +- NIL. exec: ExecHandle. modes:
Spell.Modes +- NIL} RETURNs[matches: LIST OF ROPE};
like GetFileName except always returns a list offiles. If file does not contain a pattern. then
GetMatchingFileList calls GetFileName and returns LIST of that file iffound otherwise NIL. If
file does contain a pattern. calls Spell.GetFileNames. with appropriate arguments for inform.
confirm. and aborL

conrmnation
ViewerConfirm: PROC [msg: ROPE. viewer: Viewer. timeout: INT +- -1. defaultContinn: BOOL +FALSE) RETURNs{BOOLEAN1;
provides a standard way of asking user to confirm an operation in a viewer. The confirmation
message. msg, is printed in the messagewindow. Then. the yes/no button is posted which allows
the user to confirm or reject the co"ection. The user can confirm ahead or reject ahead as soon
as SetupViewerConfirm has been called. (If the implementor wishes to abort the operation sooner
than the call to ViewerConfirm. he can determine if indeed the user has confirmed/denied ahead
using GetConfirmalion defined below. In this case. the implementor must call
FinishedViewerConfirm himseij).
if timeout .# -I. and the user has not confirmed before timeout milliseconds have elapsed then
defaultConfirm is returned as the value of the confirmation.
SetupContirm: PROC [viewer: Viewer):
Call to set up menu. etc.• to enable confirmation ahead.
FinishedConfirm: PROC [viewer: Viewer):
Call to take down menu. etc. Not a part of ViewerConfirm because ViewerConfirm may not be
called in case that confirmation is not required.'
ExecConfirm: PROC [msg: ROPE. timeout: INT +- -1. defaultConfum: BOOL +- FALSE. exec:
ExecHandle) RETURNS[BOOLEAN);
like ViewerConfirm. except (a) the confirmation message is printed in the executive. rather than
the message window. The user can confirm using the keyboard. i.e. type y. n. or del. provided he
has not typed ahead. Typing anything else. e.g. 1, will cause the user to be prompted with his
options and allow him to confirm/reject once again. If the user has typed ahead. he can only
confirm using the menu button. in order that the type ahead not be interfered with.
note that SetupConfirm and FinishedConfirm must be used the same as for ViewerConfirm.

lower level facilities.
Provided mainly in case implementor wants to be able to check whether user has confirmed or denied
ahead e.g. to abort the operation.
GetConfirmation: PROC [viewer: Viewer) RETt;R~S [hasConfirmed. confirmed: BOOl];

2

SetConfinnation: PROC [viewer: Viewer. conflnned: BOOL):
ResetConfinnation: PROC [viewer: Viewer1;

sharing global resources
AcquireResource: PROC (resource: ATOM, owner: ROPE .. NIL, exec: Exec Handle] ;
a package used for sharing a global resource between several processes. If one process has already
acquired the resource. an attempt to acquire it by another process will print a suitable message.
and the process to wait for the resource to be freed. i.e. AcquireResource will not return until the
resource is available. However. while waiting for the resource to be available. the user can abort
via the usual mechanismS. and AcquireResource will raise UserExec.UserAborted.
For example. this package is used to make sure that the compiler is not run Simultaneously by
more than one exec. by having the compiler call AcquireResource[$Compiler] before
attempting to run.
Owner is used in the message that is printed. when waiting. If owner = NIL. it defaults to
(the pname of) resource. owner is typically specified where the same resource is being shared
by several diffirent clients. For example. it is not possible for two commands registered via the
Exec interface (as opposed to UserExec) to run simultaneously. In this case. AcquireResource
is called with resource = $ExecDotW, and owner = name of the command. so that
AcquireResource can print out who it is that owns the resource.
ReleaseResource: PROC [resource: ATOM];
releases the named resource. Nop if not currently acquired.

miscellaneous
RopeSubst: PROC [old. new. base: ROPE, case: BOOLEAN" FALSE, allOccurrences: BOOLEAN ..
TRUE) RETURNs(value: ROPE]:
if old is not found in base. then value base.
if a/Joccu"ences THEN substitute for each occurrence of old. otherwise only for first
RopeFromFile: PROC [fIle: ROPE] RETURNS [value: ROPE] :
Returns contents offile as rope. or raises IO.Error FileNotFound.

=

END. - UserExecUtilities

3

UserProjile.mesa: Edited by Teitelman on December 16. 1982 11:59 am
OIRECfORY
Rope USING [ROPE]

UserProrIle:

CEDAR DEFINmONS

= BEGIN

Overview
UserProfile is a package for reading infonnation from the disk file  .profile. or if none exists.
User.profile. The purpose of the profile is to allow personalized tailoring of the system. The current
catalogue of ways the Cedar can be parameterized may be found in the file UserProtile.doc.
Entries in the user's profile are of the form: : RETURN. where value is either (1) a BOOLEAN,
(2) an INT. (3) a TOKEN. or (4) a ListOITokens (for more details. see UserProfile.doc). When Cedar is
booted. roUedBack. or any file whose extension is "profile" is edited. the profile is parsed and a data
structure which describes the information that was found in the profile is constructed Comments
(indicated using the standard "-." convention) can appear anywhere in the profile and will be ignored.
The parsing will also ignore extra spaces or blank lines. Any errors or anomalies discovered when parsing
or accessing the profile will cause diagnostics to be printed to the file UserProfile.1og. The user will be
informed that problems have been encountered via the Message Window. In no case however will the
system break.
Access to individual profile entries via the procedures below is relatively efficient, since this access does
not require any file reads or parsing. Therefore. many simple applications can simply read information
from the profile as needed However. some applications derive complex data structures from the profile
(consider the effect of the "UserCategory" profile entry on the state of Tioga). and hence cannot afford
to interrogate the profile whenever some information derived from it is used Such an application must
register a ProfileCbangedProe and perform all of its profile interrogations from within this procedure.
This guarantees that the corresponding values will be updated whenever the profile changes. The
ProtileCbangedProc will be called when it is first registered. whenever the system is booted or rolled-back.
or whenever a file with extension ".profile" is saved Fine point:
Since the ProfileChangedProc for an application is not called from that application's process(es). the
application must explicitly synchronize its reads to variables derived from the profile with the
ProfileChangedProc's writes to these variables. This may involve adding a monitor to an application that
previously did not require one.

Accessing the ProrIle
The procedures described below all read simple results from the value field given a key. The default
value is passed in as an argument so that the client can specify what the procedure returns should the
value be absent or malformed. or the protile be missing.
Boolean: PRoe [key: Rope.RoPE, default: BOOLEAN" FALSE] RETURNS [value: BOOLEAN]:
Number: PROC [key: Rope.ROPE. default: INT .. 0] RETURNS [value: INT];
Token: PRoe [key: Rope.RoPE. default: Rope.RoPE .. NIL] RETlJRNS [value: Rope.ROPE]:
returns next token following :. Le. efftctively does an IO.GetRope{IDBreakj. If the jirst
character encountered is ': then reads everything to the next matching ". and returns this as a
Single rope.

ListOrrokens: PRoe [key: Rope.ROPE. default: LIST OF Rope.ROPE .. :'IIIL] RETURNS [value: LIST OF
Rope.ROPE];
For example.

if your profile contains:

PreRun: Clock. bed. VersionMapOpsImp1.bed. HideousKludge.bed. -- just until 3.4 -- WalnutSend.bed
then ListOrrOkens["PreRun"] will return ("Oock.bcd", "VersionMapOpsImp1.bcd",

"HideousKludge.bcd". "WalnutSend.bcd).
Note that if the user profile contains Key:{cr}. then ListO/Tokens["key". default] will return NfL.
not default. i.e. the entry for "key" is neither malformed or absent.

Line: PRoe [key: Rope.RoPE. default: Rope.RoPE .. NIL] RETUR:'IIS [value: Rope.RoPE];
Like ListO/Tokens except returns the result as a single rope, e.g. for above example. the value of
Line("PreRun"] would be "Clock.bcd VersionMapOpsImp1.bcd HideousKludge.bcd

WalnutSend.bcd".
GetProfileName: PROC RETURNS [Rope.ROPE);
returns name offile used to build the profile. i.e. eilher (YourName).profile, or UserName.Profile.
Returns NIL if no profile.

Registering procedures for accessing the profile
As mentioned above. if the result of acceSsing the user profile is going to be cached by the client, then
the profile should not be accessed directly, but via a ProtileChangedProc which has been registered with
CallWhenProtileChanges. This guarantees that the corresponding values will be updated whenever the
profile changes.
In other words. rather than writing:
ClientCheckpointAag: BOOt .. UserProfile.Boolean("ClientCheckpoint". TRUE];
the implementor should write:

ClientCheckpointAag: BOOt;
Init: ProfileChangedProc = {ClientCheckpointAag .. UserProfile.Boolean("ClientCheckpoint", TRUE]:
UserProfile.CallWhenProfileChanges(lnit);
CallWhenProtileChanges: PRoe (proc: ProfileChangedProcj;
proc is called when it is first registered with reason = firstTime.
ProfileChangedProc: TYPE = PRoe [reason: ProtileChangeReason);
ProfileChangeReason: TYPE = {firstTime. rollBack. edit};
\

ProfileChanged: PRoe [reason: ProfileChangeReason];
Calls all of the ProfileChangedProcs. This procedure is automatically called after a rollback.
whenever the UserExec.Login is called, or whenever the a file with extension 'profile' is saved by

'-.

\

tioga.

GetErrorLog: PRIVATE PROC RETURNS [fileName: Rope.RoPE];

if there were any errors reported, this closes the stream and returns the name of the file.

2

UserProfile.Doc. documentaJion for UserProfile options
last edited by reitelman. April 19. 1983 11:45 am

A number of components of Cedar permit the user to parameterize their behaviour along certain
predefined dimensions via a mechanism called the User Profile. Whenever the user boots or rollsbactc.
his user profile is consulted to o·"tain the value for these parameters. This operation is performed by
consulting a fIle whose name is .profile. e.g. McGregor.Profile, or if no such file exists, a
default profile User.ProfIle. The entries in this profile are of the fonn : RETURN. where key
is a sequence of alphanumerics or :s (case does not matter) and value is either (1) a BOOLEAN, (2) an
INT. (3) a TOKEN, which is a rope consisting of either a sequence of characters delimited by SP. CR, TAB,
Comma, Colon. or SemiColon. or, in the case that the first character is '''. the sequence of characters
up to the next matching "', or (4) a ListOtTokens. Comments can appear at any point in the profIle, and
are ignored.
.
This fIle defines and documents the entries in the user profile. Each entry is presented as though it were
a mesa declaration. although of course it is not. Comments following the entry explain the effect of that
entry.
In all cases, if the corresponding entry does not appear in your personalized user profile (or the default
user profile), the value of the corresponding parameter is the indicated default. If you want to specify
some value other than this default. or want to include the corresponding entry along with its default in
your profile just so that you can see at a glance what settings are in effect, simply include it in your own
profile. Unless otherwise specified, changing or adding an entry should be "noticed" as soon as you click
the Save menu button.

Viewers/Tioga related parameters
UserCategory: TOKEN +- Intennediate;
affects which Tioga commands are turned on. Categories are {Beginner. Intennediate. Advanced}.
You need Advanced to enable the various commands for manipulating nodes. Will not be noticed
until you bOOL
DefaultFontFamily: TOKEN +- Tioga:
the name of the default font to use for all viewers. Will not be noticed until you boot. Any changes
to this entry will not be noticed until the next time you bool. (Consull a wizard before changing
this to anything other than Tioga.)
DefaultStyle: TOKEN +- Cedar;
the name of the default style.
ExtensionStyles: ListOITokens +- NIL:
specifies the default style to be used with documents that do not explicitly name a style. The style
is determined by the extension in the file name. The entry is of the form 
  .
DefaultTiogaMenus: ListOITokens +- places:
specifies which menus. if any, should automatically be displayed when you create a new Tioga
/
viewer, e.g. places levels. none means no menus will be added. i.e. only the "Clear Reset.. " menu "
will be displayed.
OpenFirstLevelOnly: BOOL +- FALSE:
If set to true, documents will be opened with only their first level showing.
•

I

DefaultFontSize: [NT to 10:
Note: strike fonts only come in a jew sizes. Any changes to this entry will not be noticed until the

/
I'

next time you boot. (Consult a wizard before changing this to anything other than Tioga.)

PreLoad: ListOITokens .. :-.IlL:
a sequence offiles for which viewers are automatically opened when you boot. Many profiles have
"TiogaDoc.tioga" here. which will open a viewer on the documentation for Tioga. Any changes to
this entry will not be noticed until the next time you boot.

TiogaTlP: TOKEN .. Default;
defines your user interface to Tioga. Value is a sequence of TIP files or the special token
"Default", which will be layered so that operations defined in earlier tables take precedence over
those defined later. Any changes to this entry will not be noticed until the next time you boot. or
you invoke the userexec command ReadTiogaTipTabies.

SourceFileExtensions: ListOITokens .. mesa tioga df cm config style:
This determines what extensions Tioga should look for in opening files.

ImplFileExtensions: ListOITokens .. mesa cedar;
This determines what extensions Tioga should look for in opening files requested via GetlmpL

ScroliTopOtTset:

INT ..

3;

When you do a Find command you may want to see a few lines in front of the match to give you
more context. This parameter tells Tioga how many extra lines to want in such situations.

ScroliBottomOtTset:

INT ..

5;

.

When you are typing and the caret goes to a new line just off the bottom of the viewer. Tioga will
automatically scroll the viewer up a little to make the carel visible again. This parameter
controls how far up to scroll: a big number causes larger but less frequent glitches.

SelectionCaret: TOKEN .. balance;
"balance" means place the caret at the end nearer the cursor when the selection is made. Some
people have requested to have the caret always placed at one end or the other. hence this profile
entry. The choices are {before, after. balance}.

YSelectFudge:

INT ..

2;

This lets you specify a vertical displacement for making selections. Tioga behaves as if you had
pointed this number of points higher up the screen so that you can point at things from slightly
below them.

UnsayedDocumentsCacheSize:

INT ..

4;

controls the number of unsaved documents the system will remember.

ShowUnsayedDocumentsList: BOOL .. TRUE;
If true. a viewer will be created holding an up-to-date list of the unsaved documents that can still
be reloaded.
.

EditHistory:

INT ..

20;

Tioga keeps a history of the specified number of edit events. The EdttHistory tool will let you undo
these events.

EditTypeScripts: BOOL .. TRUE:
If true. typescripts behave the same as Tioga documents when the selection point is not at the end
of the document. Le. DEL means delete. t X means exchange. and typein is simply inserted at the
selection point. Thus. you can edit material that has· been typed but not yet read. i.e. anything up
to the last carriage return. and the edited characters will be what the client program sees.

2

However. this also means that you cannot ~imply point anywhere in the typescript and start
typing and have the material automatically be inserted at the end of the document the way it
used to (it will be inserted where at the selection point. the same as when editing a Tioga
document). Note that a convenient. single keystroke way of moving the selection to the end of the
document is to use the NEXT key (Spare2).

Printer related options.
Note: most of the following can be overriden on the command line invoking the print command using
appropriate switches.

Hardcopy.PressPrinter: TOKEN" NIL:
the printer where your output gets sent. e.g. Clover. Used by both print and tseller.
Hardcopy.PrintedBy: TOKEN" SIL:
if omitted. defaults to name of cu"ently logged-in user
Hardcopy.Landscape: BOOL .. TRl,;E:
TRUE means print in landscape mode. FALSE in portrait mode
Hardcopy.Font: TOKEN" IF Hardcopy.Landscape THEN "Gacha6" ELSE "GachaS";
Hardcopy.Columns: INT .. IF Hardcopy.Landscape THEN 2 ELSE 1;

,

Hardcopy.Tab: INT .. 8:
the number of spaces between tab stops

Hardcopy.TemporaryPressFiles: BOOt .. FALSE:
Temporary Press Files are automatically deleted as soon as they are successfUlly sent to the
printer. This profile parameter controls the initial setting when a new /Setter tool is created It
can be changed on a tool by too/ basis using a button in the tsetter tooL

UserExecutive options
RegisteredCommands: TOKEN .. NIL;
the token is interpreted as either (a) a sequence of commands that you want the UserExecutive to
recognize in addition to the ones that it already knows about. or (b) the the name of a file
containing those commands. Each command must be on a separate line. and the line must be of
the form: CommandName Explanation name-ofbcd where Explanation is a rope delimited by
'''s. and name-ofbcd is optional and defaults to the same as CommandName. (Note that any"
appearing inside of the rope must be preceded by a \ or it would terminate the rope. Similarly.
any \ to be included in the rope must itself be preceded by a \.)
Example:
RegisteredCommands: "
Bringover '''Retrieves tiles from a remote server to your local disk. using a specified df
tile.\"
Chat '''Creates a Chat viewer. i.e. a , \ '"terminal''''' for communicating with Maxc. Ivy.
Ernestine. etc.'"
JaM '''Creates a JaM typescript. '"

3

Print \"Sends either a plain-text file or a press file to a printer.\"
SModel \"Stores files on remote servers using a specified df file.\"
VerifyDF \"Verifies that the contents of specified df file are consistent.\"
WalnutSend \"Creates a viewer for sending mail.\"

.

Note: all of the above are already registered by virtue of their being in the file
RegisteredCommands. catalogue. which is on your disk. Use this profile entry to register new, or
esoteric commands.

CommandsFrom: TOKEN" NIL;
either (a) a sequence of command lines to be executed by the UserExecutive. exactly as though
you had typed them in. or (b) the name of a jile which contains the commands. The commands
can appear directly in the user profile. e.g.

CommandsFrom: ..
WalnutSend - loads starts. and calls WalnutSend. i.e. brings up the little envelope
Alias DoBoth (file) compile file ': bind file
or this entry can be the name of a file which contains the commands. e.g.

CommandsFrom: Teitelman.commands
Note: any changes to this entry will not be noticed until the next time you boot.

ShowStatistic:s: BOOL .. FALSE;

if true. causes userexeculive to print out computation time. number of words allocated. and page
faults for each command that it executes.

CreateSessionLog: BOOL" TRUE;

if true. causes userexeculive to create a log file. called Session.log, in which is written all of the
material that appears in each of the workAreas. suitably bracketed so you can tell which is
which. as well as a record of all files that were saved

CreateWorkAreaLogs: BOOL" FALSE;

if true. causes userexecutive to create log files for each work area. of the form WorkA reax. log.
CreateChangesLog: BOOL .. TRUE;

if true. causes userexecutive to create log file containing record of all changes made to files. Each
time a file is saved. its name. date. and changelog entry, if any, is written to this log (requires
NewStujJ1mpl to be loaded).

WhenLogFileExists: TOKEN" "Rename":

.....

,
"".,

Determines what happens when a log file already exists. Value is either {Rename, Append.
OverWrite}. Rename means rename the existing log file by appending a $ to its name. Append
means append the new log file to the existing one.

Spelling corrector options
Spell.inform:

TOKEN" allAccountedFor:
what classes of corrections to inform the user about

4

SpelLconfirm: TOKEN" allAccountedFor:
what classes of corrections to request confirmation before performing
Spell.disabled: TOKEN" never;
what classes of corrections not to do at all
the values of the previous three entries are spelling correction classes. which are drawn from the
following set: {never, someMistakes, allAccountedFor, pattern Match , caseError, always}.
The value of the parameter specifies that the corresponding operation should be performed for
the indicated class. and all of those that precede it in the enumerated type. For example. if
disabled is someMistakes. then compille will be corrected to compile. but compil won't.
because it has a missing character and hence falls into the class someMistakes. If disabled is
always. then the corrector is turned off completely. Similarly. the value of in/arm and confirm
specify thaI informing/confirming is requested for that class and all that precede it in Ihe
enumerated type. For example. if inform is aUAccountedFor. then the user will be informed for
corrections of class aUAccountedFor as well as those with someMistakes. With the above
defaults. the system will correct compille to compile without confirmation (since it is of class
allAccountedFor), but tell you what it has done. will correct compil 10 compile but ask you to
confirm first (since it is of class someMistakes). and correct rttypes to RTTypes without asking
you orteiling you (since it is of class caseError). For more details. see the spelling interface.
spell.mesa

Spell.timeout: [NT .. ~ 1;
number of milliseconds to wail before timeout on a proposed correction. ~ I means never timeout.
Spell.defaultCoofirm: BOOL .. FALSE;
what to return if a proposed correction involves confirmation and you ailow the correction
timeout TRUE means ok to do the correction. FALSE means not

10

Spell.giveUpAfter: INT .. -1;
number of milliseconds to attempt correction before giving up.
SpelLassumeFirstCharCorrect: BOOL .. FALSE;
For use in context of correcting a where there is a large potential set of candidates. e.g. misspelled
frame name. file name. but this set of candidates can be structured so that only those candidates
with the same first character as the one that was misspelled will be considered. Note that it is
always the case that these candidates are considered first. This parameter simply says if you don't
find the correct spelling there. whether or not to search the other candidates.
SpelLviewerSpeliDisabled: BOOL .. FALSE;
If TRUE. then no correction for mistyped filenames in context of loading or opening'a viewer.

Compiler/Binder
Compiler.IconicLogs: BOOL .. FALSE:
If TRUE. tells userexecutive to always create compiler/binder logs iconic. regardless of whether or
not the input focus is in the executive in which the compilation has taken place.
Compiler. Blink Logs: BOOL .. TRUE:
If FALSE. tells userexecutive never to blink compiler/binder logs.
Compiler.SeparateLogs: BOOL .. FALSE:
If TRUE. tells userexec to create separate logs and viewers on these logs for each file that contains
5

errors or warnings. Moreover. these viewers are created as soon as the errors are encountered.
Thus. if you compile a sequence of files. and the first file contains errors. you can begin working
on those errors before the compilation finishes.
Compiler.AutoSave: BOOL ... FALSE:
If TR UE. when the user attempts to compile a file which has been edited but not saved. causes
the system to automatically save the file without asking the user.
Compiler.5witches: TOKEN ... ~IL:
default switches for compiler. Note that /-g can be used to cause separate compiler error logs for
each file compiled.
Binder.Switches:' TOKEN'" NIL:
default switches for binder

Walnut and Squirrel
Walnut.ReplyToSelf: BOOL ... FALSE:
if TRUE. causes walnut to always supply a Reply- To: field.
WalnutlnitialActiveRight: BOOL ... TRUE;
true says to bring up the active message set on the right column. false on left.
WalnutlnitialActiveOpen: BOOL ... FALSE:
true says open a message set viewer on Active.
WalnutlnitialActiveIconic: BOOL ... FALSE:
if true and InitialActiveOpen = TRUE, then the Active message set viewer is opened as an icon.
Walnut.MsgSetButtonBorders: BOOL'" FALSE:
if TRUE. puts borders around the MsgSet buttons in the control window.
Walnut. WalnutSegmentFile: TOKEN ... "Walnut.Segment":
value is the name of the file to be used for the walnut data base. Primarily to ai/ow, users to
experiment with alpine.
Walnut.WalnutLogFile: TOKEN'" .... ;
Name of log file. If not specified. then derived from Walnut WalnutSegmentFile by changing
extension to .DBLog.
Squirrel.SquirrelWindow: BOOL ... FALSE;
TRUE if you want the squi"el window on the screen.

miscellaneous
AutoCheckpoint: BOOL ... FALSE:
TRUE says to automatically make a checkpoint when you boot.
ClientCheckpoint: BOOL ... TReE;
If TRUE. puts a CheckPoint button at the top of your screen.
WorldSwapDebug: BOOL ... FALSE:

6

TReE means go to worldswap debugger on an uncaught signal.

AutoldleTimeout:

INT ..

20:

if you leave your terminal unattended for more than the corresponding number of minutes. is
equivalent to pressing the "Idle" bUIlOfL 0 means never time oUL

FileSwitches:

TOKEN .. NIL:

argument is interpreted as the switches (sequence of characters) to be supplied when booting using
the "File" button.

Edited on December 2. /982 1:10 pm. by Teitelman
changes to: OpenFirstLevelOnly. UnsavedDocumentsCacheSize. ShowUnsavedDocumentsList.

SourceFileExtensions
Edited on December 9. 1982 12:59 pm. by Teitelman
changes to: WalnutlnitialActiveOpert. Walnut"InitialActive[conic. Walnut WalnutOnlyUser
Edited on February 9. /983 3:10 pm. by Teitelman
changes to: Create Log Files
Edited on March 4. 1983 11:59 am. by Teilelman
changes to: Walnut. Walnut. Walnut. Walnut. Squirrel
Edited on March 10. 19835:22 pm. by Teitelman
changes to: Hardcopy
Edited on March 13. 19832:01 pm. by Teitelman
changes to: CreateChangesLog. Spell. WorldSwapDebug
Edited on March 25. 19834:51 pm. by Teitelman
changes to: EditTypeScripts. CreateSessionLog
Edited on April 19. 1983 JJ:45 am, by Teitelman
changes to: CreateSessionLog. CreateWorkAreaLogs. CreateChangesLog. WhenLogFileExists

7

Last edited
By

by Mitchell on December 20, 1982 4:33 pm
by vanLeunen on June 6, 1983 10:49 pm

Jim Mitchell

Annotated Cedar Examples
Version 3.5.2

XEROX -

FOR INTERNAL USE ONLY

Abstract This section contains a set of examples of Cedar programs for your reading pleasure. These
are actual programs that can be run. used as parts of other programs. or treated as templates to be edited
into new programs with similar structures.

This memo is probably out of date if it is in hardcopy form. It documents Release 3.5.2 of Cedar.
December 1982.

[If you are reading this document on-line in Cedar. try using the Tioga Levels and Lines menus
to browse through the top few levels of its structure before reading it straight through.)

2

Annotated Cedar Examples: Contents
1. A simple, but complete program

1.1 SimpleExampie.mesa -

Rick Cattell

1.2. Notes for SimpleExample

3

2. A general sort package for lists
2.2. ListSortRef.mesa - Mark Brown
2.3. Noles for LislSortRef interface
2.4. OnlineMergeSortReflmp/.mesa -

Mark Brown

2.5. Noles for OnlineMergeSortReflmp/

3. A sample tool using Viewers
3.1. Samp/eTooLmesa - Scoll McGregor
3.2 Notes for Samp/eToo/

4. An evaluator for FUN, a functional programming language
4.1 FUN. mesa - Jim Mo"is
4.2 Notes for FUN

4

o.

Introduction

This section contains a set of four examples of Cedar programs for your reading pleasure (it assumes
you are already familiar with the Cedar Language. either by previous osmosis or by having read the
Cedar Language Overview). These are actual programs that can be run, used as parts of other programs.
or treated as templates to be edited into new programs with similar structures.
For each example there is a short discussion of its purpose followed by the program.
After each program there is a set of notes to help in reading it The notes are keyed to the programs
by the numbers in parentheses to the right of some lines, e.g.• as "--(note 5.1)".
You will also find references to lines in the program from the notes. as. e.g.• "[line 1.1]". The
corresponding lines in the programs are marked as, e.g .• [1.1).
When Mesa identifiers appear in the notes. they are displayed in italics to make reading easier: e.g.•

ReverseName. CommandProc.
You should read the examples for understanding and use the notes as references. rather than the
other way round.

5

1. A simple. but complete program
This first example shows how to write a simple. but complete Cedar program. It illustrates a number
of features of the Cedar language and system as well as some of the stylistic conventions used by Cedar
programmers (see the Style section):
It uses Cedar ROPES for string manipulation:
It uses the 10 interface to create and use terminal input and output streams:
It registers procedures with the Cedar User Executive (UserExec) so that you can invoke them like
builtin commands of the UserExec:
One of these registered commands creates a process by means of a FORKed procedure call each time
you invoke it from the UserExec:
The process then creates a simple Viewer with which you can interact to calculate the values of
simple expressions.
The program can be run by typing "Run SimpleExample" to the Cedar UserExec. All it does at
that point is register two commands with the UserExec.
The first command. ReverseName. simply types your logged-in user name backwards in the UserExec
typescript (unless you are Bob Taylor).
The second command. Calculate. creates a separate viewer into which you can type simple expressions
of the form "constant
+" I "- ") constant)·". terminated by a carriage return. It will display the
value of the expression. If you wish. you can create multiple calculator viewers by giving the Calculate
command to the UserExec more than once.

«"

6

1.1 SimpleExample.mesa -

Rick Cattell
(note 1.1)

-- File: SimpleExampJe.mesa
-- Last edited by: Mitchell on December /6. /982 2:32 pm

DIRECfORY
[0 USING [char, Close, Create ViewerStreams. Error. GetChar. GetInt, Handle. IDBreak. int,
PeekChar. PutF, PutFR. Reset. rope. SkipOver].
Process USING [Detach].
Rope USING [Cat, Equal. Fetch. Find. FromChar. Length. ROPE. Substr. Upper].
UserExec USING [CommandProc. GetNameAndPassword. RegisterCommand);
Simp leExample: CEDAR MONITOR
IMPORTS 10. Process. Rope. UserExec

--(note 1.2)
--(note 1.3)

=

BEGIN
ROPE: TYPE
Rope.ROPE;
windowCount: INT .. 0; -- a count of the number of calculators on the screen

=

ReverseName: UserExec.CommandProc .- [exec:
[ok: BOOLEAN

#0

TRUE, msg: ROPE

#0

--(note 1.4)

UserExec.ExecHandle. clientData: REF ANY #0 NIL] RETURNS
NIL] -

=

(note 1.5)
BEGIN
userName: ROPE .. UserExec.GetNameAndPassword[ ].name:
execStream: 10.Handle .. exec.out:
-- exec is an arg to ReverseName
backwordsName: ROPE .. ~IL;

-- Reverses the user's login name and prints it out in the exec window.

--(note 1.6)
(note 1.7)

-- Remove ".PA" ifit is on the end of the user name. and check for user name Taylor.

dotPos: INT = userName.Find[". "];
--(note 1.8)
IF dotPos#·1 THEN userName .. userName.Substr{O. dotPos);
IF userName.Equal[s2: "Taylor", case: FALSE] THEN execStream.PutF["Hi. Bob\n"];
-- Now reverse the name: convert chars to upper cases and concatenate them in reverse order

FOR i: INT DECREASING IN [O.. userName.Length[ ]) 00
backwordsName .. backwordsName.Cat[
--{l.l) (note 1.9)
Rope.F romChar[Rope.Upper[ userName.Fetch[i]]]]
ENDLOOP;
execStream.PutF["Your user name backwards is: %g\n", Io.rope[backwordsName)];
--(note 1.10)
END:
MakeCalculator: ENTRY UserExec.CommandProc = BEGIN

--(note 1.11)

-- Puts up a calculator window.

title: ROPE;
windowCount .. windowCount + 1:
title .. IO.PutFR[.. Adding machine number %g". IO.int[windowCount]]: --(note 1.12)
TRUSTED {Process.Detach[FoRK Calculate[title]]}
--(note 1.13)
END;

Calculate: PRoc[title: ROPE]

= BEGIN

-- Creates typescript window separate from UserExec with given title.
-- Uses 10 procedures to read an, integer expression from the typescript and print its value.

opChar: CHAR;
number: INT:
answer: n. .-r;
in. out: IO.Handle:
[in: in. out: out] .. IO.CreateViewerStreams[title];

--(note 1.14)

7

DO

-- Read an expression. terminated by a CR:
ENABLE 10.Error =>
--(note 1.15)
IF ec SyntaxError THEN {
in. Reset( ];
out.PutF["\nIncorrect input. Please retype the expression.\n\n"];
LOOP}
ELSE EXIT;
opChar ~ '+:
-- first integer is positive
answer ~ 0;
-- initialize sum to zero
out.PutF["Type one or more integers separated by + and - and terminate with CR to
compute value:\n"];

=

00 -- Read an integer and an operator. skipping leading blanks in both cases

number ~ in.GetInt( ];
SELECT opChar FROM
'+ => answer ~ answer + number:
'. => answer ~ answer - number:
ENOCASE => {
out.PutF["I1legal operator (%g). Please retype the expression.\n\n",
10.char[opCharD;
EXIT};

IF in.PeekChar[ ] = '\n THEN GO TO NextLine: -- the normal way out
in.SkipOver[IO.IDBreak];
opChar ~ in.GetChar[ ];
REPEAT
NextLine = > {
[ ] ~ in.GetChar[ ]; -- toss C R
(note 1.16)
outPutF["\nThe answer is: %g.\n\n", Io.int[answer]] };
ENDLOOP;
ENDLOOP;
END;
-- Start code registers a Calculate and ReverseName command. which must be invoked/or this
program to do anything:

UserExec.RegisterCommand[
--(note 1.17)
name: "Calculate", proc: MakeCalculator, brietDoc: "A simple adding machine"];
UserExec.RegisterCommand[
name: "Rev:erseName", proc: ReverseName, brietDoc: "Reverses your user name"];
END.
CHANGE LOG

--(note 1.18)

Created by Cattell on 21-Apr-82 13:55:09
Changed by Cattell on May 25, 1982 10:58 am
-- added use 0/ RegisterCommand to fire up a Calculator viewer instead 0/ creating it when program
first run.

Changed by Mitchell on August 11, 1982 5:00 pm
-- changed main loop o/Calculate to co"ectly catch 10.E"or when Destroy menu button invoked
Edited on December 16, 1982 2:22 pm. by Mitchell
changes to: DIRECTORY 10. --CreateTTYStreams --) CreateViewerStreams, --,
UserExec.RegisterCommand[moved out.PutF to NextLine exit o/inner loop so it doesn't print
out an answer when an inco"ect operator is typed

8

1.2. Notes for- Simple Example
(1.1) These two stylized comments give the name of the module. who last edited it, and when (and

Tioga contains features that will automatically update the last-edited time when a save is done
- see the Tioga Editor chapter of this documentation). The section on Style contains a list of
the stylistic conventions recommended for Cedar programmers.
(1.2) A '-fONITOR module is like a PROGRAM module except that it can be used to control concurrent
access to shared data (note 1.11).
(1.3) SimpleExample imports four interfaces. 10. Process. Rope. and UserExec because it needs to
call procedures defined in those interfaces.
(1.4) Since ROPES are so heavily used in the program. an unqualified version of the type name is
generated simply by equating it with the type in the Rope interface. This is a commonly
used means for making one or a small set of names from interfaces available as simple
identifiers in a module.
(1.5) The argument and returns lists given here as comments show the type of
Userexec.CommandProc: they were inserted semi-automatically using Tioga's "Expand
Abbreviation" command to assist in reading the program. ReverseName has this type so that
it can be registered with the Cedar UserExec as a command that a user can invoke by typing
a simple identifier (note 1.18).
The ReverseName procedure prints out the user's login name in reverse order. It strips off
the registry extension (e.g. ".PA") and does something different for user name "Taylor".
(1.6) GetNameAndPassword has the type
PROC RETURNS [name, password: ROPE]
userName is initialized to the value of the "name" return value from
UserExec.GetNameAndPassword by qualifying the call with ".name".
(1.7) In the object-oriented style adopted by many Cedar interfaces. the object type provided by an
interface, Foo, is conventionally named Foo.Handle.
(1.8) The notation. userName.Fint:(... ,,], is interpreted by the compiler as follows: Look in the interface
where the type of userName is defined (Rope in this case) and look for the procedure Find.
whose first parameter is a ROPE. Generate code to call that procedure, inserting userName at
the head of its argument list Thus userName.Fin4...."] is an alternate way of saying
Rope. Fin4.userName. "."]. The userName.Find form is called object-style notation, and the
Rope.Find form is called procedure-oriented notation.
Note also that dotpos is constant over the scope of its declaration. so it is initialized with .. = ..
to prevent any subsequent assignment to it.
(1.9) Find. Fetch. Equal. Substr. Cat. and FromChar are all procedures from the Rope interface. The
program uses object-style notation for those calls whose first argument is a nameable object,
e.g., userName. and procedure-oriented notation otherwise. [line 1.1] is a good example of
both. Here it is. spread out to exhibit the two forms:

backwordsName ..
backwordsName.Cat{
Rope.FromChal{
Rope.Uppel{
userName. Fetch{i]

.- object-oriented notation
-- procedure-oriented notation
~- procedure-oriented notation
-- object-oriented notation

]:
(1.10)

10.PutF is the standard way of providing formatted output to a stream (much like FORTRAN
output with format). Its first argument is an 10.Handle. The second is a ROPE with embedded
Fortran-like formatting commands where variables are to be output. The "%g" format is the

9

most useful one: it will handle any sort of variable: I!'II"TEGER. CHARACTER. ROPE, etc., in a
general default format The third through last arguments are values to be output. surrounded
by calls to inline 10 procedures that tell PutF the type of the argument: int(answerJ, for
example. For details, see the description of 10 in the Catalog chapter.
(1.11) MakeCalculator is an ENTRY procedure to this monitor because it updates the variable
windowCount, which is global in SimpleExample and therefore could be incorrectly updated
if multiple processes were to invoke MakeCalculator concurrently.
When invoked,
MakeCalculator creates a new calculator viewer on the screen by invoking Calculate and
forking it as a new process (note 1.13).
(1.12) 10.PutFR (also known by the name PutFToRope has the same arguments as 10.PutF. but
returns a ROPE containing the resultant output rather than sending it to a stream
(1.13) The FORK operation creates a new process to execute a regular procedure call. It returns a
ProcessHandle which can either be used to synchronize with the process later (when its root
procedure executes a RETURN) and acquire its return values. Alternatively, it can be passed
to the procedure Process.Detach, in which case the process can no longer be JOINed to and
will simply disappear when its root procedure RETL'RNS.
Note that the combined FORKing and detaching is enveloped in a TRL'STED block. This is
because the Detach operation is not intrinsically SAFE, although the stylized combination of
FORK and Detach used here actually is. You should use this paradigm when detaching a
FORKed process: don't assign the process handle returned by FORK to anything. just use it as
the single argument to Process.Detach and surround the whole by a TRUSTED block.
(1.14) CreateViewerStreams makes a pair of 10.Handle objects, in for terminal input, and out for
(teletype-style) output These two returned values are assigned to the local variables in and
out using a keyword extractor to ensure that we assign them correctly.
(1.15) Calculate parses a simple expression from the in stream using a number of useful 10 functions
for input, such as Getlnt to provide an INT (skipping over leading blanks), PeekChar to look
at the next character while leaving it in the stream for the next input call, and SkipOver to
scan to the first occurence of an interesting character.
These various 10 procedures can raise the ERROR 10.E"or, so there is a catch phrase enabled
over the outer (endless) loop to deal with 10. Envr. 10.E"or also carries an argument, ec,
which is an enumerated type defined in 10.
If ec=SyntaxEnvr, the user has typed something that is not lexically correct, and the
program will regain control and go around the outer loop again.
The only other possibility is that the in and out streams were closed (ec=StreamClosed) as a
side effect of the user having destroyed the Calculator viewer by bugging the Destroy menu
item. This error and code can emanate from any of the 10 operations in the loop. In this
case the program exits the outer loop, returns from Calculate, and the process that was forked
then terminates and disappears.
(1.16) If a procedure returns values, the Cedar language requires you to assign them to something.
even if you have no use for them in a specific case. The standard mechanism for ignoring a
procedure's returned value(s) is an empty extractor, as here.
(1.17) Here, at the end of the module. is the code that is executed when the module is started. You
can create an instance of a module and start it using the UserExec "Run" command. The
loader creates instances of programs when loading configurations. If a component of a
configuration is not STARTed explicitly. then it will be started automatically (as the result of
a trap) the first time one of its procedures is called. See the Language Reference Manual for
more information.
In this case. the start code for the module consists of two calls on the procedure
UserExec.RegisterCommand. which register the commands "Calculate" and "ReverseName"
with the UserExec so that you can invoke the procedures MakeCalculator and ReverseName,

10

respectively, by typing their command names.
These procedure calls also illustrate the ability to specify the association between a procedure's
formal parameters and the arguments in a specific call using keyword instead of positional
notation. Generally, keyword notation is preferred over positional for all but simple one- or
two-argument calls, and it is definitely better for two-argument calls if the types of the
arguments are the same, e.g., either
Copy(to: argl, from: arg2] or
Cop){from: arg2, to: arg/J

is preferable to

'

Copy(argl. arg2]

(1.18) By convention each module has a CHANGE LOG following the Cedar text It is used to record
an abbreviated history of changes to the module. saying who made each change, when they
made it. and a brief description of what was done. You can insert a new entry in the log by
left-clicking Tioga's ChangeLog viewer button: see the Tioga chapter for details.

11

2. A general sort package for lists
This is an example of a Cedar package and consists of two modules: ListSortReJ specifies the
interface that client programs must import to make use of the package; ListSortRej1mpl implements
that interface.
The package sorts lists of items according to a compare function passed to it along with the list to
be sorted. The algorithm is presented as exercise 5.2.4-17 (p. 169) in Knuth Volume III, and is attributed
to John McCarthy. The comments in the code give some of the important invariants.
2.2. ListSortRef.mesa -

Mark Brown

-- File: ListSortRef.mesa
-- Last edited By Mitchell on December 20. 19823:09 pm

DIRECTORY
Environment USING [Comparison]:
--(note 2.1)

ListSortRef: CEDAR DEFINITIONS ;;
BEGIN

Comparison: TYPE = Environment.Comparison:
PROC[rl, r2: REF ANY] RETURNS [Comparison];
CompareProc: TYPE
-- Returns less if rl1' < r21', equal if r1t
r2t, greater if r1t > r21'.
Compare Error: ERROR[reason: Reason]:
{typeMismatch, invalidType}: -- errors from a CompareProc
Reason: TYPE

=

=

=

Sort: PRoc[list: LIST OF REF ANY. compareProc: CompareProc]
RETURNS[LIST OF REF ANY]:
-- Destructive sort; copy list first if nondestructive sort is needed
-- Returns a list containing the same REFs as list. a"anged in ascending order
--according to compareProc. Order of equal items is not preserved

--(note 2.2)

Compare: CompareProc:
-. ! SafeStorage.NarrowRefFault
-- (if both parameters do not NARROW to one of ROPE or REF INT.)
-- Compares ROPE: ROPE (case significant) and REF [NT : REF INT
END. -- ListSortRef
CHANGE LOG
Created by MBrown on 21-Apr-81 13:55:09
Changed by MBrown on ID-Dec-81 9:50:15
-- Change comment in Compare (now compares ROPE instead of REF TEXT.)
Changed by MBrown on July 5, 19824:59 pm
-- 'CEDAR definitions. ellininate type [tern.
Edited on December 20. 19823:24 pm. by Mitchell
added Compare Error and Reason to make errors generated by a CompareProc more germane to it instead
of the facilities it calls.

2.3. Notes for ListSortRef interface
(2.1) [nterfaces are defined in DEFI:-iITIONS modules. Basically. a DEFINITIONS module contains the
constants, types, and procedure headings (actually procedure types) needed to use a package.

12

Frequently, an interface defines some kind of object with operations (procedures) for that
class of object (the Rope interface is a good example of such an object-oriented interface).
(2.2) This definition for Sort is used for type-checking in any module that contains a calion Sort
or provides an actual implementation of it (note 2.3). Thus, client and implementing programs
can count on the fact that they agree on the type of Sort.
This separation of definition and implementation enables client and implementing modules to
be developed independently of each other. which provides some parallelism in the program
development process. Since they are more abstract. interfaces are typically more stable than
either clients or implementations.
The first argument to Sort has type LIST OF REF ANY. Lists in Cedar are similar to Lisp lists.
In this case the type "LIST OF REF ANY" is equivalent to the following pair of Cedar type
definitions:
REF ListCell:
ListOtRefAny: TYPE
RECORo{first: REF ANY. rest: ListOtRefAny);
ListCell: TYPE
The only things that are special about lists are that the compiler automatically generates the
equivalent of the above two type definitions for each list type you define, the language
provides a CONS operator for allocating and initializing list cells [line 2.1], and list types with
the same elements are equivalent. whereas record types are not.

=

=

2.4. OnlineMergeSortRefimpl.mesa -

Mark Brown

_. File OnlineMergeSortReflmpl.mesa
-- Last edited by MBrown on July 5. 19823:57 pm.
-- Mitchell on Decerrrber 20, 1982 3:21 pm

DIRECTORY
Rope USING [ROPE. Compare],
ListSortRef.
SafeStorage USING [NarrowRetFault];
--(note 2.3)

OnlineMergeSonRefImpl: CEDAR PROGRAM
IMPORTS Rope. SafeStorage
EXPORTS ListSonRef

=

BEGIN
ROPE: TYPE
Rope.ROPE:
Comparison: TYPE' = ListSonRef.Comparison:
ListSonRef.CompareProc:
CompareProc: TYPE

=

=

Sort: PUBLIC PROC [list: LIST OF REF ANY. compareProc: CompareProc]
--(note 2.4)
RETURNS [LIST OF REF ANY] = {
-- The sort is destructive and NOT stable. that is. the relative positions in the result of nodes with
equal keys is unpredictible. For a nondestructive sort. copy list first.
a, b. mergeTo: LIST OF REF ANY:
mergeToCons: LIST OF REF ANY
CONS[NIL. NIL];
-- [2.1] (note 2.5)
index: TYPE
INT [0..22): -- 22 is the number of bits in word-address space minus 2 (cons
cell takes 2**2 words).
soned: ARRAY index OF LIST OF REF ANY ... ALL [NIL];
-- sorted{i} is a sorted list of length
(note 2.6)
_. make each pair of consecutive elements of list into a sorted list of length 2. then merge it
into sorted
UNTIL (a ... list)
:'-lIL OR (b ... a.rest)
:>ilL 00
list ... b.rest:

=

=

=

=

i

or NIL

13

=

IF compareProc[a.first, b.first)
less THEN
--(note 2.7)
{ a.rest .. b; b.rest .. ~IL }
ELSE { b.rest .. a; a.rest .. NIL; a .. b };
FOR j: index .. O. j + 1 DO
IF (b .. sorted(j))
NIL THEN { sorted(j] .. a; EXIT}
ELSE {
--merge (equal length) lists a and b
sortedOJ .. ~[L;
mergeTo .. mergeToCons;
DO --assert a#N1L. b#NIL
IF compareProc[a.first, b.first] = less THEN {
--[2.2)
mergeTo.rest .. a; mergeTo" a;
IF (a .. a.rest) = ~IL THEN { mergeTo.rest .. b: EXIT}}
ELSE {
mergeTo.rest .. b: mergeTo" b:
IF (b .. b.rest) = NIL THEN { mergeTo.rest .. a; EXIT}}
ENDLOOP:
a .. mergeToCons.reSl }
ENDLOOP:
ENDLOOP:
-- if list's length was even. a = NIL: if list's length was odd. a single element list. Merge a
and elements of sorted into result (held in a).
{ j: index .. 0;
UNTIL a # NIL DO
a .. sorted(j]:
IF j < LAsT[index] THEN j .. j + 1 ELSE RETURN[a]:
ENDLOOP:
DO --assert a#NIL
IF (b .. sortedO]> # NIL THEN {
mergeTo .. mergeToCons:
DO -- assert a#NIL AND b#NlL
IF compareProc[a.first, b.first)
less THEN {
mergeTo.rest .. a: mergeTo .. a:
IF (a .. a.rest) = NIL THEN { mergeTo.rest .. b; EXIT} }
ELSE {
.
mergeTo.rest .. b: mergeTo" b;
IF (b .. b.rest)
NIL THEN { mergeTo.rest .. a: EXIT} }
ENDLOOP:
a .. mergeToCons.rest }:
IF j < LAsT[index] THEN j .. j + 1 ELSE RETUR:-.I[a]:
ENDLOOP:
}};-·Sort

=

=

=

=

CompareError: PUBLIC ERROR[reason: ListSortRef.Reason)

= CODE:

Compare: PUBLIC CompareProc ·-{rl. r2: REF .!NYj RETURNS {Comparison]" = TRUSTED {
ENABLE SafeStorage.NarrowRefFault >GOTO BadType;
IF rl = :-.IlL THEN {
IF r2 = NIL THEN RETL'RN [equal]
-- define NIL =NIL regardless of type
ELSE { temp: REF A:-.IY .. rl: rl" r2: r2" temp H:
WITH rl SELECT FROM .. assert rl#.V/L
(note 2.8)
rope: ROPE => RETURN[rOpe.Compare[s2: NARROw[r2. ROPE). case: TRUE]];
ri: REF INT > RETL'RN[CompareINnri1'. NARROW[r2. REF [NT]1']];
--[2.4]
ENDCASE =) ERROR CompareError[invalidTypeJ

=

=

14

EXITS
BadType

}:

=>ERROR CompareError[typeMismatch]

ComparelNT: PROC [intI. ina: [NT] RETURNS [Comparison] = [NLINE {
RETURN [
SELECf TRUE FROM
intI < ina = > less.
intI = ina >equal,
ENDCASE >greater] }:

=

=

END. --OnlineMergeSortRej7mpl
CHANGE LOG
Created by MBrown on 21-Apr-81 13:26:10
Changed by MBrown on 19-Aug-81 15:14:34
-- CedarString -> Rope (used only in Compare.)
Changed by MBrown on 23-Aug-81 17:45:12
-- Fix bug in sorting NfL.
Changed by MBrown on 10-Dec-8l 9:57:58
-- Cosmetic changes: ROPE. INT.
Changed by MBrown on March 9. 1982 5:03 pm
-- Use a bounded array in local frame instead of consing up a list of lists on each call. Even for a 32
bit address space. this is only 60 words of array in the frame.
Changed by MBrown on June 28. 1982 11:43 am
-- CEDAR implementation. ComparelNT no longer uses MACHINE CODE.
Changed by MBrown on July 5. 1982 3:58 pm
-- Eliminate CARDINALs. redundant range check on j. type Item.
Edited on December 20. 19823:20 pm. by Mitchell
changes to: Compare Error added generation of CompareError to Compare to map
SafoStorage.NarrowRejFault and 10 replace unnamed error when an invalid type is presented.

2.5. Notes for OnlineMergeSortRetlmpl
(2.3) To be a general-purpose package, this progam must work properly in the presence of multiple
processes. This means that any global state must be properly protected by monitors. The
writer of this package chose to eliminate all global state from the program. so that no monitor
is required. The cost is that one CONS is done on each call (for the "merge-to" list head)
[line 2.1].
Clearly the package will get fouled up if asked to sort the same list by two concurrent processes.
(2.4) Since Sort'is a PUBLIC procedure and has the same name as one of the procedures of the
EXPORTed ListSorlRef interface. the compiler will check that its type matches the one in
ListSortRef. Similarly when a client program imports LislSorlRef, the compiler will check
that all its uses of ListSortRef.Sorl are type-correct by comparing them against the interface.
[n this way, the client and the implementing modules are known to be in agreement. assuming
Ihal Ihey were both compiled using the same ListSortRef.
To ensure that they are in agreement the compiler places a unique identifier (UID) on each
module that it compiles. When the client is bound to the implemented procedure (e.g .. when
they are loaded), the llD that ListSorlRef had when the client was compiled is compared
against the (;10 it had when the implementing module was compiled. They must agree for

15

the binding to be allowed, otherwise there is a version mismatch.
(2.5) The list head, mergeToCons. simplifies the code a bit. Without it, the first comparison in a
merge [line 2.2] would have to be treated specially. Note also that mergeToCons is initialized
to refer to a new empty list cell every time Sort is called.
(2.6) The array sorted in the local frame is long enough to hold any list of REFS that will fit in the
Cedar virtual memory. By keeping this array in the local frame we save both the cost of
another allocation and the cost of ref-counting the assignmencs to array elements.
(2.7) The cli~nt's compareProc is responsible for narrowing its two REF ANY arguments to specific
types. Using a client-supplied procedure and one or more REF ANY parameters is a standard
way of,introducing some polymorphism into Cedar programs. The costs associated with doing
business this way are extra procedure calls and run-time discrimination of REF ANY arguments
in client-supplied procedures (see. for example. (note 2.8».
When these costs are deemed too high. one can get some amount of compile-time polymorphism to avoid them.
Nothing is free. however. and achieving this run-time performance requires recompiling both the interface and the
implementation modules for each application. There is a version of this sorting package that does just that: see the
description of O"li"eMergeSort in the Cedar Catalog.

(2.8) Compare provides clients with a procedure to pass to Sort for comparing ROPES or INTS. It is
a good model for writing your own comparison routine.
Since Compare is passed two REF ANY argumencs. it must perform run-time type discrimination
to determine that it can cope with them. The standard way of doing this is with a disCriminating
select statement and the NARROW operation.
One of the three arms will be executed, depending on the type of value that rl refers to (note
that rl cannot be NIL at this point because of the preceding code).
If rl is a ROPE (which is actually a REF to a data structure describing the ROPE). then the
first arm will be selected. In that arm. rope will be an alias for rl. If rl is a REF INT. the
seond arm will be selected, and ri will be an alias for rl. Otherwise. the ENDCASE arm will
be selected and the ERROR CompareE"ot{invalidType] will be raised.
Inside the rope: ROPE arm. Compare simply returns the value returned by Rope. Compare.
Since Rope.Compare expects parameters sl and s2 to be ROPES. however. :-.IARROW is used to
If r2 were not a ROPE. NARROW would generate the error
cast r2 as a ROPE.
Sa/eStorage.NarrowRejFault. which is caught by the encompassing ENABLE clause and then
mapped into CompareErrot{typeMismatch] by the procedure's EXITS clause.

16

3. A sample tool using Viewers
This program illustrates how to build tools in the CedarViewers' world The user interface it creates
uses both existing classes of viewers as well as a new class of viewer for special effects. It contains a
number of sections. each of which demonstrates a particular set of techniques. The best use of this code
would be to copy interesting sections as models for creating your own tool.
It would be a good idea to try the SampleTool before looking at this example. When you type
"Run SampleTool" to the UserExec. the SampleTool will appear in iconic form on the lower left side
of the Cedar display. Open it by selecting it with the YELLOW (middle) mouse button and then try it
out to see how it behaves.
The first part of the SampleTool viewer consists of the standard line of menu buttons at the top of
any viewer with a few of the operations deleted and a new one, "MyMenuEntry". added
The second part holds a "factorial computer", which allows you to compute N! by changing the
value of N in the input part of the viewer and then selecting the button labelled "Compute Factorial"
with the RED (left) mouse button.
The third part of the viewer presents a horizontal. logarithmic bar graph that dynamically updates
itself and shows "Words Allocated Per Second" in the Cedar system.
3.1. SampleTool.mesa - Scott McGregor
-- SampleTooLmesa: Written by Scott McGregor on June 9. 19829:51 am
-- Last edited by Mitchell on August 16, 19824:16 pm
-- Last edited by McGregor on October 4. 1982 11:01 am
DIRECTORY

Buttons USING (Button, ButtonProc, Create).
Containers USING (ChildXBound Container, Create],
Convert USING [IntFromRope, ValueToRope),
Graphics USING [Context, DrawBox, SetStipple],
Labels USING [Create, Label Set],
Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, Menu. MenuProc],
MessageWindow USING [Append. Blink),
Process USING [Detach.. Pause. SecondsToTicks. Ticks].
Rope USING [Cae. ROPE. Length),
Rules USING [Create. Rule].
SafeStorage USING [NarrowFaule. NWordsAllocated),
ShowTime USING [GecMark, Microseconds],
UserExec USING [CommandProc. GetExecHandle. RegisterCommand].
VFonts USING [CharWidth. String Width].
ViewerClasses USING [paintProc. Viewer, ViewerClass. ViewerClassRec],
ViewerOps USING [CreateViewer. PaintViewer. RegisterViewerClass. SetOpenHeight],
ViewerTools USING [MakeNewTextViewer. GetContents. SetSelection];
SampleTool: CEDAR PROGRAM
--(note 3.0)
IMPORTS Buttons. Containers. Convert. Graphics. Labels. Menus. MessageWindow, Process,
Rope. Rules. SafeStorage. ShowTime. UserExec. VFonts. ViewerOps. ViewerTools =
BEGIN

-- The Containers interface is used to create an outer envelope or "container" for the diffirent sections
below. For uniformity. we define some standard distances between entries in the tool.

17

=

entry Height: CARDINAL
15: -- how tall to make each line of items
entryVSpace: CARDINAL = 8: -- vertical leading space between lines
entryHSpace: CARDINAL
10:
-- horizontal space between items in a line

=

Handle: TYPE

=

REF SampleToolRec;
-- a REF to the data for a particular instance of the
sample tool: multiple instances can be created
SampleToolRec: TYPE = RECORD [ -- the data for a particular tool instance
outer: Containers.Container .. NIL.
-- handle for the enclosing container
height: CARDINAL .. O.
-- height measured from the top of the container
fact: FactorialViewer.
-- the jactorial viewer's state
graph: GraphViewer ];
-- the bar graph viewer's state
MakeSampleTool: UserExec.CommandProc = TRUSTED BEGIN
my: Handle .. NEw[SampleTooIRec]:
my Menu: Menus.Menu .. Menus.CreateMenu[]:
Menus.AppendMenuEntry[ -- add our command to the menu
menu: my Menu.
entry: Menus.CreateEntry[
name: "MyMenuEntry".
-- name of the command
proc: MyMenuProc
-- proc associated with command
]
];
my.outer .. Containers.Create[[-- construct the outer container
(note 3.1)
name: "Sample Tool". -- name displayed in the caption
iconic: TRUE,
-- so tool will be iconic (small) when first created
column: left.
-- initially in the left column
menu: myMenu,
-- displaying our menu command
scrollable: FALSE]];
-- inhibit user from scrolling contents
MakeFactorial[my];
-- build each (sub)viewer in turn
MakeGraph[my]:
-- hint our desired height
ViewerOps.SetOpenHeight[my.outer. my.height]:
ViewerOps.PaintViewer[my.outer, all];
-- reflect above change
END:
MyMenuProc: Menus.MenuProc

= TRUSTED BEGIN

this procedure is called whenever the user left-clicks the entry labelled "MyMenuEntry" in the tool
menu.

MessageWindow.Append[
message: "You just invoked the sample menu item with the ",
clearFirst: TRUE];
IF control THEN MessageWindow.Append[
message: "Control-".
clearFirst: FALSE);
IF shift THEN MessageWindow.Append[
message: "Shift-.. ,
.
clearFirst: FALSE);
MessageWindow.Append[
message: SELECT mouseButton FROM
red
=> "Red".
yellow => "Yellow".
ENDCASE
>"Blue".
clearFirst: FALSE]:
MessageWindow.Append[message: .. mouse button.... clearFirst: FALSE];

=

18

MessageWindow.Blink( ]:
END:
FactorialViewer: TYPE = RECORD [
•• the Text Box for user input
input: ViewerClasses. Viewer .. NIL.
result: Labels.Label .. NIL]:
•• result of the computation
MakeFactorial: PROC (handle: Handle] = TRUSTED BEGIN
··(note 3.2)
promptButton. computeButton: Buttons.Button;
"5": \
initialData: Rope.ROPE
initial Result: ~ope.ROPE = "120":
handle.height .. handle.height + entryVSpace; -. space down from the top of the viewer
promptButton .. Buttons.Create[
info: [
name: "Type a number:".
wy: handle.height,
- default the width so that it will be computed for us ••
wh: entry Height, .• specify rather than defaulting so line is uniform
parent: handle.outer.
border: FALSE].
proc: Prompt,
clientData: handle]; •• this will be passed to our bullon proc
handle.factinput .. ViewerTools.MakeNewTextViewer[ [
parent: handle.outer.
wx: promptButton.wx + promptButton.ww + entryHSpace.
wy: handle.height + 2.
ww: 5"'VFonlS.CharWidth{'O]. •• five digits worth of width
wh: entry Height,
data: initialData. •• initial contents
scrollable: FALSE.
border: FALSE]]:
compute Button .. Buttons.Create[
info: [
name: "Compute Factorial".
wx: handle.fact.input.wx + handle.fact.input.ww + entryHSpace.
wy: handle.height,
•• default the width so that it will be computed for us
(note 3.3)
ww:.
wh: entry Height, •• specify rather than defaulting so line is uniform
parent: handle.outer.
border: TRUE],
clientData: handle, •• this will be passed to our button proc
proc: ComputeFactorial):
handle.factresult .. Labels.Create[ [
name: initial Result, •• initial contents
wx: computeButton.wx + computeButton.ww + entryHSpace.
wy: handle.height,
ww: 20*VFonts.CharWidth('0), •• 20 digits worth of width
wh: entry Height,
parent: handle.outer.
border: FALSE]]:
handle.height .. handle.height + entryHeight + entryVSpace;
•• interline spacing
END;

=

19

Prompt: Buttons.ButtonProc = TRUSTED BEGIN
•• force the selection into the user input field
handle: Handle .. NARRow[clientData): •. get our data
ViewerTools.SetSelection[handle.fact.inputl:
•• force the selection
END:
Compute Factorial: Buttons.ButtonProc = TRUSTED BEGIN
handle: Handle .. NARRow[clientData): •• get our data
contents: Rope.ROPE .. ViewerTools.GetContents[handle.fact.input):
inputNumber: INT:
resultNumber: REAL" 1.0:
IF Rope.Length[contents]=0 THEN inputNumber .. 0
ELSE inputNumber .. Convert.IntFromRope[contents
! SafeStorage.NarrowFault => {inputNumber"'I; CONTINUE}];
IF inputNumber NOT IN [0 .. 34) THEN {
Message Window .Append[
message: "I can't compute factorial for that input",
clearFirst: TRUE ]:
MessageWindow.Blink[ ] }
ELSE FOR n: INT IN [2..inputNumber] 00
resultNumber .. resultNumber*n;
ENDLOOP:
Labels.Set[handle.fact.result, Con vert. ValueToRopeU real[ resultNumber]m;
END:

··(note 3.4)

-. the bar graph reflecting collector activity
GraphViewer: TYPE = RECORD [viewer: ViewerClasses.Viewer .. NIL);
MakeGraph: PROC [handle: Handle] = TRUSTED BEGIN
--(note 3.6)
xIncr: INTEGER;
-- temporarily used for labelling graph below
xTab: INTEGER = 10:
label: Rope.RoPE .. "I";
•• used to place labels on the graph
rule: Rules.Rule .. Rules.Create[ [ .• create a bar to separate sections 1 and 2
parent: handle.outer,
wy: handle.height,
ww: handle.outer.cw.
wh: 2]];
Containers.ChildXBound[handle.outer. rule];
•• constrain rule to be width of parent
handle.height .. handle.height + entryVSpace: •• spacing after rule
[ ] .. Labels.Create£[
name: "Words Allocated Per Second", parent: handle. outer.
WX: xTab. wy: handle. height, border: FALSE )]:
handle.height .. handle.height + entry Height + 2: •. interline spacing
handle.graph.viewer .. CreateBarGraph[
parent: handle.outer.
x: xTab. y: handle.height, w: 550. h: entry Height,
-- orders of magnitude
fullScale: 5.0 ];
handle.height .. handle.height + entry Height + 2: •• interline spacing
xIncr .. handle.graph.viewer.ww/5:
.• so we can space labels at equal fifths
FOR i: INTEGER IN [0..5) 00
.• place the labels. I, 10, 100. 1000, 10000 along the graph
[ ] .. Labels.CreateUname: label. parent: handle.outer.
wx: xTab + i*xIncr . VFonts.StringWidth[label]l2,
wy: handle.height. border: FALSE]]:

20

label +- label.Cat["O"]:
-- concatenate another zero each time
ENDLOOP:
handle.height +- handle.height + entry Height + entryVSpace: -- extra space at end
TRUSTED {Process.Detach[FORK MeasureProcess[handle]]}; -- start the update process
END;
MeasureProcess: PROC [handle: Handle)' = TRUSTED BEGIN

--(note 3.7)

.- Forked as a separate process. Updates the bar graph at periodic intervals.

update [nterval: Process.Ticks = Process.SecondsToTicks[1]:
mark, nextMark: ShowTime.Microseconds:
words, nextWords, deltaWords. deltaTime: REAL;
mark +- ShowTime.GetMark[ ]:
words +- SafeStorage.NWordsAllocated[ ):
UNTIL handle.graph. viewer.destroyed 00
nextMark +- ShowTime.GetMark[ ];
deltaTime +- (nextMark • mark) * 1.0E-6:
nextWords +- SafeStorage.NWordsAllocated[ ];
deltaWords +- nextWords' words:
SetBarGraphValue[handle.graph. viewer, deltaWords!deltaTime):
words .. nextWords:
mark .. nextMark:
Process.Pause[updateInterval) :
ENDLOOP:
END:
this section creates the viewer class for a logarithmic bar graph.
_. private data structure for instances of BarChart viewers

=

GraphData: TYPE
REF GraphDataRec:
RECORD [
GraphDataRec: TYPE
value: REAL" 0, -- current value being displayed (normalized)
scale: REAL):
-- "foll scale"

=

=

PaintGraph: ViewerClasses.PaintProc
TRUSTED BEGIN
myGray: CARDlNAL
1226458: -- every other bit
data: GraphData .. ~ARRow[self.data]:
Graphics.SetStipple[context, myGray):
Graphics.DrawBox[context, [0, O. data. value. self.ch]]:
END:

=

--(note 3.8)

CreateBarGraph: PROC [x. y. w. h: I~'TEGER, parent: ViewerClasses. Viewer,
fullScale: REAL]
RETURNS [barGraph: ViewerClasses. Viewer] = TRUSTED BEGIN
--(note 3.9)
instanceData: GraphData +- NEw[GraphDataRec]:
instanceData.scale +- fullScale:
barGraph +- ViewerOps.Create Viewer[
flavor: $BarG rap h. -- the class of viewer registered in the start code below
info: [
parent: parent,
wx: x, wy: y, ww: w. wh:h.
data: instance Data.
scrollable: FALSEI

I:
END:

21

-- use this routine to set the bar graph to new values
SetBarGraphValue: PROC [barGraph: ViewerClasses. Viewer, new Value: REAL] = BEGIN
my: GraphData .. NARROw[barGraph.data];

LoglO: --Fast-- PROC [x: REAL] RETURNS [Ix: REAL] = BEGIN
-- truncated for values of[l.. inj}. 3-4 good digits
-- algorithm from Abramowitz: Handbook of Math Functions. p. 68
sqrtl0: REAL
3.162278:
t: REAL;
Ix .. 0;
WHILE x > 10 DO x .. x/lO: Ix .. Ix + 1 ENDLOOP; -- scale to [1..10J
IF x >sqrtlO THEN {x .. x/sqrt10; Ix .. Ix+0.5};
-- scale to [1..1/sqrtJOJ
t .. (x-1)/(x+ 1);
Ix .. Ix + 0.86304*t + 0.36415*(t*t*t)
-- magic cubic approximation
END:

=

my.value" LoglO[1+newValue] * barGraph.cw I my.scale;
TRUSTED {ViewerOps.PaintViewer[viewer: barGraph. hint: client. clearClient: TRUE]}:
END;
-- graphClass is a record containing the procedures and data common to all BarGraph viewer
instances (class record).
graphClass: ViewerCtasses. ViewerClass ..
--13.1)
NEw[ViewerClasses. ViewerClassRec .. (paint: PaintGraphl1;
-- Register a command with the UserExec that will create an instance of this tooL
UserExec.RegisterCommand[name: "SampleTool", proc: MakeSampleTool.
brietDoc: "Create a sample viewers tool" ];
-- Register the BarGraph class of viewer with the Window Manager
TRUSTED {ViewerOps.RegisterViewerClass[$BarGraph. graphClass]};
-- and create an instance
[ ] .. MakeSampleTool[UserExec.GetExecHandle[ ]];
END.

3.2 Notes for SampleTool
(3.0) [hopefully temporary note] To make this module a valid CEDAR PROGRAM, many sections
had to be declared TRUSTED regions because they use other. not yet SAFE. interfaces. Most
of these regions are entire procedure bodies. but in some cases it has been possible to narrow
the TRUSTED region to a smaller scope.
(3.1) Many of the Viewer procedures take a fair number of arguments in order to provide a number
of options. Many of these can be defaulted. as in this section of the program. Using keyword
notation makes these calls significantly more clear about which parameters are being specified
as well as making them independent of the order specified for the parameters.
(3.2) The factorial sub-Viewer contains a "Text Box" for'the user to enter a number. and a button
that computes the factorial of the number in the text box when pushed and writes it in a
result field. The fields for' the user's input and the result are stored in handle.fact.
Note that the name of MakeFactoria!s parameter, handle. and its type. Handle. differ only in
the case of the "h". In general, having names that differ only in case shifts of letters is a
very bad idea. However, this one exception is so compelling and so common that it has
become part of the Cedar stylistic conventions: If there is only one variable· of a type in a
scope, its name can be the same as that of its type except that it should begin with a lowercase
letter. Think of it as equivalent to the definite article in English ("the Handle").
(3.3) Buttons.Create will compute the width from the button's name, so we can default this argument

22

(3.4)

(3.5)
(3.6)

(3.7)
(3.8)

(3.9)

to the procedure. Specifying the keyword parameter name w without a value indicates that
it should get whatever default value is specified in the definition of Buttons.Create.
Convert.lntFromRope lets the error Sa/eStorage.Nan'OwFault escape from it (stylistically. it
really oUght to map that error into one defined in its interface). ComputeFactorial catches
this error and assigns -1 to inputNumber to trigger the subsequent test for its being in a
suitable range and so give the error message "I can't compute factorial for that input" in the
message window.
Atoms provide virtual-memory-wide unique identifiers like $BlackOnGrey (all atom constants
are denoted by a leading "$" followed by an identifier).
The "bar graph" sub-Viewer contains a logarithmic bar graph depicting the number of words
per second currently being allocated via the Cedar counted storage allocator. Unlike the
factorial sub-Viewer. which only makes use of pre-defined viewer classes, this section defines
a new viewer class, $BarGraph [line 3.1J. to display information and makes a viewer which is
an instance of the class.
MeasureProcess runs as an independent process. looping as long as the viewer denoted by
handle continues to exist. It computes the average number of words allocated per second in
Cedar safe storage and then sleeps for a shon time before repeating the cycle.
Paint Graph is called whenever the bar graph contents are to be redisplayed on the screen. It
will always be called by the window manager. which will pass it a Graphics.Context. correctly
scaled. rotated and clipped for the viewer on the screen. It is passed to the Viewers machinery
when the $BarGraph class is created (line 3.1].
CrealeBarGraph is called to create a new BarGraph viewer. It creates the private data for the
new instance and then calls a Viewers' system routine to create the actual viewer.

23

4. An evaluator for FUN, a functional programming language
This standalone program provides interactive entering and evaluation of expressions in a small,
functional programming language, FUN, based on Landin's [SWIM language. The language is defined by
the following BNF rules:
Prog :: ExpO" #"
.
ExpO :: = "let" Id .. =" Exp1 "in" ExpO I Exp1
Exp1 ::= "lambda" Id "." Exp11 Exp2
Exp2 :: = Exp2 Exp3 I Exp3
Exp3 :: = Id I ..(.. ExpO ")"

=

An example FUN program is
let Twice
lambda f. lambda y. f( f y) in
let ApplyThyself = lambda z . z z in
(ApplyThyself Twice Twice) (PLUS 1) 2

=

#+
Twice is a function that produces a function which applies Twice's parameter f twice to whatever
comes next (y). ApplyThyself applies its parameter z to itself. The result of this program is 18 because
(ApplyThyself Twice)
(Twice Twice)
FourTimes, (FourTimes Twice)
SixteenTimes. and
SixteenTimes plus 2 is 18.

=

=

=

4.1 FUN.mesa - Jim Morris
-- FUN. mesa.
-- Last edited by Mitchell on December 16, 19822:50 pm
-- Last edited by Jim Morris. May 12. 1982 10:28 am
DIRECTORY
[0 USING [BreakAction, BreakProc, CR, CreateViewerStreams, EndOf. Error, GetInt. GetToken,
Handle. int. PutF, PutFR, refAny. rope, RIS. SP, TAB),
Process USING [Detach],
Rope USING [Digit. Equal, Fetch, Letter. ROPE],
SafeStorage USING [NarrowRetFauit. NewZone];
FUN: CEDAR PROGRAM
[MPORTS 10. Process. Rope, SafeStorage
BEGIN
ROPE: TYPE
Rope.RoPE;
z: ZONE
SafeStorage.NewZone[ ];
--(note 4.1)

=

=
=
Exp: TYPE = REF ANY;-- always a REF to one of the following
Variable: TYPE = ROPE;
Application: TYPE = REF ApplicationR;

(note 4.2)

ApplicationR: TYPE = REcoRo[rator. rand: Exp];
Lambda: TYPE = REF LambdaR:
LambdaR: TYPE
RECORo[bv: Variable. body: Exp);
Closure: TYPE
REF ClosureR:
ClosureR: TYPE = RECORD[exp: Exp, env: Environment];
Primitive: TYPE
REF PrimitiveR:
PrimitiveR: TYPE = RECORo[p: PRoc[Exp. Exp] RETURNS [Exp] , state: Exp];
Environment: TYPE
LIST OF RECORo[var: Variable, val: Exp];

=
=

=

=

din, dout: 10.Handle:
FUNError: ERROR = CODE:

--(note 4.3)

24

=

NoteError: PROC [msg: ROPE]
BEGIN
-- this procedure always generates the error FUNError.
doutPutF["\n %g \n\n", [O.rope[msg]];
ERROR FUNError;
END:
-- The FUN lexical analysis and parsing machinery

--(note 4.4)

cToken: ROPE:
Next: PROC = {
cToken .. IF din.EndOt{ ] THEN" #" ELSE din.GetToken[StTokenProc]};
StTokenProc: IO.BreakProc = BEGIN
OPEN 10;
RETURN[
IF Rope.Letter[c] OR Rope.Digit[c] THEN KeepGoing
ELSE IF c=SP OR c=CR OR C=TAB
THEN StopAndTossChar ELSE StopAndlncludeChar];
END:

--(note 4.5)
--(note 4.6)

Id: PROC RETURNS [i: Variabie] = BEGIN

IF IsId[cToken] THEN {i .. cToken: Next[ ]}
ELSE NoteError[uInput Error: No Id"]
END;
Isld: PROC[X: ROPE] RETURNS [BOOLEAN] = BEGIN
RETURN[Rope.Digit[x.Fetch(O)) OR Rope.Letter[x.Fetch[O))
AND NOT Rope.Equal(x. "let"]
AND NOT Rope.Equal[x. "in"]
AND NOT Rope.Equal[x. "lambda"]];
END:

Prog: PROC RETURNS [e: Exp] = BEGIN
e .. ExpO[ ]:
IF Rope.Equal(cToken, "#"] THEN RETUR~;
UNTIL Rope.Equal(cToken. "# "] DO Next( ] ENDLOOP;
NoteError["Input Error: Whole Expression not consumed"]:
END;

=

--(note 4.7)

ExpO: PROC RETURNS [Exp]
BEGIN
IF Rope.Equal(cToken, "let"] THEN {
Next[ ];
{v: Variable = Id(]:
IF NOT Rope.Equal[cToken. "= "] THEN NoteError[" Input Error: No = "];
Next[ ];
{val: Exp = Expl[];
IF NOT Rope.EquaI[cToken, "in"] THEN NoteError["Input Error: No in"];
Next[ ]:
RETURN[
Z.NEW[ApplicationR .. [Z.NEw[LambdaR .. [v,. ExpO( ]]]. val]]] } } }:
RETURN[Expl( ]];
END;
Expl: PROC RETURNS [Exp] = BEGIN
IF Rope.Equai(cToken, "lambda"] THEN
{Next[ ];

25

{i: Variable = Id(]:
[F NOT Rope.Equal(cToken. ". "] THEN NoteError("[nput Error: No ."];
Next[ ];
RETURN[Z.NEW[LambdaR .. [i, Expl( ]]]] } };
RETURN[Exp2[ ]];
END;

Exp2: PROC RETURNS [e: Exp] = BEGIN
e .. Exp3[ ];
WHILE Rope.Equal[cToken. "C"] OR IsId[cToken] 00
e .. Z.NEW[ApplicationR .. [e. Exp3[ ]]];
ENDLOOP:
END;

--[4.01

ExpJ: PROC RETURNS Ie: Exp] = BEGIN
[F Rope.Equal[cToken. "("] THEN {
Next[ ]; e .. ExpO[ ];
[F NOT Rope.Equal[cToken.
THE:-.I NoteError["Input Error: No )"]; .
Next[ ]}
ELSE e .. Id[ ];
END;

"n

-- The FUN interpreter
Eval: PROc[x: Exp, env: Environment] RETURNS [Exp] = BEGIN

--(note 4.8)

00

WITH x SELECT FROM
v: Variable => {t: Environment .. env;
UNTIL t=NIL OR Rope.Equal[v, t.first.var] DO t ... t.rest ENDLOOP:
RETURN[IF t=NIL THEN x ELSE t.first.val]};
p: Primitive = > RETURN[x);
I: Lambda = > RETURN[Z.NEW[ClosureR .. [1. envID;
a: Application = >
{rator: Exp = Eval[a.rator. env];
rand: Exp = Eval[a.rand. env];
WITH rator SELECT FROM
f: Closure = > {
I: Lambda = ~ARRow[f.exp
! SafeStorage.NarrowRefFault = >
NoteError["Evaluation Error: Illegal application"] ];
x .. l.body; env .. cONs([l.bv. rand], f.env] }:
prim: Primitive = > RETt.:RN[Prim.p[prim.state. rand]];
ENDCASE = > NoteError["Evaluation Error: Ulegal application"]}:
f: Closure = > RETURN[X];
ENDCASE
ENDLOOP;
END:
Plus: PROc[d. first: Exp] RETURNS [Exp] =
{RETURN[Z.NEw[PrimitiveR .. [Plus!. first]]]}:
Plus!: PRoc(first. second: Exp] RETURNS[v: Variable] = BEGIN
ENABLE [o.Error = > NoteError["Evaluation Error: Not a number"];
a: [1';! = [o.Gednt(Io.RIS(NARROW[first. ROPEI11;
b: INT = Io.GetInt[Io RIS[NARROw[second. ROPE]]];

--[4.1)
--[4.2)

--(note 4.9)

--[4.3)
--(note 4.10)

26

RETURN[IO.PutFR[, IO.int[a + b]]]:
END:
EvalLoop: PROC

= BEGIN

00

ENABLE {
--(note 4.11)
FUN Error =) LOOP;
--(note 4.12)
IO.Error => EXIT}:
result: Exp +0 NIL;
Next[ J:
result ... Eval[Prog( J, LISTU"PLUS". Z.NEw[PrimitiveR ... (plus. NIL]]]]): --(note 4.13)
dout.PutF("\nResult is %g\n\n",Io.refAny[result]];
--(note 4.14)
ENDLOOP
END:
[din. doutJ ... lo.CreateViewerStreams("Fun"J;
TRUSTED {Process.Detach(FORK EvalLoop[ ]]}:
END.
4.2 Notes for FUN
(4.1) This declares z to be a storage zone. and initializes it by creating a new zone.
Throughout the program you will see expressions of the form "Z.NEW[...]". which allocate data
structures using storage taken from this zone. It is not required that we create a zone to use
for allocation. but experience has shown that performance is better if each application takes
its storage from its own zone rather than the public. default zone one gets by saying simply
"NEW(...]".
Some commonly used packages provide zones in which to allocate the objects they manage. For example. the zone
Lisl.LisrZone can be used to make a list element. e.g.. LisLLisrZone.CONS(NIL. NIL). Alternatively. the procedure
LisLCons can be used with the same effect. Also. the Ref!'exr interface contains the procedure

ReITextNew[nChars: NAT] RETURNS [REF TEXT].
which uses a zone provided by the package for allocating the REF TEXT rather than the default system zone.

(4.2) This sequence of declarations defines the representation for FUN expressions. An expresSion
is parsed into an abstract tree form which can then be interpreted by the Eval procedure.
An expression (Exp) can refer to one of five different node types:
A Variable. which is represented as a ROPE containing its name;
An Application. which consists of an operator (rator) and an operand (rand);
A Lambda expression. which consists of a bound variable (bv) and a body:
A Closure, which is an expression (exp) together with an Environment, which is a LIST defining
a value for each its free variables:
A Primitive. which is a Cedar procedure together with some state.
Notice that it is perfectly legal to store procedures in data structures. What is actually stored.
however, is a pointer to the code. Since Cedar does not support procedures as values in full
generality. such procedures cannot be local to other procedures; nor can they refer to their
parents' local variables (because. for efficiency of procedure invocation, the Cedar garbage
collector does not treat procedures' activation records as collectible storage).
We had to define a name for both the node record types and for references to them. e.g.,
ApplicationR and Application. The record type name is needed when calling the NEW
procedure as in
Z.NEW(ApplicationR ... [e, Exp3[ ]]]
--[4.0J

27

The reference types are used in nodes to provide the tree structure for a FL"!'i expression
[n declaring an Exp to be a REF ANY. we have told the compiler that it may be a reference to
anything at all. This is the recommended way of achieving type variation in Cedar. (A version
of Pascal-like variant records is also available. but should only be used when efficiency is crucial.)

(4.3) The procedure NoteError types an error message to the user and then generates the ERROR
FUNError to clean up the call stack back to Eva/Loop, where the error is caught and dealt
with (note 4.11).
(4.4) The tokenizer and parser for FUN use [0 for reading tokens from the input stream din using
the StTokenProc to direct the tokenizing facilities provided by 10.
(4.5) The value returned by StTokenProc is an enumerated type from the (0 interface.
(4.6) oPENing [0 allows us to omit the 10. prefix from SP. CR. TAB, KeepGoing, StopAndTossChar,
and SlopAndlnc/udeChar. This is one of the few cases in which an unqualified OPEN should
be used. Generally, programs are more easily read when it is obvious which identifiers are
imported and which interfaces they come from. If you use OPEN over any but the smallest
scope, it is recommended that you use the qualified form. e.g., "OPEN Safe: SafeSlorage"
over a limited scope, or just "Safe: SafeStorage" in the imports list if the scope is the entire
module.
(4.7) Prog, ExpO, ExpJ, Exp2, and Exp3 constitute a simple recursive descent parser for FUN.
(4.8) Eva/, Plus, PlusJ, and Eva/Loop constitute the FUN interpreter. Eva/ uses WITH-SELECf to
discriminate among the various Exp node types and NARROW when there is only one possible
type that an Exp could be [line 4.1]. If the NARROW fails. it will raise the signal
SafeStorage.NarrowRe/Fault. If the user were to see .that error, it would be somewhat
mystifying, so the program catches it and generates
NOleErrol'{"Evaluation Error: Not a lambda expression"]
[line 4.2],
which at least says what is actually happening in terms of the FUN language. The same
effect is achieved in P/us/ [line 4.3) using an ENABLE clause in the body of the procedure.
(4.9) Plus is a "primitive-returning-primitive" that returns a function prepared to addfirst to whatever
comes second.
(4.10) This is a standard way to convert a ROPE to an integer; create a stream from the rope using
RS and pull (scan) an integer from it. A NARROW could fail if the user typed something like
"(PLUS x 1) #l". Should that happen, the signal SafeStorage.NarrowRe/Fau/t would be
caught, an error message given to the user, and then the FUNError signal would be generated
to unwind control cleanly out to Eva/Loop.
(4.11) If a problem is encountered while parsing or evaluating a FUN expression. the error FUNError
will be generated.
EvalLoop catches it and Simply continues around the main
read-evaluate-print loop.
(4.12) When the user destroys the FUN viewer, its din and dout streams will be closed, and any
pending call on 10 routines will generate the error IO.E"oI'{StreamClosed). This error is
caught so that Eva/Loop can then gracefully exit and it process can then disappear.
(4.13) The second parameter of Eva/ is an environment mapping "PLUS" into a primitive.
(4.14) This PUlF will print result. even if it is a paritaUy evaluated function or an environment. Try
typing "(PLUS 1) #l" to see this.

Release as

Draft
By
Last edited

[Indigo] {inputNumber"-l; CONTINUE}];

4. Programming constructs:
Ensure that the target type for a NARROW is obvious
either by naming it explicitly or using it in a simple contexL
_. target type = Handle
handle: Handle" NARRow[clientData);
a: INT = lo.GetInt[IO.RS[NARROW[first. ROPE]ll:
•• target type = ROPE

Use TR USTE D over the most confining region in which it is needed
TRlJSTED {Process.Detach[FORK EvalLoop( J)}:

5. Module histories:
The first two lines of a source module
should be comments. one giving the file name for the module, and the other giving the name of the
person who last edited it and when she/he did so. [f you use the conventions described in the Tioga
chapter for these lines, Tioga can be made to update the last-edited date automatically when you save
the file.

- FILE: OnlineMergeSortRepmpLmesa
- Last Edited lJy MBrown on March 9, 19825:01 pm

Immediately following each procedure declaration in a definitions module
should be a brief comment, providing the information most useful to a potential client, who may be
reading the listing. or querying via the User Exec.
Sort: PROC
[itemList: LIST OF Item.
compareProc: PRoc[Item, Item] RETCRNS [Comparison]]
RETURNS[LIST OF Item):

- Destructive sort of itemList; returns sorted list containing same items.
- Order of equal items is not preserved.

7

Keep a CHANGE LOG
at the end of each source module for keeping track of who first created the module. who has changed
it. why it was changed. and when. (see the description of the Tioga Change Log button in the Tioga
chapter for a way of preparing change log entries semi-automatically).
CHANGE LOG

Created by MBrown on 2h\pr-81 13:26:10
Changed by MBrown on 19-;\.ug-81 15:14:34

- CedarString

-> Rope (used only in Compare.)

Changed by MBrown on 23-Aug-81 17:45:12
- Fix bug in sorting NIL.
Changed by MBrown on 10-Dec-81 9:57:58
- .Cosmetic changes: ROPE. INT.
Changed by MBrown on March 9. 1982 5:03 pm
- Use a bounded array in local frame instetIJJ 0/ consing lip a list o/Iists on each calL Even
lor a 32 bit address space. this is only 60 words 0/ array in the frame.

6. Program layout

Use Ceriar.abbreviations
and see the description of the "Expand Abbreviation" command in the Tioga chapter.

7. The Fuglemen
This section consists of a set of skeletal programs. Fugleman. FuglemanImpl, and FuglemanClient, that
use the conventions expounded in the above style discussion. The name Fugleman comes from the
following definition:
ru·gle·man n., pl. -men.
1. Archaic. A soldier who serves as a guide and model for his company.
2. A leader: especially a religious leader.
And. Lord knows. there is no more religious issue than one's favorite programming style.
7.1. Fugleman.mesa
This is a template for defining the interface for a class, Fugleman, of objects. It provides for multiple,
coexisting implementations of the class. The file FuglemanClientmesa shows how a client program can
create instances of the objects of this class, and the file Fuglemanlmpl.mesa is a template for an
implementation of the class.
-- FILE: Fugleman.mesa
-- Last Edited by Homing. June 7. /982 2:55 pm

Fugleman: CEDAR DEFINITIONS
BEGIN

=

=

Handle: TYPE
REF Rep:
Rep: TYPE;
FugleFailure: ERROR;

-- opaque type for the representation of the object

NewFugleman: PROC RETt:RNS [Handle];
-- Makes a new Fugleman object
Print: PROC [h: Handle]:
Check: PROC [h: Handle];
-- ERRORs: FugleFailure

8

-- Returns normally

if Fugleman object OK

SomeProc: PROC [h: Handle. otherArgument: [NT] RETtiRNS [INT];
-- Comment goes here saying what it does
END.
CHANGE LOG

Created by Mitchell. March 17. 1980 11:00 AM
-- This is a template for interim Cedar object interfaces. It shows what one would write to
define the interface for a class FugleMan of objects with operations Release. Print. Check.
and SomeProc
Changed by Mitchell. June 4. 1982 3:34 pm
-- Convert to present Cedar conventions
Changed by Homing, June 7. 1982 2:55 pm
-- Use templates from Mesa.abbreviations

7.2. FugiemanClient.mesa
This is an example intended only to show syntactically how client programs create object instances.
invoke operations on them and catch signals that those operations might generate. The files
Fugleman.mesa and FuglemanImpl.mesa contain the definitions of the object interface used here and a
sample implementation of it, respectively.
FILE: FuglemanClienl.mesa
Last Edited by MitchelL August 16. /9822:04 pm
DIRECTORY

Fugleman USIN~ [Handle. NewFugleman. Check. SomeProc. FugleFailure]:'
FuglemanClient: CEDAR PROGRAM
IMPORTS Fugles: Fugleman =
BEGIN

TestError: ERROR:

=

SimpleTest: PROC
BEGIN
a nonsense program to show how clients invoke operations on objects implemented this way
fm: Fugles.Handle = Fugles.NewFuglemanO;
anotherFm: Fugles.Handle = Fugles.NewFuglemanO:
x: [NT .. 1:
fm.Check[ ! Fugles.FugleFailure = > ERROR TestError]:
-- check the object. convert error
IF fm=anotherFm THEN ERROR TestError: -- should get unique objects
[F fm.SomeProc[l] = anotherFm.SomeProc[2] THEN x"2;
END:

SimpleTest[ ]:

-- call the test procedure

END. -- FuglemanClient
CHANGE LOG

Created by Mitchell. March 27. 19809:23 AM
Produce exemplary template
Changed by Homing: June 7. 1982 2:58 pm
Cosmetic changes for conformance with current recommendations
Changed by Homing: June 8. 1982 2: 10 pm
Insert CEDAR prefix

9

7.3. FuglemanImpl.mesa
This is a template for an implementation of the class of objects defined by Fugleman.mesa. There
may be more than one implementation of this same class. An example of a client program can be
found in FuglemanClient.mesa.
FILE: Fuglemanlmpl.mesa
Last Edited by Mitchell. August 16. 19822:01 pm

DIRECTORY
Fugleman:
FuglemanStd[mpl: CEDAR PROGRAM
EXPORTS Fugleman =
BEGIN OPEN Fugleman:
Implementation types

=

Handle: TYPE
REF Rep: -- declare the concrete type locally
Rep: PUBLIC TYPE
RECORD(
count: INT.
flag: BOOLEAN .. TRUE.
mumble: INT];

=

FugleFailure: PUBLIC ERROR

= CODE;

New Fugleman: PtJBLIC PROC RETURNS [Handle] = BEGIN
RETURN [NEw[Rep .. (count: 5. mumble: -10)]]:
END;
Operations on a Fugleman

Print: PUBLIC PROC [h: Handle]

= BEGIN

-- some body would go here

END;

=

Check: PtiBLIC PROC [h: Handle]
BEGIN
IF h.count> 100 OR h.mumble 100 THEN otherArgument .. 100:
h.count .. otherArgument:
r .. 17:
END:
END. -- FugfemanStdlmpl
CHANGE LOG
Created by Mitchell: March 17. 1980 11:33 AM
Exemplary template

Changed by Homing: June 7, 19826:17 pm
Use Mesa.abbreviations

Changed by Homing: June 8. 1982 2: 15 pm
Fix the use of the exported opaque type. add CEDAR prefix

Changed by Mitchell: August 15. 1982 8:55 pm
added needed declaration of FugfeFailure

10

Ceda r Style Sheet
I~o common suffix on the names
of DEFINITIONS modules

I
I

- FILE; CedarSample.mesa
- Last edited by Mitchell. April 23. 1980 12;03 PM

~

Standard preludo for a module

_ Cedl'lrSample: DEFINITIONS •
BEGIN
upperLimit INTEGER .. 32; •• name the upper limit of an interval type
IntervnlTs: TYPE .. 1'0 .. uocerLimill: .. oreferred form for intervals

I

capitalize the first letter of module.
procedure. signal. or type names

r

Sample: TYPE.. REF SampIeRec;
SampleRec: TYPE .. RECORO[val: Value. next: Sample);

I Naming a type is better than using an
I anonymous type constructor.

SampieSet: TYPE .. REF SameleSetRecj
SampleSetRec: TYPE .. RECORD[hesd: Sample. count Value):

I Use a small set of ERRORs with an

Problem: ERROR rreason: ErrorCodel:

~ ErrorCode: TYPE" {damagedSample. caliingError. programError}:
I- New§ample: PROCEDURE [val: Value) RETURNS [Sample~

I error code parameter.

NewSampleSet: PROCEDURE RETURNS[nilSet: SampleSet):

I~Pitalize the first letter of each
~ IImbedded word of a multi·word name

RemoveSample: PROCEDURE[toBeRemoved: Sample. from: SampleSet)
RETURNS (inSet: BOOlEAN. setMlnus: SampleSetj;
.. ERRORs: Problem[damagedSample)
~
.. SIGNAls: ResumableCondition. SomeSlgnal
emptySet: SampleSet • NIL;
END.
This Is where a global description 01 the module goes
CHANGE LOG
Changed by: YourHame: OsteTlme
OescriptJonOfChange

~

I attach stylized comments to proce-

ISIGNAls.
dures thai generate ERRORs or

II

Standard posUude for a module
includes a history log of (non·trlvlal)
Changes to the module

- FILE: CedarSampie/mpl.mesa
- Last edited by Mitchell. April 23. 1980 3: 19 PM

PROGRAM module name is normaly
formed by suffixing interface name
with "Impl". Alternativaly. name may
be totally different than interface's

NO names in same scope differing
only by letter case distinctions except
a value with same name as its type but
with lowercase firstleller
Qualify identifiers from interfaces

DIRECTORY
Somelnterface USING [Som!Proc, SomeTe];
CedarSample;

-

CedarSampleimpl: PROGRAM IMPORTS SI: Somelnterface
EXPORTS CedarSample •
BEGIN geEN CedarSamelt:
Problem: ERROR[reason: ErrorCodej • CODE:

1
...r

I OK to use unnamed OPEN of Interf8CE
I if DIRECTORY entry has a USING list
I OK to OPEN interface that module
I implements

ResumableCondition: PUBLIC SIGNAL • CODE;
SomeSignal: PUBLIC SIGNAL .. CODE;

NewSample: PUBLIC PROCEDURE [val: Value) RETURNS [Sample) •
BEGIN
_
mel!; S!!!!I2Ig;
--1!':' SI.SomeTyee • 0:
IF val .. 0 THEN val" SI'SomeProc[x);

...

RETURN [sample):
END:
NewSampleSel: PUBLIC PROCEDURE RETURNS [nilSet SampleSetj •
BEGIN
nllSet .. AliocateSampleSet[ I AllocFault .. ) ERROR PrS!blem[e!:S!!ilramError]1:
nilSet .. [heed: NIL. count OJ;
END;

Keyword constructors. argument lists.
and extractors preferred for multiple·
component constructors

Bug: ERROR .. CODE:
RemoveSample: PUBLIC PROCEDURE [toBeRemoved: Sample, from: SampieSel)
RETURNS [inSet BOOlEAN. setMinus: SampleSetj •
.. ERRORs: Problem[damagedSample]
BEGIN OPEN SI:
Use REF ANY instead of variant
records and discriminate
calls on single-argument procedures
don't have 10 use keyword notation

~

P'

r--

IF ••. THEN ERROR Problem[dama9!i!!:!Same!!ll;
WITH refA!rtVar SELECT FROM
r: REF REAL .. )rt .. rt + 1.0;
I: REF INT .. )( ...
SorneProcM; ••• };
b: REF BOOlEAN .. ) SIGNAL R2!!!mableCondl!12ni
ENDCASS .. >ERROR Bug;

I Only let signals that are part of the

I abstraction escape out of it.

I OK to OPEN an Interface In a local
I scope where it is heavlfy used

rt

Only raise SIGNALs using SIGNAl,
and ERROR using ERROR

I NO using ENDCASE to handle a slng/4

I remaining
case: use as "OTHERWISE
or 10 generate an ERROR

...

END:
.. error for local use In this module
AIJggF!!!,!lt ERBQR .. CODE'
AllocateSampleSet: PROCEDURE RETURNS (uninltedSet SampleSet] ..
BEGIN

I OK to have locally defined ERRORs
I and SIGNAls

...

END:

END.
CHANG6LOG
Changed by: YourHame: OateTlme
OescriptionOlChange

JGM

16 AUG 82

Print on color printer il you can.

Filed on Pndlgo]Language>SlyleSheet.sil, .prE

BugBane . the Cedar Debugger
Russ Atkinson

May 27. /983 3:44 pm

BugBane is the standard debugging suppon in the Cedar environment. It is organized as a collection
of facilities. which include a simple Mesa expression interpreter. with .suppon for breakpoints and
uncaught signals.
BugBane is usually called from a Work Area. When the input focus is in a Work Area viewer you can
type Mesa expressions (preceeded by .. 4- "). Each expression is then evaluated and the results printed to
the typescript. Each value is assigned to an interpreter variable for later use.

I. The Mesa subset
The subset of Mesa expressions interpreted by BugBane is roughly described by the following list of
constructs. BugBane attempts to perform a reasonable amount of coercion to get values to agree with
their targets. This coercion is usually more than the compiled langauge provides.

1. 1.2. "abc". 'A. TRUE, $atom-- fixed. float. rope. char. booL atom constants
&x. foo. Foolmpl -- simple variables. according to search rules below
X.Y -- X is a record. ref to a record. pointer to a record. a global frame

x[YJ -- X is a sequence or array. ref or pointer to a sequence or array
Proc(x, ...J _. Proc is a procedure taking given arguments
Type[x• .•.1-- a record or array constructor (Type may be implicit)
:-.lEW [T

4-

expr) -- only in the local world

X op Y -- for op in {+. -. -. /, MOD}

op[x....J -- for op in {.'\{IN.
X

4-

Y --

~AX. ALL. LIST. CONS}

X and Yare expressions. 0

~

Y is permitted

II. Actions and multiple processes
Actions
In BugBane. an action represents the occurence of an uncaught signal (or error) or a breakpoint An
address fault is treated as an uncaught signal and is therefore also an action. When an action occurs,
the associated process is stopped. Other processes can continue. subject to the usual constraints (e.g.
monitor locks).
The occurence of a new action usually spawns (create~) a new work area or reuses an old work area.
When an action is associated with a work area the expression executed in that work area are interpreted
with respect to the call stack for that action. Setting of breakpoints. stack display. proceeding and
aboning are all performed with respect to that action.

Multiple processes

A process stack may only be examined by BugBane when the associated process is stopped. Any other
approach is highly unsafe. The DebugTool can be used to stop processes. Another way to stop a process
is to set a breakpoint in code that it executes. One difficulty with stopping processes by either method
is that the process may be holding a resource necessary for Bug Bane. Since no automatic method for
detenning these resources is available, the decision as to when and where to plant the breakpoint is left
to the user (sigh),
Procee.ding a breakpoint will continue with program execution. Proceeding an uncaught signal will
attempt to resume the signal (although there is no provision for resuming with arguments).

In.

Name lookup

Name lookup in Bug Bane differs from name lookup in Mesa. primarily because the facilities available
to the compiler are not available to the runtime. but also because there are more places to look at
runtime. Names are found only if they are the right case and in the current "context." A context is
like a search path. and is searched in the following order:
Debugger table lookup

The debugger name table contains a name to value association for identifiers. Aside from a few
special cases (like TRUE, FALSE, and some built-in types), all names in this table start with "&".
There is a separate debugger table. and hence a separate name space, for each work area.
Stack lookup (includina alobal frames)

A stack exists for every action. When a name is looked up from a work area associated with an
action the local frames (and associated global frames) are searched (last-created-first-found) for
names up to some reasonable depth (currently 8).
Interface DalDeS

For lookup of X in expressions of the fonn X.Y. Bug Bane will attempt to treat X as an interface
record and Y as a selector. This facility is quite new, quite slow, and somewhat frail. The user
should try to use implementation module names when this facility does not work:.
Global frame table
The global frame table is searched for global' frame names only in last-Ioaded-first-found order.
Variables in those global frames will not be found without qualification. The user should note that
multiple instances of global frames are not supported.
Default alobal frame

The default global frame is set whenever one evaluates the expression that is the simple global frame
name. Variables in that global frame will be found in this search. There is a separate default global
frame for each work area.

IV. Octal commands
The following commands are intended for use by experienced users. They are made available as
expressions. since they are applicable to contexts inherited from the interpreter (to allow for remote
debugging).
&ar(ptr,!en)
Ascii Read - Displays the Ascii characters starting at address plr for len characters. Values of

2

ptr that are smaller than 64K are interpreted as being MDS pointers.
&ars[ptr.lenJ
Ascii Read Short - Like &ar. but does not interpret values of ptr that are smaller than 64K as
MDS pointers.
&clob[gf,pcJ
CLear Octal Break - Clears the breakpoint set at the numerically specified global frame and
program counter.
&fm[patternJ
Find Matching - [f the pattern (as a ROPE literal) does not contain a period. &frn finds and
prints the names of the global frames whose names match the pattern (case does not matter).
[f the pattern does contain a period. &fm finds the matching components of matching global
frames.
&Iob[]
List Octal Breaks - List all of the current breakpoints that were set by &sob.
&ofc[gf.pc.bO.b l.b2.b3 •...• b9J
Octal Find Code - Starting at the specified global frame and program counter. find the program
counter for the given code bytes.
&or[ptr. len .. 4. width .. 16. base .. 8J
Octal Read - Displays the contents of memory in the given base starting at plr for the number
of units given by len. The value of width must be in {1.2.4.8.l6.32}. The value of base must
be in [2..36J. Values of ptr that are smaller than 64K are interpreted as being MDS pointers.
&orc[gf,pc.lenJ
Octal Read Code - Displays the code bytes (in octaL unfortunately), starting at the given global
frame and program counter for len bytes.
&ors[ptr,lenJ
Octal Read Short - Like &or. but does not interpret values of ptr that are smaller than 64K as
MDS pointers.
&ow[Ptr. word.len)
Octal Write - Writes the given 16-bit word into the given address for the number of words
given by len. Values of ptr that are smaller than 64K are interpreted as being MDS pointers.
&ows[ptr, word.lenJ
Octal Write Short - Like &ow. but does not interpret values of ptr that are smaller than 64K
as MDS pointers.
&pgf[gt]

Print Global Frame - Prints the components of the specified global frame.
&pltllt]
Print Local Frame - Prints the components of the specified local frame.
&so b[g f, pc)

Set Octal Break· Sets a breakpoint at the speicifed global frame and program counter.
&tgtlgt]

3

Trust Global Frame· "Trusts" the given number as a global frame. This allows examining or
setting named components. as in &tgf{gfJ.name.
&tllllt]
Trust Local Frame - "Trusts" the given number as a local frame. This allows examining or
setting named components. as in &tgflljJ.name.

V. Shortfalls
Perfonnaoce is ooly moderately acceptable.
Although there is substantial caching of results in AMTypes and in BugBane. the first time through for
many expressions may take a long time. particularly if the symbols are not available on your local disk.
Patience is the only current recommendation. although we are certainly concerned about performance.
One Dame • one global frame.
Recompiling and reloading a module will work only with very simple systems. BugBane only provides
a linear search space for global frame names (last loaded. first found). Therefore you can only find one
instance of a global frame with a given name.
Peculiar name interpretation.
BugBane has both better and worse interpretation of names than the compiler or CoPilot. Unlike the
compiler, BugBane knows nothing about OPEN. so many names that can be left unqualified in compiled
programs must be fully qualified for interpreted expressions. BugBane will search for names both in the
current call stack and in the global frame table.
Opaque types are Dot fuUy supported.
The mapping between opaque and concrete types is not supplied by the runtime system. This leads to
type clashes when you try to hand a value of opaque type to a procedure that expects a concrete type,
and vice versa. There is only one automatic coercion practiced. which is when a REF opaque is passed
to a routine that expects a REF concrete. [n this one case. the object carries the concrete type, and the
coercion is made automatically. In other cases. LOOPHOLE should be used as a work-around.
Some safe expressions are not yet supported.
SELECT expressions are not supported.

Very few expressions involving types are supported. and there
may always be a few shortfalls here. Statements are not supported. so catch phrases in expressions will
not work.
Variant record constructors are limited to positional notation (keyword notation is not supported).

LIST constructors are only partially implemented. since they ignore the zone option, and only work for
LIST OF REF ANY.

Object notation is supported for procedure invocation. but may not do all that the compiler does. In
particular, NIL as the first argument in object notation will not work.
Selection from interfaces is only partially implemented. The most likely result of not having the
appropriate module loaded or not having the inter face exported to the top level is that NIL will be
returned. It is also the result for I:'IILINE procedures.
There are no plans for Bug Bane to interpret more than expressions.
Some type constructors are not supported.

4

AMTypes does not allow the construction of types on the fly, so BugBane does not support type
constructors. This means that type constructors such as POINTER TO Foo cannot be interpreted. BugBane
does treat types as expressions where possible, so type constructors such as FooDefs.FooPointer are legal
(assuming that the symbols are available to BugBane). The difference is that with FooDefs.FooPointer
sufficient information is passed from the compiler to the runtime to allow interpretation of the type.
Some unsafe constructs are not supported.

[n particular:

DESCRIPTOR constructors and overlaid record constructors.
UNSPECIFIED and LONG
are discouraged. since they are both obsolete and buggy (CODE(LONG UNSPECIFIED) will
crash the compiler, for example).
UNSPECIFIED

Although LOOPHOLE is supported. no checking for lengths is provided. so you can really do terrible
things by typing the wrong thing. [t is, of course, your machine.
Procedure type equivalence is only partially implemented.

While this is essentially an AMTypes problem, it does impact BugBane users. Procedure types must
match exactly in order for a procedure to be an argument. [f you can't get the interpreter to understand.
use LOOPHOLE (sigh).
Remote debugging is a bit buggy.

We're working on it. [t is not possible to pass ROPE or ATOM constants to remote procedures. for
example. LIST, CONS, and NEW do not work for the remote world.
Context reporting is unreliable.

There are several parts to this problem.
1: The compiler performs certain optimizations. such as cross-jumping and constant folding, that
keep the object code from being linearly related to the source code. This drawback will not be
overcome for some time.
2: There is a long-standing bug in reporting locations inside of catch phrases.
3: Context reporting involving

INLINE

procedure and cross-jumped code is unreliable.

4: Due to a long-standing bug in the format of fine-grain tables. the source position of the last
statement in a procedure is not known. Therefore. when setting breakpoints on the last statement.
make sure that the selection points to the first character of the last statement.
The abstract machine has some rough spots.

This is a subset of the know problems.
1: The eval stack is not always empty between Statements. If the value of a variable has been
placed on the stack in one statement. it may be left on the stack for the next statement. Attempts
to set that variable may not work for the latter statement.
2: It may not be possible to form the address of a variable that does not occupy a whole word.
3: The program counter used to report breakpoints may be wrong by 1, which may cause the
previous statement to be reported as the location of the breakpoint.

VI. Recent changes
for Cedar 4.2

Remote debugging

5

Various bug fixes should improve remote debugging.

Bug fixes
Minor bug fixes only (panicularly to octal commands).

Structural merge
The octal commands mentioned above are now a standard part of InterpreterPackage. which is a
pan of the boot file.
.

Additional features
Expressions of the form v[tag). where v is an overlaid or computed variant record and tag is the
name of one of the variants. now coerce the record to be of the specified variant type.

for Cedar 4.1
Remote debugging
Remote debugging is supported through the use of DebugTool. a program by Andrew Birrell. Since
this tool is in the boot file. previous methods of remote debugging are now inoperative. There have
been significant bug fixes in this area. especially to remove problems when the remote world has
been booted. and the use of interfaces.

Structural split
BugBane.bed and BBV.bed have been rearranged into BugBaneBelow (lower-level modules) and
BugBaneAbove (higher-level modules). BugBaneBelow exports everything that BugBane used to
export except BBObjectLocation. BBDisableBrea1cs. BBAction. BBBrea1c. BBFocus. and BBNub.
BugBaneAbove exports everything that BBV used to export. plus the former Bug Bane interfaces not
exported by BugBaneBelow. Most clients should not notice the difference.

Bug fixes
Performance has improved somewhat. A few minor bugs have been repaired. Error messages have
been slightly improved.

Additional features
Array constructors. including ALL{exprJ. are supported. NEw(type" exprJ is supported.

~AX{expr•

.••J and MIN(expr• .••J are supported.
for Cedar 4.0
Remote debugging
Remote debugging is supported through the use of DebugTest. a program by Andrew Birrell. The
Cedar debugger will be automatically set up if Cedar is installed on the CoPilot volume. To run
the remote debugger in the Client volume. perform:
run AMProcessBasicImpl; run AMProcesslmpl: run OebugTest
OebugTest RemoteMachineName

Bug fixes
Minor bug

fix~

only.

Additional features
Variant record constructors now work (positional notation only).

for Cedar 3.5

6

Remote debugging

Remote debugging is now supported. although the user interface is quite incomplete. Actions may
now come from any enabled world.
To start listening to a remote machine, evaluate
BBNubImpl.FindWorld[name: name, new: TRUE), which will return a world (WorldVM.World) for
the named machine. A new action should appear from that machine (if it is set up for remote
debugging). Please note that invocation of remote procedures and some remote assignments
(especially those involving allocation and reference-counting) are not yet allowed.
Bug fixes

Minor bug fixes only.
Restructuring

BBObjectLocation is now implemented through the AMModel. This interface will probably disappear
completely in Cedar 4.0.

/0' Cedar 3.4
New approach to read-evai-print

Removing the default read-eval-print loop and the default error reporting provides greater separation
between Bug Bane facilities and Bug Bane clients (the UserExec & BBV). The choice of whether to
make a UserExec "stall" if it gets an error, to make it look at the new error. or to provide some
other service is no longer dictated by the code of Bug Bane.
BBV provides default reporting of new actions (breakpoints & uncaught signals). The user is able
to select the "current" action through the current menu interface. Facilities for displaying the
current stack and actions are also provided.
The UserExec provides an work area (evaluator) for each action. A work area is a read-eval-print
loop in the classic style. However. when a breakpoint or uncaught signal occurs for that evaluator
other work areas may be spawned in response.
All of these user interfaces should be regarded as experimental.
Separation of printing

Printing of TVs and types has been unified under the control of the 10 package maintainer (Warren
Teitelman). The implementation no longer appears in Bug Bane. Russ Atkinson will assist in
maintaining this package during the life of. Cedar 3.4. However, Warren should be consulted about
formatting.
New features
LOOPHOLE is now better supported.
LONG CARDINAL as the target

An implicit LOOPHOLE with a blank target now defaults to

BBV provides better error messages. It now reports the source version its wanted if it can't get the
right one.
Parsing has become a little faster. This is due to more cases handled by the quick-kill parser, and
caching of intermediate storage by the long-winded parser.
The load state is used instead of the G FT to establish global frame search order. This !'lrovide:. true
last-loaded-first-found search order. Caching of global frame searching is now substantially improved
as well.
. Non-started global frames can be found and manipulated much like started global frames.
It should now be possible to set breakpoints in viewers that view remote sources.

7

Coercion of REF opaque to REF concrete at procedure boundaries has been improved. Coercion of
REF ANY variables to REF something values has also been improved. Coercion between opaque and
concrete types is not otherwise supported.

Remote debugging
Most users should not see any changes from the Bug Bane changes in support of remote debugging.
Remote debugging is still not supported in Cedar 3.4.

lor Cedar 1.2
New features
LOOPHOLE is somewhat supported. Non-RC (reference containing) values of less than 3 words in
length can be freely LOOPHOLEd based on the target type. Therefore. LOOPHOLE is only useful when
constructing a procedure argument or assigning to a variable in either a global or local frame (not
a debugger variable). Explicit types for LOOPHOLE are not yet supported..
Some octal debugging features have been added.
useful in attempting to examine variables..

[n particular. Octal Read and Ascii Read are

Bug Bane now can access (through RTTypes) symbols files in the Cedar release that are not on the
local disk. This access should only be noticable if the server is down or especially slow.

Bug fixes
Improvements have been made (and bugs fixed) in signal handling and reporting. [n particular.
features regarding catch frames should now work.
The infamous doubled breakpoint problem (where a breakpoint would immediately recur upon
proceeding it) will not entirely disappear until the Trinity release of Pilot. The problem lies in the
interaction between breakpoints and page faults. In the meantime. the code is touched immediately
before proceeding the breakpoint to force it in.

8

The Cedar DebugTool
Version 4.2
Release as
Came from
Last edited

[lndigo]ReleaseProcedures.Press and .Bravo, for information on use of OF files
in the Cedar release process.

Simple DF File Format
A simple OF file is composed of some control lines and lines of the form:

Directory [host) 



For example.
Dir~tory

[Indigo)Cedar>pl.mesa! 13

2-0ct-80 15:43:09 PDT

specifies a specific version numb~r for the file server, and also lists the file's create-date. Note that a
file cannot have the name Directory. and upper- and lower-case differences are ignored.
Blank lines are 0 K and lines are treated as comments if they begin with "/1" or .. --".
The format of OF files is similar to that produced by the Local-List or Remote-List sub-commands in
the FileTool. You may make it almost identical by setting the options in the FileTool so that only the
file name and file create dates are listed.
.

Example DF File:
An example file might be named "Poplar.OF" and contain:

-- File Popiar.DF. ereaied 5-0el-80 19:48:32

Directory [Indigo]Cedar>
poplar.bcd!l6

. 3-0ct-80 13:26:28

DFFiles

checkpoint.bcd!3

3

24-Sep'-SO 11:14:26

AFiles.bcd!5

2-0ct-80 17:17:32

overviewdefs.bcd!6

2-0ct-80 17:16:16

coredefs.bcd!7

2-0ct-80 17:16:20

filepageusedefs.bcd!5

2-Oct-80 17:17:28

filepageusedefs.mesa! 1

26-Oct-79 12:45:39

filesystemdefs. bed! 5

2-0ct-80 17:17:31

filesystemdefs.mesa! 1

22-Oct-79 13:21:59

BringOver
[f the name of your ftle is "Poplar.DF", you type

BringOver Poplar.OF
to the Executive.
BringOver works as follows: It reads the OF tile one line at a time. It takes the remote ftle name, strips
off the directory information and looks to see if it is on the local disk. One of three things can happen:
(1) If the tile is not on the local disk. BringOverO will try to retrieve it.
(2) If the file is on the local disk. BringOver looks at the version on the local disk. If the create-date
on the local file differs from the the create date listed in the OF file, BringOver will try to retrieve
the remote version.
(3) If the create-date is omitted from the OF file. BringOver will ALWAYS try to retrieve the tile.
If you omit the [FS version number (e.g. "13"), BringOver will enumerate all the versions of that
particular tile looking for one with the correct create time. If there are no versions of the file you list
in the OF file on the remote host in the directory you specify, BringOver will give you a warning
message. [f there are files with the same name and none of the create-dates avaliable match that listed
in the OF tile, BringOver will give you a warning and offer to retrieve the latest version.
After running BringOver you can be sure the tiles listed in the OF file are on your local disk. and that
their create-dates agree with the create dates listed in the OF tile, or BringOver will have printed out
error messages.
Normally BringOver will list each file to be retrieved and wilLask for confirmation. (You may reply "y"
or CR to confirm, "n" to skip retrieval of this ftle, "q" to quit the BringOver program altogether. and
"a" to retrieve this tile and transfer subsequent tiles without further confirmation.) BringOver will
transfer all the files without confirmation if you provide the fa switch:

BringOver.- fa Poplar.OF
BringOver can read a remote OF file as easily as a local one:

BringOver.- [Indigo]Poplar.OF
reads Poplar.DF from the remote file server as specified. (If the host ftle system is "Indigo", the
"[Indigo)" can be omitted.)
As tiles are brought over, a property (called the RemoteFileName property) is added to their leader page
recording where the remote copy can be found. These properties can be printed out by the OFDisk
program (see below.)

DFFiles

4

Comments may be indicated by lines beginning with / / or --. as in the Poplar.DF example above. In
addition. BringOver will print comments at the end of the file after the last line listing files when it is
run. This way distributors of software can print out useful reminders to their users.
Instead of giving create dates
If the create date entry is a "- =" rather than a nonnal date. BringOver will retrieve the file only if the
version on the remote server is different than the version on the local disk. If the file is not on the local
'disk. it will be retrieved. For example.
Foo.Mesa

-=

If the create date entry is a ">" rather than a nonnal date. BringOver will retrieve the file only if the
version on the remote server is newer (or more recent) than the version on the local disk. If the file is
not on the local disk, it will be retrieved. For example.
Foo.Mesa

>

will .retrieve from the remote server only if there is a newer version on the remote server.
[ndired Use of Other OF Files
There are two common. distinct uses of one or more OF files by another. The first is syntactic inclusion.
similar to macro-expansion. where a OF file references another and all programs treat these OF files as
if they were a single OF file with the text of the inner OF file substituted in the outer one at the point
of reference. The second use is as an "Imponer" of another system, package. or set of files controlled
by someone else. By analogy with these concepts in Mesa. there are Exports as well.
The OF file syntax allows both forms of use. which are indicated by different keywords before the name
and date of the nested OF file.
Syntactic lnclusion

A line of the form
[nclude [hostjfile.OF Of 
will cause BringOver to invoke itself on file.OF at the point it encounters the [nclude statemenL If the
included file itself has an [nclude statement. then BringOver will again invoke itself on the inner OF file.
and so on. in a recursive fashion. Furthermore. the OF file is retrieved using the usual BringOver rules
before the recursive call.
Examples of Include:
Include [Indigo]CompilerSources.OF Of 2-Oct-81 15:43:09 POT
Include [IndigojCompilerObjects.OF Of >
(The Of keyword is optional, and the Include statement may be split on multiple lines.)
Exports and lmports

OF files users are encouraged to use a single D~ file for packages they maintain. Some, but usually not
all. of the files an implementor needs are also needed by users. or clients, of the package. Files that. are
useful to both users and implementors are said to be exported. These files are indicated by being listed
below a statement similar to the Directory statement:
Exports [hostl

DFFiles

5


Directory [hostj

BringOver normally examines all the files in a OF file (i.e. it assumes you are an implementor.) If you
are a user. you can get only those marked Exports by giving BringOver the /p switch:

BringOver /p Poplar.OF
Users often need to specify the /p and /a switches. The correct way to invoke BringOver is

. BringOver.- /a /p Poplar.OF
(Note the space before the /a and between /a and /p.)
When a OF flle needs to refer to other OF files as a user. it may have an Imports statement
Imports [hostJfile.df Of 
which causes BringOver to (1) retrieve file.df to the local disk if necessary and (2) examine all files
marked Exports in flle.df and retrieve them if necessary. Of course file.df may have Include or Imports
statements. so this is a recursive algorithm.
Sometimes the Exports files are too few or too many files and the user of a package would like to list
the files he/she needs from the imported OF flle. Appending a Using clause to the Imports statement.
analogous to the one in the Mesa language, gives the user explicit control over which files he/she needs:
Imports [host)Package.DF Of 
Using [list of files. separated by commas)
(The Of (dale) clause can be omitted.)
Use of the Using clause is strongly recommended. but is not required.
Examples of Imports:
Imports

[Indigol~Cedar>Pilot>PilotMesaFriends.OF

Imports [Indigo]CoPiloOCoPilotOF Of 24-Sep-8111:14:26 POT
Using [CPSwapDefs.Bcd. CPSwap2.Bcd1
As with the Include clause. the Imports statement (and Using clause) may span multiple lines.
In the CoPilot.OF example above. CPSwapOefs.Bcd and CPSwap2.Bcd can appear anywhere in
CoPilot.DF. (It does not matter whether they are Exports or not when a Using clause is used to access
them.)
The files referred to by an [mports statement may themselves be exported to the next outer DF file by
preceding the word Imports by the word Exports. This is useful when users of a package you maintain
need to have files from some other package in order to (e.g.) compile their system. You can import and
export these files to assure your users will have them.
Using Clause Semantics
Since. in general. CoPilot.OF (in the example above) may have internal structure (Le. it references other
OF files with Include and Imports lists), CPSwapOefs.Bcd and CPSwap2.Bcd may be defined in some of
the OF files referenced by CoPilot.DF. To avoid an explosion in search time, these restrictions apply
when using Using lists on a OF file with internal structure:

DFFiles

6

(1) A using list file (e.g. CPSwapDefs.Bcd) may be retrieved from a OF file included by an imported
OF file (e.g. included by CoPilot OF). (In other words. included OF files are treated as if they
were macro·substituted inUne in the top OF file.)
(2) A using list file may be retrieved from a OF file imported (without a Using list) by an imported
OF file (e.g.• imported without a Using list by CoPilotDF) as long as the file is exported in the
inner OF file. (I.e.• imports are significant one level below the top OF file. CoPilotOF.)
(3) A using list file may be retrieved from a OF file imported with a Using list by an imported OF
file (e.g.- imported with a Using list by CoPilotOF) as long as the using list file being retrieved also
appears on the inner using list. (I.e .• multiple. nested Using lists must intersect)
Useful Modes
A option (Iv) will run BringOver in verifY mode. where it will verifY that the files listed in the OF file
are present on the remote servers. (No files are retrieved in this mode.) If the file is listed correctly
and a local copy exists, BringOver will add the RemoteFileName property to the leader page. Note for
large OF files the verifY option takes a few minutes. BringOver will inform the user if there are newer
versions of files on the remote file servers. and will make a new OF file (on a file called "NewOFFile.OF")
listing the newer versions of files listed in the original OF file. If any files were listed in the OF file
without their IFS version numbers (e.g. 15). BringOver will make a new OF file with those version
numbers tilled in (also on "NewOFFile.DF").
An option (/0) will instruct BringOver to only BringOver the file(s) listed after the 10. For example.

BringOver 10 x.mesa files.df
will examine only the file "x.mesa" in flles.df, even if other files should be brought over. If no ..... is
given, BringOver will append ".Mesa", so this is equivalent to the preceding example:

BringOver 10 x f;les.df
More than one file can be listed after 10. in which case the last OF file on the command line is searched.
Five options are available to reduce the number of files that are retrieved when BringOver is run. Ib
causes BringOver to retrieve only those files that are "derived" from source files. Le. files that end in
".Bcd". ".Signals". ".Boot", and ".Press". Is causes BringOver to retrieve only non-derived files. i.e. all
files that do not end in ".Bcd" , ".Signals". ". Boot" , and ".Press", Ir causes BringOver to retrieve tiles
that are in directories marked ReadOnly in the OF file and to retrieve files that are imported from other
OF files. Iw is the inverse of Ir: only files that are not marked ReadOnly or imponed are retrieved.
Finally, lu causes BringOver to retrieve a file if a version is already on the local disk and the version
listed in the OF file differs from the version on the local disk.
The If option causes BringOver to ignore local files when it decides to retrieve a version of a file, thus
If "forces retrieval" of files on the local disk.
Other information about BriogOver
When the filename on a line in a OF file is preceded by a tilde (" - "), BringOver will retrieve the
indicated version if it is not present on the disk. If there is already a version on the disk. then it will
not be (Jverwritl.en. regardless of its create date.
BringOver listens for Control-DEL. When typed. BringOver will abort itself.
BringOver can handle OF files with fewer than 500 files.
Should you need to supply a connect name and password. BringOver will prompt you for them. When

DFFiles

7

a CR for the connect name and a CR for the connect password are typed. BringOver will ask if you
want to use a different login name or abon the program.
BringOver can be given a list of OF files on the command line. It will benave as if each file had been
given separately.
BringOver can be used to retrieve files that are not listed in OF files by putting them on the command
line

BringOver [Ivy]" or "- = ". chis file is ignored and will not be transferrEd.
If the OF file contains a reference to itself (e.g. System.OF lists "System.OF" as one of the files you
want), then SModel will also store a new version of the OF file on the remote server. Since SModel
has to write out a new OF file before it can store the OF file. SModel cannot put the IFS version
number (e.g. !5) on the OF file name in the case of self-referencing OF files. However, BringOver will

DFFiles

8

always get the correct version of the OF file since it will use the create-date of the OF file instead.
SModel will pause before storing each file and ask if it should go ahead. You may respond with "y",
"n", "q", or "a". "y" Il"~ans go ahead and store it, "n" means do not store this file and keep running.
"q" means do not store this file and stop running immediately. and "a" is like "y" except subsequent
questions will not be asked. and the "y" answer will be assumed. You can give the "/a" option on the
command line to SModel. e.g.
SModel la Poplar.OF
and all questions will automatically be answered "y".
ReadOnly files
When you don't want any of the files in a directory to be changed by SModel. regardless of any changes
you may make, you can indicate the files in the directory are read-only by preceding the Directory
keyword with ReadOnly. For example:
ReadOnly Directory [Indigo)System>
indicates the files listed below should NEVER be stored back on System>.
Maintaining Consistency
It is important to remember that SModel NEVER enumerates the remote file system, so SModel may not
detect that certain files listed in a OF file are not present on remote servers.
A common mistake is to assume that if you run SModel on a OF file successfully, and then simply
change a Directory in the OF file. then all the files will be transferred (again) to the new directory. This
is WRONG! After SModel has been run the fmt time the create dates listed in the OF file will agree
with the dates of the files on the local disk. Since SModel checks the create dates listed in the OF file.
on the second invocation SModel will not detect that any fIles need be transferred EVEN though the
Directory has been changed.
To resolve these problems. SModel will take a Iv option (Iv stands for verify.) If given this Iv option,
SModel will not only apply the algorithm described above to store files. but if it decides a file does not
need to be stored. it will look on the remote file server and check that in fact the file does not need to
be stored. If the file is not on the remote directory, or the version listed in the OF file is not on the
remote directory, then SModel will store the file. In this way SModel Iv will try to force the remote
directory to agree with the OF file.
Include and Imports
SModel will invoke itself recursively on OF files that are specified in Include statements (and
non-ReadOnly OF files preceded by @.) SModel will :"lOT invoke itself on OF files listed in Imports
statements (or on OF files listed in ReadOnly directories preceded by @.)
If the Include or Imports statement is not followed by an Of  clause. SModel will insen such a
clause in its output OF file with  replaced by the create date of the file on the local disk.
Release Option
If the Ip option is given. SModel will store all files listed in the OF file on subdirectories of
[Indigoj. The subdirectory will be the same as the subdirectory given by the ReleaseAs
statement. If the files listed in the OF file are normally stored on a working directory that is not
. the copy of the OF file on the local disk is not rewritted by SModel /p. If the normal

DFFiles

9

working directory of the files in the OF file is , then In is equivalent to Iv.
Other Options
1. The "In" option instructs SModel to do everything it would nonnally do BUT it never transfers any
files. For example,

SModel In Poplar.OF
2. If you give the "Is" option to SModel, it will store onto the remote server(s) all the files you've listed
in the OF file, except those marked ReadOnly, whether or not local create dates match the ones in the
OF file. For example,

SModel Is Poplar.OF
3. If the Ir option is given, then SModel will store files it decides should be stored by the above algorithm
even if the directory they are stored onto in marked ReadOnly.
Getting Started with SModel
New users are often confused about the relationship of the entries in a OF file to the local and remote
directories, and what SModel will do in certain cases. The easiest way to understand it is that SModel
assumes 1) that the OF file was an accurate description of the remote directory at some point in the past
and 2) files with differing create dates that it finds on the local disk are the "Truth" and that it should
transfer any files that are different. However. assumption # 1 allows SModel to assume that files with
the same create date in the OF file and on the local disk ALSO exist on the remote server. This
assumption is often not true when a new OF file is being created. To get started, there are at least these
things you can do:
1. Make a OF file of just file names (no create dates) and run SModel on it. The files will be transferred
and the create dates will be filled in.
2. Use VerifyOF (see below) to automatically generate a OF file, edit the OF file as you need to, and
use the Is option to store all the files out onto remote servers.
3. If you have a complete consistent world out on remote servers. simply retrieve all those files onto the
local disk and make a OF file with all their filenames but no create dates. Run SModel with the In
option to get the OF file filled in with all the create dates. (In will not needlessly make extra copies of
the files on your remote directories).
If you are maintaining a system for others, you may need to have entries in the OF file that are ReadOnly
(such as for Oefs>, etc.) Filling in all the create dates by hand is painful, so you may combine
the Ir and In options to fill in all the create dates in the OF file but not transfer any of the files! For
example,

SModel Ir In Foo.OF
will fill in all the create dates for files in Foo.DF but none will be stored.
CameFrom handling
SModel nonnally changes entries like
Directory [host2) CameFrom [host1)
into lines like
Directory [host1] ReleaseAs [hosr2]

DFFiles

10

and changes Imports like
Imports [hostl]file.DF Of 
CameFrom [host2j
into
Imports [hostl]file.DF Of 
since the CameFrom is inserted by the Release Tool. If you want to prevent SModei from making these
changes, give SModel the If option.
Other Information about SModel
SModel listens for Control-DEL. When typed. SModel will abort itself.
SModel handles Connect user names and passwords exactly as BringOver does (see above).
If a file is transferred. the RemoteFileName property (see above) is added to the leader page of the file
on the local <;lisk to record where a remote copy can be found.
Summary of options to SModel:
la
Ic

If
In

Ip
Ir

Is
It
Iv

Store files without asking the user for confirmation.
Try to write OF files that are compatible with Alto OF software. (No warnings are given if
this is impossible.)
Do not switch Came From clauses to ReleaseAs clauses and do not delete CameFrom clauses
from Imports.
Do everything it would normally do BUT never transfer any files.
Store fues on the  directory for the next Cedar release.
Ignore the ReadOnly attribute when deciding to store files.
Store all the files in the OF file. even if the create dates are correct
Do not invoke SModel recursively on inner, included OF tiles. Only examine the top OF
tile given.
Verify mode: Check every entry to see if it is correct Files will be stored onto remote
directories if necessary.

VerifyDF
VerifyDF attempts to answer the question: Does this OF tile have entries for all the files I need to .
rebuild this program? VerifyDF will analyze a .Bcd tile and compare the files recorded in the .Bcd with
entries in a OF tile. If a file entered in the .Bcd is not in the OF file, VerifyDF will give a warning
message about the omitted file(s).
To the Simple Executive. type

> VerifyOF"OFFile.OF Package.Bcd
where DFFile.DF is supposed to be a complete description of all the source files that were compiled
and bound to produce "Package. Bcd" . and all the object files produced while bu;lding "?ackage.Bcd".
Verify OF will analyze "Package.Bcd" and give warning messages about those files needed to build
Package. Bcd not listed in DFFile.DF. If Package.Bcd was produced by the Binder, VerifyDF will
complain if the .Contig file or if any of the implementation modules listed in the .Contig are not also
listed in "DFFile.DF". If Package. Bcd was produced by the Compiler. VerifyDF will complain if the
.Mesa source file or any of the Definitions Files (.Bcd's) it depends on are not listed. (A list of files

DFFiles

11

omitted is written to the screen and to a file "MissingEntries.OFFile.OF$". Similarly.. Mesa. .Bcd. and
.Config files that are not actually required to build "Package.Bcd" are listed.}
Once it .has analyzed Package.Bcd. VerifyDF will then analyze any .Bcd's needed by Package. Bcd
(described above). This analysis will continue until all .Bcd's that are referenced in the closure of the
dependencies among .Bcd's are analyzed.
[fthe OF file is omitted. VerifyOF will put a list of the top-level dependencies onto "MissingEntries.DF$~'.
which can then be given a more suitable name and VerifyDF can be invoked again. This is a simple
way to bootstrap a complete DF file for a package.
VerifyDF will look on remote file servers for the correct version of a Bcd file and will use the Leaf
protocol to read it page by page, so the Bcds do not necessarily have to be on the local disk for VerifyDF
to do its job.
Other Information about VerifyDF:
The DF file that describes a package may optionally have entries preceded by a "+ ". [f VerifyDF is
invoked without a .Bcd file it will look inside the DF file and assume that any file name preceded by a
" +" is a top-level Bcd and proceed to analyze it and all its dependencies. as described above. More
than one .Bcd may be preceded by a "+" sign. For example. if DFFile.DF had an entry of the form

+ Package. Bcd
then

VerifyDF DFFile.DF
will analyze "Package. Bcd" and all its dependencies.
The DF file(s) involved do not need to be on the local disk. For example. if DFFile.DF were stored
on [Indigo]DFFile.DF
is equivalent to retrieving OFFile.DF and invoking VerifyDF on the local copy.
VerifyDF has two options:
When given If. VerifyOF will write out a single OF file containing (1) the contents of the top-level
DF file. and (2) the entries this top-level DF file refers to using Imports and [nclude statements.
Thus If "flattens" the top-level DF file. (This is useful for generating DF files to input t6 ad hoc
DF parsers. such as the Cedar cross-reference program. etc.)
When given Ia. VerifyDF will retrieve any OF files referenced by the DF file being verified without
asking for confirmation. If la is not given. then the user will be asked to respond with either "y",
"n", "a", "1", or "q". "y" means retrieve the DF file. "n" means skip the Of file. "a" is like "y"
but subsequent OF files are retrieved as if "y" had been typed. "I" means use the copy of the Df
file on the local disk in place of the version listed in the OF file. and "q" means stop running
immediately.
VerifyDF listens for Control-DEL. When typed. VerifyDF will abort itself.

Summary of options to VerifyDF:
la
If

Retrieve DF files to the local disk without confinnation ..
Write out a single OF file containing all the parts included and imported by the top-level
OF file.

DFFiles

12

Summary of command lines for Pilot VerifyDF:
Verify OF DFFile.DF Package. Bcd

-- analyze Package. Bcd

Verify OF DFFile.DF

-- analyze files preceded by "+"
_. analyze Package.Bcd and construct a DF file

Verify OF Package. Bcd

DFDisk
DFDisk will produce a file "Disk.DF" that "describes an entire Pilot volume. It lists most of the files on
the Pilot volume (except files ending in $ and a few kinds of log files). If present the RemoteFileName
property is used to give a remote host and directory where the file may be found. Note reading leader
pages is slow, even on a Dorado, so expect DFDisk to take about two minutes.
OFDisk is most useful when used to print out the RemoteFileName property and when trying to save
all the files on your Client volume before you ~e·initialize the volume.
OFDisk listens for Control-DEL. When typed. DFDisk will abort itself.

DFDitT
DFDiff will take two files specified on the command line and compare them. If a file is present in the
first but not the second. it says the file is deleted. If a file is present on the second but not the first, it
says the file has been added. If the create dates differ for a file listed in both OF files DFDiff will print
a message to that effect. For example, if OldPoplar.DF and NewPoplar.DF are respectively old and new
"versions of the Poplar system,

oFoiff OldPoplar.oF NewPoplar.oF
will compare the two.
This is most useful when used with DFDisk, before and after major changes, and if the file output by
DFDisk (the first time it is run) is copied to some other file name like "SaveDisk.DF". Then

oFoisk
oFoiff Saveoisk.oF oisk.oF
will compare the two OF files and tell you what you've added or deleted.
DFDiff listens for Control-DEL. When typed. OFDisk will abort itself.

DeleteAll
The DeleteAll command will delete any tile on the local disk that does not match one specified in an
exception list.
If invoked with no arguments, DeleteAll uses an exception list on
BasicClientVolumeFiles.DF or BasicCoPilotVolumeFiles.DF (stored on [Indigo]B>

[Ivy]B>B.DF!5 '[Ivy]B>C.oF!6

would offer to delete all files on [Ivy]B> that are not entered in the same name and create date as
those listed in [Ivy]B>B.DF!S and [Ivy]B>C.DF!6. Should a file listed in a OF file be listed
or ». then flO versions of that file will be deleted.
without a create date (such as with -

=

The user may also enter "a" when asked whether to delete this file. When given "a," RemoteDeleteAll
will ask if you are sure you want to go ahead and then delete the remaining candidate files without
pausing for confirmation for each file.

ReleaseTool
The ReleaseTool should be run by the Cedar Release Master. Contact me for more information.

Other Information

DFFiles

14

You can find all the commands in Cedar .Bcd form on [Indigo]DFFiles>. All programs, except
the RemoteGetTool. will run in the Cedar Viewers and Cedar UserExec world.
You may retrieve the newest released versions of these Cedt'c OF programs by running

BringOver /p [Indigo]Top>OFFiles.OF
followed by

Run BringOver.Bcd
to load in the new version of BringOver.
Also. you may find newer. experimental versions on [Indigo]Top>*.OF. Use these at your
own riskl
All of these programs listen for control-DEL. When typed, they will abort themselves.
Should you need to supply a connect name and password, any of these programs will prompt you for
them. When a CR for the connect name and a CR for the connect password are typed, these programs
will ask whether you would like to login using different login credentials or abort the program.
If you get a message that begins with "Schmidt's Debugging:" you may safely ignore it-- these messages
are usually due to certain objects in memory not being freed properly.

Cedar Release Procedures
rrhe following section is an edited version of a set of messages written by Roy Levin and sent to Cedar
implementors in September 1981. Although the procedures described below are required of Cedar
implementors. many of the extensions added to OF files will be helpful for non-Cedar users as well.
Although it represents a restriction on OF file usage, I recommend non-Cedar users follow this style as
much as possible.]
Background
Releasing large systems is a tricky business. SOD has known this for a long time and has developed
elaborate release procedures to cope with the matter. We're only just discovering how messed up things
can get. However. since we have many fewer human cycles to expend on this problem than SOD does.
it is imperative that we devise natural. easy-io-use. and efficient (of people time) procedures for our
releases of Cedar.
'
Release Procedures
The [Indigo]PilotMesaPublic.df Of - =
in the OF file. There are several convenient OF files of this sort available. e.g.•
[Indigo]
PilotMesaPublic.df
PilotMesaFriends.df
ComSoftPublic.df
[Indigo] ReleaseAs [Indigo]

SpyNub.bcd



SpyClient.bcd



Directory [Ivy)SpyBuild> ReleaseAs [IndigojSpy>
Spy.df



SpyImplA.bcd



SpyImplA.mesa



Imports [Indigo]CoPUoOCoPilot.df Of 
Now suppose that a user of the Spy wants to retrieve the public files of the Spy.
The user types:

Br;ngOver /p [Ivy]" form of date specification was originally added to OF files. Implementors who tind
themselves in this predicament should use ">" instead of" #" where necessary.
It should also be understood that when the ReleaseTool is constructing the OF files to be stored on the
release directory. it will uniformly replace" #" and ">" specifications by explicit dates. This is important
for a release. since it is intended to be a snapshot of the state of the files at some instant of time. and
the loose binding implied by "#" and ">" is inappropriate. During the development process. however.
these "dynamically bound" date specifications are very useful. and it is unreasonable and unnecessary to
expect people to perform the manual tran~latlon to specific dates when release time arrives.
How. then. does this transformation of dates fit in with the ongoing development process? When an
implementor finds it necessary to change a component following a release. he/she has the choice of
starting from the OF tile on the release directory or from the one used to build the component in
preparation for the release. (Of course. the latter may validly disappear after the release: only the OF
tile on the release directory is guaranteed to be retained.) In the former case. the maintainer will have
to edit the released OF tile to make it convenient for subsequent development, e.g.• by adjusting Directory
headings to reference working directories and by replacing specific dates with" #" or ">". In the latter

DFFiles

18

case. the OF file is already (still) suitable for development work.

If a particular component is frequently
changed and usually by the same person, the latter approach will likely be followed. If the component
is infrequently modified or if many different people have occasion to change it, the former approach will
be less error-prone. The choice should be made on a package-by-package basis:

Complete Syntax Description of DF Files
Directory [hosl]
Exports [host]
ReadOnly [host]
Any of the above can be followed by ReleaseAs [hostl or Came From [host]. Exports,
ReadOnly, and Directory can be combined on one line. (Public is a synonym for Exports.)
jiJellll11Ul
(dIlte)
Multiple lines consisting of filenames and (optionally) create dates may follow Exports,
ReadOnly, and Directory headings. filename- may be preceded by "+ ", "@", and! or
{PublicOnly}. The filename may have a directory path (but no host), a shon filename. possibly
followed by a version number. The  can have the usual form, "- = ", "#", ">", or be
omitted.
Include [host]file.dflversion Of 
The Include statement may be followed by a ReleaseAs [host] or Came From [hosl]
statement. The Of  is optional.
Imports [host]fiie.dflversion Of 
Using [ list offilenames. separated by commas J
The Imports can be preceded by Exports. the Of  and Using [ ] can be omitted. and the
Using clause may be preceded by a Came From statement

Semantics of DF Files
All OF programs in this set use a consistent view of what a line in a OF file means. In summary, here
is a list of ways to specify files in a OF file:
jiJelltlme!vD'S



Any file on the remote directory with create time . If necessary, Of programs like BringOver
will enumerate the remote server looking for such a file. The version number vers (if present) is
used as a hint
jiJelltlme!vers

>

jiJellll11Ul!vers

#

jiJellll11Ul!vD'S

-

=

The highest version (IH). If - = or # is given, a program like BringOver will retrieve filename
from the remote directory if its create time differs from that of the tile on the local disk. The
except that the file will be retrieved
version number vers (if present) is used as a hint. > is like only if its create time is newer.

=

jiJellll11le!vers

When no date is present. and a version # is given. then this refers to the file filename on the remote
server with version number ! verso
jiJe~

DFFiles

19

When no date and no version number is present, then it is treated· like - =. (Except by SModel,
which tills in the local create time.)
The cases for OF tiles that are included or imported are exactly analogous.
For example.
Directory [Indigo]Dorado800ting.press

XEROX
Dorado bootstrapping is a complex process. involving a number of hardware. microcode. and
software components. This memo describes how to boot a Dorado and how to configure it to boot
A companion memo, "Dorado booting-implementation". file
in certain ways.
[Indigo). and is copied to [Indigo]Top> during each
Cedar release. Both Initial and Pilot microcode are installed using the Othello utility program.
Note that even though Othello is a Pilot program. it can be used to install any Initial microcode.
even if you don't have a Pilot file system on your disk; of course. you do have to have a Pilot file
system in order to install Pilot microcode.
The following is a sample dialogue for installing Initial and Pilot microcode:

Get into the Alto NetExec somehow.

> MesaNetExec CR
Wait a/ew seconds/or Ether booting.

> Switches: nCR
> OthelloOorado CR

do this only ifyou don't have a Pilot file system

Wait a/ew seconds/or Ether booting.

Othello 7.0 of 17-Jun-82 17:34:02
Please login ...
User: xxxxxx Password: xxxxxxCR ... GV ... OK
> Open Indigo CR
Indigo Parc IFS 1.36L, File Server of May 17. 1982
> Oi rectory Cedar>TopCR or Directory Dorado
> Initial Microcode Fetch
Drive name: ROO CR
File name: O~doInitialMesa.ebCR
Are you sure? res
Fetching ... done
> Pilot Microcode Fetch
Logical volume name: Othello CR
Pilot microcode file name: OoradoCedar.eb CR
Fetching ... installing ... done
Shall I use this for the physical volume? res

>

1.5 Recommended microcode configurations
There are many possible ways of configuring the microcode on a Dorado's disk.
configurations are suggested. though others are reasonable also.

The following·

For a Dorado running standard versions of Alto/Mesa. Lisp. or Smalltalk-76. and never running
Pilot/Cedar:

Dorado booting-operation

5

Initial microcode: Dorado InitiaIEtherMesa.eb. Dorado InitialEtherLisp.eb, or
DoradolnitialEtherSmalltalk.eb (Smalltalk-80 users should install
DoradolnitialEtherMesa.eb, as the Smalltalk-80 system loads its own microcode)
Pilot microcode: none
For a Dorado running non-standard versions of Alto/Mesa. Lisp, or Smalltalk-76, and never running
Pilot/Cedar:
Initial microcode: DoradoMesa.eb, DoradoLisp.eb, or DoradoSmalltalk.eb
Pilot microcode: none
For a Dorado running both an Alto-based emulator and Pilot/Cedar, and which is to boot the Altobased emulator by default:
Initial microcode: DoradoInitialEtherMesa.eb, DoradolnitialEtherLisp.eb, or
DoradoInitialEtherSmalltalk.eb
Pilot microcode: DoradoCedar.eb (invoked by booting with "P")
For a Dorado running Pilot/Cedar, and which is to boot Pilot/Cedar by default:
Initial microcode: DoradoInitialDisk.eb
Pilot microcode: DoradoCedar.eb
Regardless of what microcode is installed, booting with one of "C", "L", "M", "S", or "T" (or the
alternate RETURN, SHIFf, or ")") invokes the microcode designated by the depressed key; and this
microcode always comes from the Ethernet.
1.6 Microcode se/f-loading

The Dorado can also load its own microcode under program control. using a special instruction
(LoadRam) described in section 2. There exists a program called LoadMB that runs on the Dorado
(in Alto emulation mode) and loads microcode from a file on the Dorado's disk. The file must be
in MB (micro binary) format, as produced by MicroD, and the microcode contained within that file
must conform to certain conventions in order to be sott-bootable in this manner.
For example, the Mesa microcode is contained in a file called Mesa.MB. To load and start that
microcode. type:
>LoadMB Mesa.mb
This loads the Dorado's control store with the contents of Mesa.mb and then starts it at a special
entry point that causes it to reset 1/0 devices but does not disturb emulator execution or the
contents of main memory.
This means of loading microcode isn't very interesting for bootstrapping the standard emulators.
since the 3-push boot is easier and doesn't require the new microcode to be on your Dorado's disk.
But it is useful for loading non-standard or experimental emulators. (The LoadMB program has
The program is stored as
some other features. described in section 3.
[Indigo] LoadMB,run.)

Dorado booting-operation

6

1.7 Loading microcode using Midas

Each cluster of Dorados has an umbilical Alto that is able to control a connected Dorado for
purposes such as hardware checkout and microcode debugging. The Alto program that performs
these functions is called Midas.
Most Dorado users will have no occasion to use Midas. But if the normal microcode' bootstrap
mechanisms don't seem to be working, you can use Midas to load your desired emulator microcode.
If Midas is not already running, boot the Alto and type:
>Midas
Midas first displays a menu of the serial numbers of all the Dorados that are connected to this Alto.
Select your Dorado by positioning the cursor over your Dorado's serial number and clicking RED
(left or top mouse button). This step is skipped automatically if there is only one Dorado connected
to the Alto.
If the selected Dorado is running, Midas displays a status of "Running" and puts up a menu (near
the bottom of the screen) consisting of ABORT, DTACH, and EXIT items only. To halt the Dorado,
select ABORT.
Now Midas displays a large menu near the bottom of the screen. Select RUN-PROGRAM, and the
menu changes to a list of microprograms that you can run; these include CEDAR. LISP, MESA, and
SMALLTALK. Select one of those. The screen then goes blank while Midas loads the Dorado's
control store, a process that takes about a minute. After that, Midas starts the Dorado as if you had
initiated a 2-push boot.
Important: Do not leave Midas running on the Alto after you have loaded your microcode, because
multiple-push boots from the Dorado's keyboard don't work if Midas is controlling the Dorado.
Therefore. exit Midas by selecting the EXIT menu item.
The versions of emulator microcode stored on the Midas Alto's disk might not always be up-to-date.
If you are in doubt, update the microcode files by issuing the Executive command:
>@UpdateEmulators
which runs FTP to retrieve the current versions of all emulator microcode.
1.8 Machine status

There is a green light on the front panel of the Dorado that indicates the machine's present state, as
follows:
1 flash.

Bootstrap sequence in progress (power-on or 3-push boot).

2 flashes.

BootStrap sequence failed.

3 flashes. Transient power-supply problem-voltage or current was out-of-spec at least
once since the last boot.
4 flashes.

Present power-supply problem.

S flashes.

Dorado is in shut-down state (never booted. or shut down by 7-push boot).

6 flashes.

Dorado has overheated and shut itself down automatically.

7 flashes.

Midas has taken over control of the Dorado.

Dorado booting-operation
Continuously on. Bootstrap sequence is believed to have completed successfully. and there.
have been no occurrences of the conditions indicated by 3 through 7 flashes.
Continuously off.

Unknown but probably serious malfunction. or AC power turned off.

7

Lupine User's Guide
An Introduction to Remote Procedure Calls in Cedar
Version 1.0

by

Bruce Nelson
and

Andrew Birrell

XEROX
Computer Science Laboratory
Palo Alto Research Center

JulyS, 1982
[lndigo]Oocumentation>LupineUsersGuide.press
This document describes research software for Xerox intemal use only.

Lupine User's Guide-Version 1.0

2

Contents
1 Introduction
2
2 Translator Operation
3
6
3 Con,ersations, Encryption, and Secure Communication
4 Binding and Configuration
8
15
5 Crash Detection and Recovery
6 Parameter Passing
16
7 Interface and Parameter Restrictions
18
8 References
20
Appendix A: Public RPC Interfaces
21
Appendix B: Example Remote Interface and Stubs
2S

1 Introduction
Lupine is the translator for Cedar's [Cedar) remote procedure call mechanism. A thorough
understanding of remote procedure call (RPC) principles is assumed throughout this guide-indeed,
once-skeptica1 readers have assured us it is foolish to continue without adequate background.
Nelson's dissertation [RPC) provides more than the necessary foundation, as Lupine, not
surprisingly. resembles that thesis's Emissary mechanism closely (Lupine, however, includes no
orphan algorithms). Be particularly conversant with chapters 1 and 2, and section 5.4.

Relationship to Courier
Xerox's Office Products Division has its own RPC mechanism, Courier [CourierFS, CourierPS].
Courier is for use in standard Pilot [Pilot) environments and has its own Lupine-Uke translator,
Diplomat [Diplomat). The Courier system is supponed by OPD and is released with Pilot: it is the
product software RPC mechanism. Lupine, in contrast, is supponed by CSL for use primarily
within CSL and PARCo Lupine's remote calls execute in both the Cedar and Pilot environments.
are about ten times faster than Courier's, and are significantly easier to program.

Operational Overview
Lupine reads a compiled Mesa interface and mechanically writes four Mesa source modules that
implement the same interface remotely. For a given DEFINITIONS interface named Target, Lupine's
stub control interface and three stub modules are:

TargetRpcControi.mesa. This public definitions module contains declarations for the remote
binding of Target.
TargetRpcClientlmpLmesa. This program module executes in hosts that want to impon
Target.
TargetRpcClientImpl is the client stub module.
It exports Target and
TargetRpcControl.
TargetRpcBinderlmpl.mesa. This optional program module is used to instantiate and impon
a dynamically varying number of remote Target interfaces. It exports TargetRpcControl but
not Target. It depends on module TargetRpcClientlmpl.

Lupine User's Guide-Version 1.0

3

TargetRpcServerlmpl.mesa. This program module executes in hosts that want to export
Target. TargetRpcServerlmpl is the server stub module. It imports Target and exports
TargetRpcControl.
Appendix B contains an example of each of these generated modules. As you use this guide,
refer to appendix B as necessary for concrete examples.
To use the stub modules compiled from the generated programs. clients include them in
configurations on their clien~ and server hosts. Aside from these configuration modifications. the
only required program changes are two procedure calls to routines in TargetRpcControl. These
binding calls. discussed in detail later, cause the serving machine. to export Target and the client
machine to import it. This scenario is slightly more complicated with secure calls or multiple
instantiation. and much more complicated with dynamic crash recovery.
To establish bindings., make secure calls. and handle exceptions, Cedar RPC programmers use an
RPCRuntime package interface called RPC. There is a parallel interface, MesaRPC, for standard
Pilot programmers. Appendix A reproduces both of these interfaces.

Acknowledgments
Cedar's RPC mechanism is the work of two people: Andrew Birrell designed and wrote the
RPCRuntime package with its transport, binding, and secure communication subsystems; Bruce
Nelson designed the stub format and wrote the Lupine translator and diagnostic tools. In addition.
members of the Alpine and Voice projects-Mark Brown. Dan Swinehart, and Ed Taft. in
particular-made numerous good suggestions about parameter marshaling and multiple interface
instances. Dan was also a revealing alpha tester.
This guide is primarily Nelson's venture. with Birrell contributing material on secure
communication and remote binding.

2 Translator Operation
Installation
The Lupine translator runs in the Cedar environment (but a Tajo version would be trivial if
needed). To install Lupine and all the necessary RPCRuntime underpinnings, use Bringover to
retrieve the public components of [IndigojLupine.df.

Translation
Lupine reads the BCD of a compiled interface and writes four output files. At present, Lupine is
used from the Executive. although eventually it will be under the control of the Cedar system
modeller. Establishing a command file to translate each remote interface, or package of interfaces.
is recommended for now.

Lupine User's Guide-Version 1.0

4

The basic procedure is this:

When your target interface is ready for remote use. compile it:
>Compile Target
Feed the resulting interface to Lupine:
>Lupine Translatelnterface{" Target"]"
Compile the four stub modules. in this order:
>Compile TargetRpcControl TargetRpcClientlmpl, TargetRpcBinderlmpl
TargetRpcServerlmpl

Lupine records its translation progress in the Executive's window and log. The source and object
files for the stubs will be many times larger than the original interface, so be sure you have
sufficient space for them.
To abort a translation just type control-DEL.

Commands and Syntax
Lupine can be invoked from the command line or used interactively from the keyboard. There
is one real command., Transfatelnterface, and a number of option-setting commands. They are
presented here in procedural keyboard style. Consult a Lupine wizard before using a nondefault
value for any option except TargetLanguage, InterMdsCalls, InlineDispatcherStubs, and
LineLength.
OTranslatelnterface (fileName: STRING)
Lupine processes fileName.bcd. e.g., Target.bed.
<>TargetLanguage [language: STRING ~ "Cedar"]
TargetLanguage sets the programming language used to write the output fIles (do
not confuse the TargetLanguage command with the use of Target as an example
interface). The acceptable languages are Cedar and Mesa; Cedar is the default.
<>OefaultParameterPassing [method: STRING ~ "VALUE"]
This command sets the default parameter passing method to be VAR, VALUE,
RESULT, or HANDLE. (These are explained in a later section on Parameter Passing
Methods.) VALUE is the default. and take heed that this is different from Mesa's
de(ault semantics for address~containing values.
OlnterMdsCaUs [yes: BOOLEAN"

FALSE]

When InterMdsCails is true. the importers and exporters of Target must operatewithin the same host (the remote binder insures this), but can execute in different
MDSs. This tighter binding yields much faster parameter marshaling for addresscontaining parameters. Note, however, that intraMDS addresses such as POINTERs
and STRINGs are necessarily illegal in interMDS calls, and Lupine issues warnings if
they are used. The default is false.
<>lnlineOispatcherStubs [yes: BOOLEAN"

TRUE]

Lupine usually writes a single large procedure in the server stub program. For
large or complicated remote interfaces. however, the compiler can overflow when it
If this happens, setting
compiles this huge dispatcher procedure.

Lupine User's Guide-Version 1.0

5

InlineDispatcherStubs to false may cure the overflow problem by writing many
small procedures instead. If not, there two distasteful alternatives: either simplify
the troublesome interface, or split it into two smaller interfaces. The default is true.
(>FreeServerArguments [yes: BOOLEAN" TRUE]

When FreeServerArguments is true, Lupine automatically deallocates any
noncollected storage that it allocates to unmarshal arguments in the server stubs.
When false, it does not deallocate this storage, presumably because the underlying
server implementation is going to assume responsibility for deallocation itself. This
unSAFE feature is only.for Mesa-not Cedar-RPC interfaces that·use this contorted
allocation strategy. It applies only to arguments: storage for results is never
deallocated in either the client or the server. The default is true.
(>DynamicHeapNews [heap, mds: INTEGER .. 50, 50]

A Mesa remote interface can have parameters with a dynamic number of
noncollected objects (Le.. objects NEWed from the heap, such as a descriptor of
strings or a sequence of pointers). Lupine imposes a translation· time upper bound
on the total number of these dynamic objects allowed in the argument list-not
result list-of a single call. The default is SO heap (long pointer) objects and SO
mds (shon pointer) objects.
OLineLength [length: INTEGER" 82]
LineLength specifies the approXimate maximum length of source lines in the
generated output files. The default, 82, is a good choice for Viewers and Tajo.

There are additional debugging commands for wizards only. Type? at any point for a list of
possible commands or responses.

Command Files
The following example illustrates option·setting and translation in command files:
>Lupine DefaultParameterPassing[nVAR "] InlineDispatcherStubs[FALSE]
LineLength[eo] Translatelnterface[nTarget n]

Lupine Errors
Fonunately, because Lupine's input is compiler output, few translation errors are possible. Most
errors are caused by pai'ameter passing restrictions. Lupine reports errors both in the typescript and
in the output file itself. Error and warning messages in the typescript include the output file name
and character position of the error. and messages in the output file are preceded with .. # # # # # .. to
make them easy to spot Many errors cause an ERROR statement to be insened in the output file.
This prevents a bogus stub from executing when the result would be chaos. If you can't understand
a particular error message, see a Lupine wizard.
As mentioned above, if a set of stubs is too big to compile, the InlineDispatcherStubs option
may remedy the problem.

Lupine User's Guide-Version 1.0

6

Compiler Warnings
The compiler will occasionally issue warning messages about referenced but unused DIRECTORY
items as it compiles stub programs. . Lupine is a mechanical translator. and eliminating the spurious
warning" would be difficult. Live with them.

3

Conversatio~

Encryption., and Secure Communication

Lupine and the RPC runtime provide facilities for making secure remote calls. Such calls are
encrypted using the DES encryption algorithm [DES). The protocols used provide secure two-way
authentication without any passwords being passed in the clear [Needham-Schroeder]. Secure RPC
calls prevent an intruder from seeing the procedure names, parameters. or results of the calls; from
modifying calls in transit; from replaying previously valid calls; from observing passwords
(encryption keys) in transit; from observing the cipher text of known (or chosen) plain text.
Secure RPC communication is based on the concept of a conversation. A conversation takes
place between two authenticated Grapevine individuals. known as the originator and the responder
of the conversation.

RPC.Principal: TYPE = Rope.ROPE;
RPC.EncryptionKey: TYPE = BodyDeft.Password:
RPC.Conversation:TYPE = ... :
RPC.SecurityLevel = {
none,
authOnly.
ECB.
CBC.
CBCCheck};
RPC. GenerateConversation: PRoe RETURNS(Conversation);
RPC.startConversation: PROC [
caJler: Principal.
key: EncryptionKey.
calfee: Principal.
level: SecurityLeve~authOnly.. CBCCheck]]
RETURNS[Conversation);
RPC.EndConversation: PRoe [conversation: Conversation);
RPC.GetCaller: PAoe (conversation: Conversation) RETURNS [Principa4:
RPC.GetLevel: PROC [conversation: Conversation] RETURNS [SecurityLeve~;
RPC.ConversationID: TYPE [3];
RPC. GetConversationlD: PROC[conversation: Conversation]
RETURNS (id: ConversationlD);
RPC.AuthenticateFailed: ERROR [why: RPC.AuthenticateFailure];
A conversation is created by the originator calling RPC.StartConversation and is destroyed by the
originator calling RPC.EndConversation. The originator provides his own name and password and
the name of the responder. StartConversation communicates with Grapevine to verify the validity

Lupine User's Guide-Version 1.0

7

of these arguments; at this time there is no communication with the responder. See below for a
description of the SecurityLevel of a conversation. At present, the communication with Grapevine
does not use secure protocols.
Having created the conversation. the originator may now make secure calls to the .responder by
passing the Conversation as the first argument of any remote call to a procedure in an interface that
is exported by the responder. (The same conversation may be used to make calls in multiple
interfaces.) The RPC runtime guarantees that the call can be understood only inside a host
containing the authenticated responder and that the call will be received by the responder at most
once. The responder can determine the authenticated identity of the originator by calling
RPC.GetCaller when he receives a call having the Conversation as its first argument. Every
conversation is uniquely identified for all time by an identifier that either party may obtain by
calling RPC.GetConversationlD.
Calling RPC.StartConversation may raise the exception
AuthenticateFailed. with the following values for its argument:

communications Unable to contact Grapevine.
badCaller

The originator's name is not a Grapevine individual.

badKey

The originator's password was incorrect.

badCallee

The responder's name is not a Grapevine individual.

The procedure GenerateConversation may be called to obtain a Conversation to be used solely for
calls within a single machine; such a Conversation must not be used for remote calls.
The SecurityLevel passed to StartConversation indicates how much security the originator wants
for this conversation. The SecurityLevel of any conversation may be obtained by calling GetLevel.
The meanings of the conversation levels are as follows. none indicates that the conversation was
created by calling GeneraleConversation. and that no authentication or encryption has been
employed. authOnly will perform the authentication, but calls are not encrypted. and modification,
manufacture or replay of calls or results is not detected. ECB uses the ECB mode of DES [DES],
which protects calls and results from eavesdropping (and makes modifying. manufacturing or
replaying calls or results somewhat more difficult). ECB mode does not hide patterns of repeated
data within or between calls. C BC uses the CBC mode of DES [DES],. which behaves like ECB
except that it hides repeated data patterns. CBCCheck is like CBC. with the addition of a
checksum on each call and result; this prevents any eavesdropping, modification, manufacture or
replay of a call or result. CBCCheck should normally be used for secure communication, and
authOnly should normally be used for applications where only authantication is desired; the other
values of Security Level are advisable only -.yhere hardware or performance constraints dictate. At
present the DES algorithm is replaced by a trivial exclusive-or algorithm, because of the absence of
encryption hardware.

Lupine User's Guide-Version 1.0

8

4 Binding and Configuration
Lupine does not perform remote binding by using remote versions of the modeller or C/Mesa
binder [Mesa]. Instead, the modeller or binder are used to bind-locally-to an instance of
TargetRpcControl. A remote interface, say Target. is then bound remotely by calling binding
procedures in the TargetRpcControl interface. These procedures use the RPCRuntime. in
cooperation with Grapevine [Grapevine]. to perform remote binding. This is elaborated below. after
a discussion of remote interface naming.

Interface Names. Instances. and Versions
Naming remote interfaces is much more complicated than naming local-machine interfaces
because remote interfaces must be uniquely identifiable in a distributed environment. Furthermore.
ability to control the degree of typechecking is required for widespread systems such as Laurel (see
sections 4.1.3.1 and 4.1.3.4 in Nelson's thesis [RPC}). Lupine addresses this problem with
InterfaceNames. defined below. (ShortROPEs are discussed in the Parameter Passing section.)

RPC.ShortROPE: TYPE = Rope.ROPE;
RPC. VersionRange: TYPE = RECORD {first. last: CARDINAL];
RPc'matchAIIVersions: VersionRange = ...;
RPC.lnterfaceName: RECORD [
type: ShortROPE .. NIL,
instance: ShortROPE .. NIL,
version: VersionRange .. matchA.I/Versions];
RPC.defaultInterfaceName: InterfaceName = [];
InterfaceName.type
The type in an interface name specifies which interface is being exported or imported. This
is not a precisely defined concept. since it is up to the implementors of interfaces to
separate their interfaces into types, but it is intended to correspond to a single Mesa
definitions module. Only the implementor can decide at what stage in the incremental
development of an interface it should be considered as a new type. In the distributed
environment. there may be multiple exporters of a given type of interface. For example. if
the interface is for access to a printer. each printer would export the same type of interface.
These multiple interfaces are distinguished by their InterfaceName.instance. described
below.
The type of an interface may be a Grapevine R-Name. or an arbitrary string chosen by the
implementor. One approach is to use the corresponding definitions module name as the
type. The effects of using these forms of type are described below.

InterfaceName.instance
The instance in an interface name specifies which particu 1 ar one of the (potentially) many
instances of this interface is being named. For example. if the interface is for access to a
printer and is exported by each printer. each printer would export the same interface type
but a different interface instance.
The instance of an interface may be a Grapevine R-Name, or a host name (for example.
"Ivy"). or a Pup network address of the exporting host (for example. "3#17#"). The

Lupine User's Guide-Version 1.0

9

effects of using these forms of instance are described below.
Multiple remotely exported interfaces may have the same instance, provided that they each
have a different type and they are exported from the same host.

InterfaceName. version
The version in an interface name may be used to control the extent to which the remote
binder will check compatibility of versions between the exporter and importer. If the
exporter of a remote interface specifies [a,b] as the InterjaceName. version and the importer
specifies [c,a1. then the remote binding will be allowed to succeed only if the ranges [a..b]
and [c.• a1 have a non-empty intersection. However, RPC.matchAIIVersions is assumed to
intersect with every version range. That is, if RPC.matchAllVersions is specified by either
the importer or the exporter, then the remote binding will not fail because of version mismatch.
By using this facility, the implementors are asserting that they support, at a bit-wise
compatible level, multiple versions of an interface. This freedom is in marked contrast to
the Mesa binder (and loader), which insist on identity of versions for binding to succeed.
This extra freedom seems necessary in the distributed environment of RPC, but may well
be a fertile source of bugs.
To remain upward compatible with previous versions of an interface, you may add
procedures (or signals or errors) only at the end of the interface. You must not make any
significant changes to any types (for example. changing the order of fields in a record or of
parameters to a procedure is significant. as is adding fields or parameters). You may
change the names of things (like procedures, fields. parameters). You may also use this
version field to indicate semantic changes that do not involve changes to the definitions file.

Exporting
For interface Target, calling TargetRpcControLExportlnterjace causes Target (as specified by
interjaceName) to be exported for immediate remote use. Any attempts to import Target before
Exportlnterjace completes. or after Unexportlnterjace completes. will raise an exception (see the
description of importing, below). These two routines must be called in the strict sequence
Exportlnterjace. Unexportlnterface, Exportlnterface. .... Calling Unexportlnterjace has no effect on
calls in progress.

TargetRpcControl.Exportlnterjace: PROCEDURE [
interjaceName: InterjaceName .. defaultlnterjaceName,
user. RPC.PrincipaJ,
password: RPC.EncryptionKey,
parameterS/orage: Zones" standardZones];
TargetRpcControl. Unexportlnterjace:

PROCEDURE;

RPC.ExportFailed: ERROR [why: RPC.ExportFailure]:
The precise behavior of Exportlnterjace depends on the value of interfaceName. If the
interjaceName.instance is a Grapevine R-Name, the Grapevine registration service is consulted to
ensure that the instance is an individual whose connect-site is a. Pup net address for the exporting
machine. If necessary, the database is updated, using the given user and password as credentials. If

Lupine User's Guide-Version 1.0

10

the instance is not an R-Name (that is. it does not contain a dot). it should be either a Pup Name
Lookup Server name that maps to the exporting machine. or a Pup net address constant for the
exporting machine. If the interfaceName.type is an R-Name. the Grapevine database is consulted'
(and updated if necessary) to ensure that the type is a group. one of whose members, is the
inlerfaceName.inslance. At present, these actions on an itrterjilceName.type which \S an R-Ntuntl are
not implemented: every type is treated as just a string.
If you call Exportlnterface and default the interfaceName.type. Lupine will use for the type a'
combination of the interface name (for example. "Target") and the compiler's version stamp for the
interface. The default type is thus a unique name for the remote interface. and this uniqueness
permits the default version to be matchAllVersions - of which there can be just one.
Calling Exportlnterface with a defaulted interfaceName.instance is not yet supported; exporters
and importers must give an explicit instance each time. For simple experiments, it is convenient to
use your own Grapevine R-Name as the instance. and your own credentials as parameters to
Exportlnterface. For example:

mylnterjace: InterfaceName

=[instance: "Nelson.pa

n ];

--

Use default type &: version.

TargetRpcControLExportlnterface [
interfaceName: mylnterface.

user: "Nelson.pa".
password: Rpc.MakeKe}{ "Nelson's password"1 ];

If an attempt to export a remote interface fails. the exception ExportFailed is raised. No
monitors are locked when this signal is raised, so further caUs into the RPC runtime may be made
from catch-phrases. The parameter of the signal is one of the following:

communications Exporting failed because of inability to contact Grapevine or a Pup
Name Lookup server.

badType

The interjaceName.type was illegal (a Grapevine R-Name. but not a
group).

badlnstance

The interfaceName.instance was illegal (NIL, not a Grapevine R-Name.
not an individual. not a Name Lookup server name for this host. not a
net address constant for this host).

badVersion

The interfaceName. version was illegal (upper bound less than lower
bound).

tooMany

Too many current exports for local tables -

consult a Lupine wizard.

badCredentials The credentials were inadequate for updating the Grapevine database.
Importing
an
interface
Target
may
be
caused
by
calling
TargetRPCControLlmportlnterface or TargetRPCC0!ltrol.lmportNewlnterface, as described below.
In either case. an interfaceName is provided. which is interpreted as follows.
Remote

importing

of

Lupine User's Guide-Version 1.0

11

If interfaceName.instance is not NIL, then it must be: a Grapevine R-Name that is an individual
whose connect-site is a Pup net address. a Pup Name Lookup server host name, or a Pup net
address constant Each of these maps to a net address of a machine, which is assumed to be the
machine that has previously exported the desired interface. If that machine is running the Cedar
,"
RPC package and has exported an interface whose Inter/aceName has the same type and instance,
and whose version is compatible with the importer's interfaceName. version, then the import succeeds
and the importer's stub is now bound to the exporter's stub.
If inter/aceName.instance is NIL, then the remote binder will attempt to find any exported
interface whose type and version match those given in inter/aceName. If the type is a Grapevine RName, then it should specify a Grapevine group. The binder enumerates the members of that
group, obtains the network addresses that are the connect-sites of the members, and tries to bind to
them in tum until one succeeds. The order of these binding attempts is undefined, but is closely
related to hop-count and responsiveness. The algorithm usually chooses the nearest ins~ce of the
type that is operational. If the type is a Pup Name Lookup server name string, then this algorithm
is performed with the network addresses that are the value of that name. Importing with
interjaceName.instllnce = NIL is not yet implemented.
If an attempt to import a remote interface fails, the ERROR ImportFailed is raised. No monitors
are locked when this signal is raised, so further calls into the RPC runtime may be made from
catch-phrases. The parameter of the signal is one of the following:

communications Importing failed because of inability to contact one of: Grapevine, a
Pup Name Lookup server, the exporting host.
badType

The inter/aceName.type was illegal (inter/aceName.instance is NIL and
type is not a Grapevine R-Name of a group, and not a Name Lookup
server name).

badlnstance

The inter/aceName.instance was illegal (not a Grapevine R-Name, not an
individual. not a Name Lookup server name, not a net address
constant).

badVersion

The inter/aceName. version was illegal (upper bound less than lower
boun,d).

wrong Version

The exporter and importer version ranges don't overlap.

unbound

No currently running host has exported the appropriate type and
instance.

stubProtocoJ

The exporter and importer are using stub modules produced by
incompatible verisons of Lupine.

Importing One Remote Instance
For interface Target, calling TargetRpcControl.lmportlnter/ace causes Target (as specified by
inter/aceName) to be remotely imported for immediate use. In the C/Mesa sense, Target was
bound when TargetRpcC/ientlmpl, which exports Target locally, was bound. But remote binding is
not complete until Importlnterface is called. As a consequence, any attempts to use operations in

Lupine User's Guide-Version 1.0

12

Target before lmportlnterjace completes, or after Unimportlnterjace completes. will fail
unrecoverably. Calling Unimportlnterjace h~ no effect on calls in progress. These two routines
must be calle~ in the strict sequence Importlnterjace. Unimportlnterjace, lmportlnterjace, .... Note
that Importlnterjace[somelnterjace) will raise the exception RPC.lmportFailed..unbound) unless some
host has previously called Exportlnterjace[somelnterjacel.
TargetRpcConlrol.lmportlnterjace: PROCEDURE [ .
interjaceName: InterjaceName .. defaultlnterjaceName,
paramelerStorage: Zones" standardZones];
TargetRpcControl.Unimportlnterjace:

PROCEDURE;

RPC.lmportFailed: ERROR [Why: {... }];
Importing Multiple Remote Instances
For interface Target. calling TargetRpcControl.lmportNewlnterjace causes a new instance of
Target (as specified by interjaceName) to be created and remotely imported for immediate use.
Typically, each call of ImportNewlnterjace will specify a different value for interjaceName.instance,
thus binding to a different, distributed instance of the Target interface. The operations in this new
instanc~ must be accessed through the interjaceRecord that ImportNewlnterjace returns. not through
Target itself. as in the static importing case discussed above. (The Target interface is useless to RPC
programmers using multiple instances and should not even be referenced.) For example, if Target
contains
procedure
WritePages,
a
call
to
WritePages
must
be
written
interjaceRecord. WritePage~. ..). not Target. WritePage~ . ..J. Any attempts to use operations in
interjaceRecord before ImportNewlnterjace completes. or after UnimportNewlnterjace completes. will
fail unrecoverably.
Calling UnimportNewlnterjace has no effect on calls in progress.
UnimportNewlnterjace is available only for the Mesa target environment. In Cedar. discarded
remote interfaces are garbage collected. Note that ImportNewlnterjace[somelnterjace) will fail unless
some host has previously called Exportlnterjace[somelnterjace].
TargetRpcControl.lnterjaceRecord: TYPE REF RECORD [. _ .J;

=

TargetRpcControLlmportNewlnterjace: PROCEDURE [
interjaceName: InterjaceName .. defaultlnterjaceName.
parameterS/orage: Zones" standardZones J
RETURNS (interjaceRecord: InlerjaceR ecordJ;
TargetRpcControl. UnimportNewlnterjace: PROCEDURE [
interjaceRecord: InterjaceRecord]
RETURNS [nillnterjace: InterjaceRecord" NIL]; -- Only for Mesa, not Cedar.
RPC.lmportFailed:

ERROR

[why: {... }];

Importing Multiple Local Instances

true

When a distributed program deals with multiple remote instances. it is often
that one (or
more) of the instances will actually reside on the local host. In this case, perfonning remote calls to
the local instance can have an undesirable perfonnance impact. RPC programmers who want to
optimize "remote" calls to local dynamic instances can do so in a simple and transparent fashion:

Lupine User's Guide-Version 1.0

13

Copy and rename TargetRpcBinderlmp/ to be TargetLocalBinderlmpl.
Edit TargetLocalBinderlmpl. removing all the RPCLupine calls
ImportNewlnterface to NEW Targetlmpl and not TargetRpcClientlmpl.

and

changing

TargetRpcControl.lmportNewlnterface-as implemented by TargetLocaiBinderlmpi-now returns
an interfaceRecord for a local instance. not a remote one. The binding and communication
optimizations are transparent to users of 'TargetRpcControl and interfaceRecord. See a Lupine
wizard for more information.
Parameter Storage Zones,
To unmarshal certain parameters. Lupine's stubs must allocate private storage. This storage is
taken from zones that RPC programmers can specify at binding time. For simple interfaces a set of
standard zones is adequate. and thus the binding operations have default standardZones (below).
For production interfaces that use address-containing (AC) parameters frequently, however,
establishing special-purpose zones can increase performance significantly. If a remote interface uses
a large number of small AC objects (except for ropes, which get special treatment from the Rope
package), or it uses any large AC objects, consult a Lupine wizard.

RPC.Zones: RECORD [
gc: ZONE" NIL,
heap:

UNCOUNTED ZONE .. NIL,

mds: M DSZone .. NIL ];
RPC.standardZones: Zones =

D;

Madule Dependencies
The compile-time relationships of Target modules, Lupine's stub modules, and the RPCRuntime
packages are shown below. If module B is to the right of module A, then B depends on A.

RPC or MesaRPC
RPCLupine
LupineRuntime
RPCRuntime package
Target
Target's clients
Targetlmpl
TargetRpcConlro/
Target's remote binding modules
LupineRuntime (repeated from above)
TargetRpcClientlmpl
TargetRpcBinderlmpl
TargetRpcServerlmpl
DF Filesfor Remote Interfaces
As a general rule. Lupine.df exports all the Lupine. LupineRuntime, RPCRuntime, and Cedar
runtime components needed by remote programs. Thus OF files describing remote applications
should say [Exports] Imports Lupine.df to get all required components. although tailoring with a

Lupine User's Guide-Version 1.0
USING

14

list may be worthwhile.

Configurations Using Remote Inter/aces
Remote calls typically take place between independent hosts. and thus, for a given Target
interface, Target's client and implementation modules, along with the necessary stubs, must be split
between the cooperating hosts. A simple division of the Target service into remote TargetClient and
TargetServer C/Mesa configurations is illustrated below. Constructing corresponding Cedar models
would be similar.

TargetClienr. CONFIGURATION
IMPORTS

-- For Lupine-generated modules:

Atom. ConvertUnsafe. Heap. Inline. LupineRuntime. Rope. Ropelnline.
RPC Lupine. SafeStorage. UnsajeStorage,
-- For ClientRpclmportlmpl and TargetClientlmpl:
CONTROL
= BEGIN

ClientRpclmportlmpL TargetClientlmpl

TargetRpcClientlmpl: -- EXPORTS Target. TargetRpcControl.
TargetRpcBinderlmpl: - Optional. for multiple instances via ImportNewlnter/ace.
ClientRpclmportlmpl: -- IMPORTS TargetRpcControl. calls Import(New}/nter/ace.
TargetClientlmpl: --IMPORTS Target (one instance) or uses inter/aceRecord(for multiple).
END;

TargelServer: CONFIGURATION
IMPORTS

-- For Lupine-generated modules:

Atom. ConvertUnsafe. Heap. Inline. LupineRuntime. Rope. Ropelnline.
RPCLupine. SafeStorage. UnsafeStorage,
-- For ServerRpcExportlmpl and TargetlmpI:
CONTROL
= BEGIN

ServerRpcExportlmp/

TargetRpcServerlmpl: -- IMPORTS Target. EXPORTS TargetRpcControl.
ServerRpcExportlmpl; -- IMPORTS TargetRpcControl. calls Exportlnter/ace.
Targetlmpl: -- EXPORTS Target.
END;

The purpose of the user-written ClientRpclmportlmpl and ServerRpcExportlmpl modules is to
impon· and expon the remote Target interface by making calls on TargetRpcControl's
Import(New)lnter/ace and Exportlnter/ace routines. These trivial binding operations could just as
well be placed in TargetClientlmpl and Targetlmpl, or combined with the binding operations of
other remote interfaces into one master binding module. Note that these configurations do not
include the RPC runtime package. RPCRuntime.bcd. This package should normally be loaded
separately, because it is essential that only one copy of this package is loaded into any machine.
Check with current Cedar release documentation to see whether RPCRuntime.bcd is included in the
Cedar boot file.
It is sometimes advantageous to have both client and server configurations loaded into one host.
as for single-machine debugging. Such configurations must be specified cautiously, however, so that
remote imports and exports are not misconnected locally, shon circuiting all remote calls. The
easiest way to do this is to use nested configurations. as in the following example.

Lupine User's Guide-Version 1.0
TargetTestCombined:

15

CONFIGURATION

IMPORTS

-- For Lupine:
Atom. Convert Unsafe. Heap. lnline. LupineRuntime. Rope. Ropelnline.
RPC Lupine. SafeStorage. UnsafeStorage.
-- For Targetimpl. ClientImpl:
CONTROL
= BEGIN

TargetServer. TargetClient

TargetClient:
TargetServer:
END;

These TargetClient and TargetServer examples are simple; more elaborate configurations will be
commonly required. See appendix A of the Diplomat document [Diplomat] for further, more
complicated. examples, or consult a Lupine wizard.

5 Crash Detection and Recovery
A general discussion of crashes and crash recovery in the context of RPC is outside the scope of
this guide. The main reason is insufficient experience with distributed systems: there is no
widespread agreement on an RPC-Ievel crash recovery methodology, or, indeed. if such a
methodology is even needed or possible at this level. In currently operational distributed systems.
those with the best crash behavior appear to use highly application-specific techniques. See
Nelson's thesis [RPC] for more discussion (sections 4.1.1. 4.2.3, 5.1. 7.2).
RPC.CaIIFailed'.

SIGNAL

[why: RPC.CaIIFailure]:

Lupine's RPCRuntime uses the RPC.CallFailed exception to report crashes and other remote call
execution problems. This exception can be reported by any invocation of a remote procedure. or
on any signal of a remote signal or error. RPC programmers interested in continuous service must
therefore be prepared to catch CalIFailed on each remote operation. Recovery actions usually
consist of restoring some invariants before trying to rebind to another instance of the remote
interface. No monitors are locked when RPC.CaJlFai/ed is raised. so further calls into the RPC
runtime may be made from catch-phrases. The parameter of the signal is one of the following:
timeout

The other participant in the call is not responding to attempts to
communicate. The remote call mayor may not have taken place. Note
that this is not raised merely because the remote call takes a long time to
execute. The RPC runtime places no limit on the execution time of a
remote call. provided the server still responds to probes. A client can
terminate a call that is taking too" long by using the Abort mechanism of
the Mesa process machinery. . RPC.CallFailed may be resumed iff its
parameter is timeout.

unbound

The server has un3exported this interface, or has been restarted. since the
interface was imported. The call did not take place.

busy

After repeated attempts. the server is too busy to accept the call. The call
did not take place.

Lupine User's Guide-Version 1.0

protocol

16

The caller and server runtimes disagree about the communication protocol;
consult a Lupine wizard.

stubProtocol The caller and server stubs disagree about the communication protocol;
consult a Lupine wizard.
Note for experts: In servers, the RPCRuntime is prepared to catch CallFaiJed itself and abort
the incoming call that caused it. Thus if CallFaiJed is signalled out of a remote exception or a
callback (procedure parameter), and the exception or procedure was invoked by a remote call
executing in a server, the RPC programmer's server code does not have t-o catch CallFai/ure. The
RPCRuntime will automatically clean up and ignore the original call, if desired.

6 Parameter Passing
Semantics
For parameters that do not contain addresses. Lupine's parameter passing semantics are exactly
those of Cedar and Mesa: call-by-value. For address-containing (AC) parameters, however, Lupine
has four passing semantics: for arguments, VAR, VALliE, RESULT, and HANDLE; for results, just
VALUE. Each of these is a copy semantics: Lupine does not support reference semantics (call-byreference) between disjoint address spaces. Here is a brief description of each: the next secion has
examples:
VALUE. Value semantics cause the actual argument to be evaluated and assigned (copied) to
the formal argument at the time of invocation. For AC types used as RPC parameters, the
referent and not the address is used. For example, if p is a REF INT, then passing p by
VALUE uses the integer pt, not the pointer p (HANDLE passing would use just pl. NIL
semantics are preserve

[SEQUENCE • • • OF

Intensity]]:

=> [REF RECORD[SEQUENCE ••• OF

Intensity]]];

Anonymous record components and single-component records. Lupine cannot cope with
anonymous record components. (Anonymous parameters, however, are fine, except for
signal and error ai-guments.) Therefore unnamed, single- or multi-component, addresscontaining (AC) records will cause a translation error. To recover, just give the components
names.
Default values for variant records. Sometimes, to marshal a variant record, Lupine must
storage for it. Safety requires that the new record have an initial tag value, but Lupine
is not in a position to choose the correct one. An RPC programmer must therefore specify
a default value for the record in the record's declaration, even if Lupine's stubs are the only
place it is used. You needn't worry about this, however, until the compiler first complains
about it.
NEW

Record type declarations. To marshal certain records. Lupine must NEW each of the
embedded components. If one of these components is an explicit record specification (e.g.,
RECORD [re~ green, ... ]), and not a record type identifier (e.g., ColorRecord), the compiler
will report a type clash. If this happens, RPC programmers must redeclare all such records
to be record types.
Packed arrays of AC types. Lupine will properly translate these ill-used types (e.g., PACKED
but the compiler will not accept the result because of an @ applied to
the packed elements.
ARRAY OF STRING),

Lupine User's Guide-Version 1.0

8 References
[Cedar1

Cedar Language Committee.
Cedar Mesa-Version 6T5.
File [Indigo]Diplomat>Diplomat.press. version 5.0, 8' August 1980.
Envoy is an ancestor of Courier. so this document is somewhat dated.

[Grapevine)

Andrew Birren, Roy Levin, Roger Needham, and Michael Schroeder.
Grapevine, an Exercise in Distributed Computing.
Communications ofthe ACM25(4): 260-74, April 1982.

[Mesa]

James G. Mitchell, William Maybury, Richard Sweet.
Mesa Language Manuai.
Xerox PARC technical report CSL-79-3, version 5.0, April 1979.

[Needham-Schroeder1
Roger Needham and Michael Schroeder.
Using encryption for authentication in large networks of computers.
Communications ofthe ACM 21(12):993-99, December. 1978.
[Pilot1

Pilot Programmer's Manual.
Xerox Office Products Division, version 8.0, March 1982.

[RPC]

Bruce Nelson.
Remote Procedure Call.
Xerox PARC technical report CSL-81-9. May 1981.

20

21

Lupine User's Guide-Version 1.0

Appendix A: Public RPC Interfaces
The following are the public interfaces to Lupine's RPC runtime, RPC.mesa and MesaRPC.mesa.
Small details are likely to have changed since this document was last edited. so remember that
Lupine.df always refers to the latest version.
RPC.mesa
Andrew Birrell
BlM
DIRECTORY
Rope
MesaRPC

3-Dec-8t 10:14:28
29-0ct-81 11:46:31

USING [ROPE].
USING [AuthenticateFailure. CallFailure. Conversation.
ConversationID. ConversationLevel. EncryptionKey.
EndConversation. ExportFailure. GetLevel. ImportFailure.
GetConversationID. GenerateConversation. matchAllVersfons.
maxPrincipalLength. maxShortStringLength. SecurityLevel.
ShortSTRING. unencrypted, VersfonRange];

RPC; DEFINITIONS
IMPORTS MesaRPC
BEGIN

a

-- Short string/rope/atom types. Used only by Lupine clients.
maxShortStringLength: CARDINAL = MesaRPC.maxShortStringLength:
-- maximum length of ShortSTRING/ShortROPE/ShortATOM values -ShortSTRING: TYPE = MesaRPC.ShortSTRING;
ShortROPE: TYPE = Rope.ROPE;
ShortATOM: TYPE = ATOM;
-- Types for Import and Export calls.
InterfaceName: TYPE = RECORD [
e.g .• "AlpineAccess.Alpine"
type: ShortROPE ~ NIL.
instance: ShortROPE ~ NIL.
e.g .. "MontBlanc.Alpine"
version: VersionRange ~ matchAllVersions ];
defaultInterfaceName: InterfaceName
VersionRange: TYPE

a

[];

= MesaRPC.VersionRange;

matchAllVersions: VersionRange = MesaRPC.matchAllVersions;
-- Parameter storage zones.
Zones: TYPE
gc:
heap:
mds:

Used only by Lupine clients.

= RECORD [
ZONE ~ NIL,
UNCOUNTED lONE ~ NIL.
MDSZone ~ NIL ];

standardlones: Zones = [];
-- Encryption and Authentication facilities.
maxPrincipalLength: CARDINAL = MesaRPC.maxPrincipalLength;
-- Limit OR length of ropes used for Principal names -Principal: TYPE = ShortROPE;
EncryptionKey: TYPE = MesaRPC.EncryptionKey;
MakeKey: PROCEDURE [text: Rope.ROPE] RETURNS[EncryptionKey];
Conversation: TYPE = MesaRPC.Conversation;

Lupine User's Guide-Version 1.0
SecurityLevel: TYPE • MesaRPC.Securitylevel;
Conversationleve1: TYPE. MesaRPC.Conversationlevel;
unencrypted: Conversation • MesaRPC.unencrypted;
GenerateConversation: PROC RETURNS[Conversation] • INLINE
{ RETURN( MesaRPC.GenerateConversation[] ] }:
StartConversation: PROCEDURE[ca11er: Principal, key: EncryptionKey,
ca11ee: Principal,
level: ConversationLeve1 ]
RETURNS[conversation: Conversation]:
EndConversation: PROCEDURE [conversation: Conversation] • tNLINE
{ MesaRPC.EndConversation[conversation] }:
GetCaller: PROCEDURE [conversation: Conversation]
RETURNS [caller: Principal]:
GetLevel: PROCEDURE [conversation: Conversation]
RETURNS [level: SecurityLevel] • INlINE
{ RETURN[ MesaRPC.GetLeve1[conversation] ] }:
ConversationID: TYPE = MesaRPC.ConversationID:
GetConversationID: PROC[conversation: Conversation]
RETURNS(id: ConversationID] • INlINE
{ RETURN[ MesaRPC.GetConversationID(conversation] ] }:
PubliC signals:
AuthenticateFailure: TYPE • MesaRPC.AuthenticateFailure;
ExportFai1ure:

TYPE • MesaRPC.ExportFailure:

ImportFailure:

TYPE· MesaRPC.ImportFailure:

CallFailure:

TYPE • MesaRPC.Cal1Fa11ure:

AuthenticateFai1ed: ERROR[why: AuthenticateFai1ure]:
-- Raised by StartConversation -ExportFailed: ERROR[why: ExportFailure]:
-- Raised by ExportInterface -ImportFailed: ERROR[why: ImportFailure];
-- Raised by ImportInterface -CallFailed: SIGNAL[why: CallFailure);
Raised by any remote call; only why=timeout is resumable -END.

22"

Lupine User's Guide-Version 1.0
-- MesaRPC.mesa
Andrew Birrell
BZM
DIRECTORY
BodyDefs

23

3-Dec-8l 10:12:00
29-0ct-8l 11:45:47

USING[ maxRNameLength. Password ];

MesaRPC: DEFINITIONS

a

BEGIN
-- Short string types. Used only by Lupine clients.
maxShortStringLength: CARDINAL = 64;
-- Maximum length of ShortSTRING values.
ShortSTRING: TYPE = STRING;
-- Types for Import/Export calls
InterfaceName: TYPE • RECORD [
type:
LONG ShortSTRING ~·NIL. -- e.g. "AlpineAccess.Alpine"
instance: LONG ShortSTRING ~ NfL. -- e.g. "MontBlanc.Alpine"
version: VersionRange ~ matchAllVersions];
defaultInterfaceName: InterfaceName

= [];

VersionRange: TYPE = MACHINE DEPENDENT RECORD[first. last: CARDINAL];
-- client-defined. closed interval -matchAllVersions: VersionRange = [1.0];
-- importer: use any version; exporter: no versioning implied

-- Parameter storage zones.

Used only by Lupine clients. not the runtime.

Zones: TYPE = RECORD [
heap: UNCOUNTED ZONE ~ NIL.
mds: MDSZone ~ NIL ];
standardZones: Zones = [];
-- Encryption and Authentication facilities -maxPrincipalLength: CARDINAL = MIN[maxShortStringLength.
BodyDefs.maxRNameLength];
-- Limit on length of strings used for Principal -PrinCipal:
TYPE = LONG ShortSTRING;
-- Name of authentication principal -EncryptionKey: TYPE
-- DES key --

a

BodyDefs.Password;

MakeKey: PROC[text: LONG STRING] RETURNS[EncryptionKey];
Conversation: TYPE = LONG POINTER TO ConversationObject;
ConversationObject: PRIVATE TYPE;
SecurityLevel: TYPE
none(O).
authOnly(l).
ECB(2).
CBC( 3) •
CBCCheck(4)

MACHINE DEPENDENT {
cnauthenticated. insecure; used for "unencrypted"
authenticated. but unencrypted calls
authenticated, encrypt with ECB mode of DES
authenticated. encrypt with CBC mode of DES
authenticated. encrypt with CBC mode of DES + checksum

};

ConversationLevel: TYPE

= SecurityLevel[authOnly .. CBCCheck];

Lupine User's Guide-Version 1.0
unencrypted: Conversation = NIL;
Dummy conversation; may be passed to RPC runtime.
GetConversationID(unencrypted] = ERROR;
GetCa11er(unencrypted] = NIL:
Getleve1(unencrypted] = none; -GenerateConver$ation: PROC RETURNS(Conversation]:
Returns a handle for a previously unused Conversation. This
conversation is only for local use. it must not be passed to
the RPC runtime.
GetConversationID(GenerateConversation(]] = unique ID;
GetCal1er(GenerateConversation(]] • NIL;
Getleve1(GenerateConversation(]] = "none"; -StartConversation: PROC(ca11er: Principal. key: EncryptionKey.
ca1lae: Pr.incipa1.
level: Conversationleve1]
RETURNS(conversation: Conversation];
-- Obtains authenticator for conversation, registers it with runtime.
-- and allocates ConversationID -EndConversation: PROC(conversation: Conversation]:
~- Terminates use of this conversation -GetCa11er:

PROC(conversation: Conversation]
RETURNS(ca11er: Principal]:
Returns the caller name for a current call. The result
string has lifetime at least equal to the duration of the
call. Result is NIL if conversation's security level is "none" (including
conversation = "unencrypted"). --

Getlevel:

PROC(conversation: Conversation]
RETURNS[leve1: Securityleve1]:

ConversationID: TYPE(3];
-- UID allocated by initiator host -GetConversationID: PROC(conversation: Conversation]
RETURNS(id: ConversationID];
-- Returns permanently unique IO of this conversation

-- Public signals -Authenticatefai1ure: TYPE • (
communications,
couldn't contact authentication server(s) -badCa11er.
invalid caller name -badKey.
incorrect caller password
badCa11ee
invalid cal1ee name -};

Exportfai1ure: TYPE • {
communications,
couldn't access binding database -badType,
unacceptable interface type name -badInstance,
unacceptable interface instance name
badVersion.
statically silly version range -tooMany,
too many exports for local tables -badCredentials
not allowed to change the database --

}:

ImportFai1ure: TYPE = {
communications.
badType,
badInstance,
badVersion,
wrongVers ion,
unbound,
stubProtocol

couldn't access binding database -unacceptable interface type name -unacceptable interface in~tance name
statically silly version range -exported version not in req'd range
this instance not exported -exporter protocol incompatible with importer

} ;

Ca11Failure: TYPE
timeout,

{

no acknowledgement within reasonable time --

24

Lupine User's Guide-Version 1.0
unbound,
busy,
runtimeProtocol.-stubProtocol

server no longer exports the interface -server says it's too busy -user/server runtimes don't understand each other
user/server stubs don't understand each other --

}:

AuthenticateFailed: ERROR[why: AuthenticateFailure]:
-- Raised by StartConversation .ExportFailed: ERROR[why: ExportFailure]:
-- Raised by ExportInterface -ImportFailed: ERROR[why: ImportFailure];
-- Raised by ImportInterface -CallFailed:
SIGNAL[why: CallFailure]:
Raised by any remote call; only why=timeout is resumable -END.

25

Lupine User's Guide-Version 1.0

26

Appendix B: Example Remote Interface and Stubs
There follows a very simple interface. Target.mesa. and its stub modules as an example. Once
again. small details may have changed. but this is unimportant since RPC programmers need not be
concerned with stub implementations. These modules are un-retouched output from the Lupine
translator.
-- Lupine: example interface
-- Target.mesa
-. Andrew Birrell July 8, 1982 9:22 am
DIRECTORY
Rope
USING[ ROPE ]:
Target: DEFINITIONS

=

BEGIN
Basic: PROC:
Simple: PROC(first: INT. second: REF INT] RETURNS(a: Rope.ROPE. b: ATOM]:
Reason: TYPE

~

{ x. y. z }:

Exception: ERROR(why: Reason]:
Consultation: SIGNAL:
END.

Lupine User's Guide-Version 1.0
Stub file TargetRpcContro1.mesa was translated on
-- POT by Lupine of 7-Jul-82 17:14:26 POT.

27
8-Jul-82

9:59:49

Source interface Target came from file Target.bcd. which was created
on 8-Jul-82 9:59:46 POT with version stamp 52164#37310473537 from
source of 8-Jul-82 9:33:34 POT.
The RPC stub modules for Target are:
TargetRpcContro1.mesa:
TargetRpcC1ientImp1.mesa:
TargetRpcBinderImp1.mesa:
TargetRpcServerlmp1.mesa.
The parameters for this translation are:
Target language = Cedar:
Default parameter passing = VALUE:
Deallocate server heap arguments = TRUE:
In1ine RpcServerImp1 dispatcher stubs = TRUE;
Maximum number of dynamic heap NEWs = 50. MDS NEWs • 50:
Acceptable parameter protocols = VersionRange[1.1].
DIRECTORY
Rope.
Target.
RPC USING [defau1tInterfaceName. EncryptionKey. InterfaceName. Principal.
standardZones. VersionRange. Zones]:
TargetRpcContro1: DEFINITIONS
SHARES Target
= BEGIN OPEN Target. RpcPublic: RPC;
-- Public RPC types and constants.
InterfaceName: TYPE = RpcPublic.InterfaceName:
VersionRange: TYPE = RpcPublic.VersionRange;
Principal: TYPE • RpcPub1ic.Principal;
EncryptionKey: TYPE = RpcPublic.EncryptionKey;
Zones: TYPE = RpcPub1ic.Zones;
defau1tInterfaceName: InterfaceName = RpcPubl1c.defau1tlnterfaceName;
standardZones: Zones = RpcPublic.standardZones;
-- Standard remote binding routines.
ImportInterface: SAFE PROCEDURE [
interfaceName: InterfaceName ~ defau1tInterfaceName.
parameterStorage: Zones ~ standardZones ];
UnimportInterface: SAFE PROCEDURE;
Exportlnterface: SAFE PROCEDURE [
interfaceName: InterfaceName ~ defau1tInterfaceName.
user: PrinCipal.
password: EncryptionKey.
parameterStorage: Zones ~ standardZones ];
UnexportInterface: SAFE PROCEDURE;

Lupine User's Guide-Version 1.0

28

-- Dynamic instantiation and binding.
ImportNewlnterface: SAFE PROCEDURE [
interfaceName: InterfaceName ~ defaultlnterfaceName.
parameterStorage: Zones ~ standardZones ]
RETURNS [interfaceRecord: InterfaceRecord]:
InterfaceRecord: TYPE

~

REF InterfaceRecordObject;

InterfaceRecordObject: TYPE 2 RECORD [
Basic: PROCEDURE.
Simple: PROCEDURE [first: INT, second: REF INT] RETURNS (a: Rope. ROPE ,
b: ATOM].
Exception: ERROR (why: Reason].
Consultation: SIGNAL.
lupineDetails: PRIVATE REF LupineDetailsObject~NIL];
LupineDetailsObject: PRIVATE TYPE;
-- Definitions for the stubs.
LupineProtocolVersion: PUBLIC VersionRange
InterMdsCallsOnly: PUBLIC BOOLEAN

= (first:

= FALSE;

Procedurelndex: PRIVATE TYPE • MACHINE DEPENDENT {
LupineUnusedIndex (0). LupineLastIndex (3).
Basic (4). Simple (5)};
Sign.1Ind.x: PRIVATE TYPE = MACHINE DEPENDENT (
LupineUnusedInd.x (0). LupineLastlndex (3).
Exception (4). Consultation (5)};
END.

-- TargetRpcControl.

1. last: 1];

Lupine User's Guide-Version 1.0
Stub file TargetRpcC1ientImp1.mesa was translated on
-- 9:59:50 PDT by Lupine of 7-Jul-82 17:14:26 PDT.

29
8-Jul-82

Source interface Target came from file Target.bcd. which was created
on 8-Jul-82 9:59:46 PDT with version stamp 52#64#37310473537 from
source of 8-Jul-82 9:33:34 PDT.
The RPC stub modules for Target are:
TargetRpcContro1.mesa;
TargetRpcC1ientImp1.mesa;
TargetRpcBinderlmp1.mesa;
TargetRpcServerImpl.mesa.
The parameters for this translation are:
Target language = Cedar;
Default parameter passing = VALUE;
Deallocate server heap arguments = TRUE;
In1ine RpcServerImpl dispatcher stubs· TRUE;
Maximum number of dynamic heap NEWs = 50. MDS NEWs = 50;
Acceptable parameter protocols = VerSionRange[l.l].
DIRECTORY
Rope.
Target.
TargetRpcContro1 USING [InterMdsCa11s0n1y. LupineProtoco1Version.
ProcedureIndex. Signal Index].
RPC USING [InterfaceName. standardZones. Zones].
RPCLupine --USING SOME OF [Call. oataLength. Dispatcher. GetStubPkt.
-- ImportHand1e. ImportInterface. maxDataLength. maxPr1ncipa1Length.
-- maxShortStringLength. pktOverhead. ReceiveExtraPkt. SendPre1imPkt.
-- StartCa11. StartSigna1. StubPkt. UnimportInterface]--.
LupineRuntime --USING SOME OF [BindingError. CheckPktLength. CopyFromPkt.
CopyFromMu1tip1ePkts. CopyToPkt. CopyToMu1tip1ePkts. DispatchingError.
FinishThisPkt. ListHeader. Marsha1ingError. Marsha1ingExprError.
-- Ni1Header. Protocol Error. RopeHeader. RpcPktDoub1eWord. RuntimeError.
-- SequenceHeader. SHORT. StartNextPkt. StringHeader. StubPktDoub1eWord.
-- Trans1ationError. Unmarsha11ngError. Unmarsha1ingExprError. WordsForChars]--.
Atom --USING SOME OF [GetPName. MakeAtom]--.
ConvertUnsafe USING [AppendRope].
Heap USING [systemMDSZone].
RopeIn1ine --USING SOME OF [In1ineF1atten. NewText]--.
SafeStorage USING [GetSystemZone].
UnsafeStorage USING [GetSystemUZone];
TargetRpcC1ientImp1: MONITOR
IMPORTS RpcPrivate: RPCLupine. Lupine: LupineRuntime. Atom. ConvertUnsafe.
Heap. RopeIn1ine. SafeStorage. UnsafeStorage
EXPORTS Target. TargetRpcContro1
SHARES Target. TargetRpcControl. Rope
= BEGIN OPEN Target. RpcContro1: TargetRpcContro1. RpcPub1ic: RPC;

Lupine User's Guide-Version 1.0
-- Standard remote binding routines.
bound: BOOLEAN ~ FALSE:
myInterface: RpcPrivate.ImportHandle ~ NULL;
paramlones: RpcPubl1c.lones ~ RpcPubllc.standardZones:
ImportInterface: PUBLIC ENTRY SAFE PROCF'URE [
interfaceName: RpcPub11c.InterfaceName.
parameterStorage: RpcPublic.Zones ] ~
TRUSTED BEGIN ENABLE UNWIND => NULL;
.
IsNull: PROCEDURE [string: LONG STRING] RETURNS [BOOLEAN] ~
INLINE {RETURN( string-NIL OR string.length=O ]};
IF bound THEN Lupine.BindingError:
BEGIN
type: STRING = [RpcPrivate.maxShortStringLength]:
instance: STRING • (RpcPrivate.maxShortStringLength]:
ConvertUnsafe.AppendRope(to: type. from: interfaceName.type]:
ConvertUnsafe.AppendRope[to: instance. from: interfaceName.instance];
myInterface ~ RpcPrivate.Importlnterface (
interface: (
type: IF -IsNull[type]
THEN type ELSE "Target-62#64#37310473637"L.
instance: instance.
version: interfaceName.version ].
local0nly: RpcControl.InterMdsCalls0nly.
stubProtocol: RpcControl.LupineProtocolVersion ]:
END;
paramZones ~ [
gc: IF parameterStorage.gc # NIL
THEN parameterStorage.gc ELSE SafeStorage.GetSystemZone[].
heap: IF parameterStorage.heap # ~IL
THEN parameterStorage.heap ELSE UnsafeStorage.GetSystemUZone(].
mds: IF parameterStorage.mds # NIL
THEN parameterStorage.mds ELSE Heap.systemMDSZone ]:
bound +- TRUE:
END;
UnimportInterface: PUBLIC ENTRY SAfE PROCEDURE =
TRUSTED BEGIN ENABLE UNWIND => NULL;
IF -bound THEN Lupine.BindingError;
mylnterface ~ RpcPr1vate.UnimportInterface(myInterface];
paramZones ~ RpcPublic.standardZones;
bound ~ FALSE;
END:

30

Lupine User's Guide-Version 1.0
-- Remote public procedure stubs.
Basic: PUBLIC PROCEDURE a
BEGIN
ArgumentOverlay: TYPE a MACHINE DEPENDENT RECORD [
transferIndex (0): RpcControl.ProcedureIndex ~ Basic];
pktBuffer: ARRAY [1 .. RpcPrivate.pktQverhead+1] OF WORD:
pkt: RpcPrivate.StubPkt = RpcPrivate.GetStubPkt[space: ~pktBuffer];
argPkt: POINTER TO ArgumentOverlay a ~pkt.data[O];
pktLength: RpcPrivate.DataLength ~ 1:
lastPkt: BOOLEAN:
RpcPrivate.StartCall[callPkt: pkt. interface: myInterface]:
argPkt.transferIndex ~ BasiC:
[returnLength: • lastPkt: lastPkt] ':
RpcPrivate.Call[ pkt: pkt. callLength: pktLength.
maxReturnLength: O. signalHandler: ClientDispatcher]:
Lupine.CheckPktLength[pkt: pkt. pktLength: 0];
RETURN[];
END: -- Basic.
Simple: PUBLIC PROCEDURE [first: INT. second: REF INT] RETURNS [a:
Rope.ROPE. b: ATOM] =
BEGIN
ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
transferlndex (0): RpcControl.Procedurelndex ~ Simple. first (1):
INT]:
pktBuffer: ARRAY [1 .. RpcPrivate.pktOverhead+Z54] OF WORD:
pkt: RpcPrivate.StubPkt = RpcPrivate.GetStubPkt[space: 8pktBuffer];
argPkt: POINTER TO ArgumentOverlay a ~pkt.data[O]:
pktLength: RpcPrivate.DataLength ~ 3;
lastPkt: BOOLEAN;
RpcPrivate.StartCall[callPkt: pkt. interface: -mylnterface];
argPkt? ~ [first: first]:
BEGIN -- Marshal second: REF INT to pkt.data[pktLength].
pkt.data[pktLength] ~ secondaNIL; pktLength ~ pktLength+1;
IF second # NIL THEN
BEGIN
Lupine.StubPktDoubleWord[pkt. pktLength]? ~ second?:
pktLength ~ pktLength + Z:
END:
END: -- Marshal second.
[returnLength: . lastPkt: lastPkt] ~
RpcPrivate.Call[ pkt: pkt. callLength: pktLength.
maxReturnLength: 254. s1gnalHandler: ClientDispatcher];
pktLength ~ 0;
BEGIN -- Unmarshal a: Rope.ROPE from pkt.data[pktLength].
ropeIsNIL: Lupine.NilHeader;
IF pktLength+Z > RpcPrivate.maxDataLength
THEN pktLength ~ Lupine.FinishThisPkt[pkt: pkt. pktLength:
pktLeng th] ;
ropeIsNIL ~ pkt.data[pktLength]; pktLength ~ pktLength+1;
IF ropeIsNIL
THEN a ~ NIL
ELSE BEGIN
ropeLength: Luptne.RopeHeader;
textRope: Rope.Text:
ropeLength ~ pkt.data[pktLength]; pktLength ~ pktLength+1:
IF ropeLength > LAST[NAT]
THEN Lupine.UnmarshalingError;
a ~ textRope ~ RopeInline.NewText[size: ropeLength];
pktLength ~ Lupine.CopyFromPkt[pkt: pkt. pktLength: pktLength.
dataAdr: BASE[DESCRIPTOR[textRope.text]]. dataLength:
Lupine.WordsForChars[ropelength).
alwaysOnePkt: FALSE];
END; -- IF ropeIsNIL.
END; -- Unmarshal a.
BEGIN -- Unmarshal b: ATOM from pkt.data[pktLength).
pNameOfAtom: Rope.ROPE;
ropeIsNIL: Lupine.NilHeader;
IF pktLength+2 > RpcPrivate.maxDataLength
THEN pktLength ~ Lupine.FinishThisPkt[pkt: pkt. pktLength:
pktLeng th] ;
ropeIsNIL p pkt.data[pktLength]; pktLength ~ pktLength+1;

31

Lupine User's Guide-Version 1.0
IF ropeIsNIL
THEN pNameOfAtom ~ NIL
ELSE BEGIN
ropeLength: Lupine. RopeHeader;
textRope: Rope.Text;
ropeLength ~ pkt.data(pktLength]; pktLength ~ pktLength~l;
IF ropeLength > LAST[NAT]
THEN Lupine.UnmarshalingError:
pNameOfAtom ~ textRope ~ RopeInline.NewText[size: ropeLength];
pktLength ~ Lupine.CopyFromPkt[pkt: pkt. pktLength: pktLength.
dataAdr: BASE(DESCRIPTOR[textRope.text]]. dataLength:
Lupine.WordsForChars[ropeLength].
alwaysOnePkt: FALSE]:
END; -- IF ropeIsNIL.
b ~ Atom.MakeAtom[--pName:-- pNameOfAtom];
END; -- Unmarshal b.
Lupine.CheckPktLength[pkt: pkt. pktLength: pktLength]:
RETURN(a. b]:
END: -- Simple.

32

Lupine User's Guide-Version 1.0

33

-- Remote public signals and errors.
Exception: PUBLIC ERROR [why: Reason]
Consultation: PUBLIC SIGNAL

CODE;

= CODE;

-- Public signal and error dispatcher.
ClientDispatcher: --PROCEDURE [pkt: RPCPkt, call1ength: DataLength,
-- lastPkt: BOOLEAN, localConversation: Conversation] RETURNS [returnLength:
-- Datalength]-- RpcPrivate.Dispatcher =
BEGIN
SELECT lOOPHOlE[pkt.data[O], RpcControl.SignalIndex] FROM
Exception => RETURN[
ExceptionStub[pkt: pkt, call1ength: callLength, lastPkt: lastPkt,
localConversation: localConversation]];
Consultation => RETURN[
ConsultationStub[pkt: pkt, call1ength: call Length. lastPkt:
lastPkt. localConversation: localConversation]];
ENDCASE => RETURN[Lupine.DispatchingError[]];
END;

-- ClientDispatcher

Public signal and error dispatcher stubs.
ExceptionStub: --ERROR [why: Reason]-- RpcPrivate.Dispatcher =
INLINE BEGIN
ArgumentOverlay: TYPE • MACHINE DEPENDENT RECORD [
transferIndex (0): RpcControl.SignalIndex. why (1): Reason];
argPkt: LONG POINTER TO ArgumentOverlay = Ipkt.data[O];
Lupine.CheckPktlength[pkt: pkt. pktLength: 2];
ERROR Exception[argPkt.why];
END; -- ExceptionStub.
ConsultationStub: --SIGNAl-- RpcPrivate.Dispatcher =
INLINE BEGIN
pktlength: RpcPrivate.Datalength;
Lupine.CheckPktlength[pkt: pkt. pktlength: 1];
SIGNAL Consultation[];
pktLength .. 0;
RETURN[returnlength: pktlength];
END;
ConsultationStub.
-- No module initialization.
END.

-- TargetRpcClientImpl.

Lupine User's Guide-Version 1.0
Stub file TargetRpcServerImpl.mesa was translated on
-- 9:59:52 PDT by Lupine of 7-Jul-82 17:14:26 PDT.

34
8-Jul-82

Source interface Target came from file Target.bcd, which was created
on 8-Jul-82 9:59:46 PDT with version stamp 52#64#37310473537 from
source of 8-Jul-82 9:33:34 PDT.
The RPC stub modules for Target are:
TargetRpcControl.mesa;
TargetRpcClientImpl.mesa;
TargetRpcBinderImpl.mesa;
TargetRpcServerImpl.mesa.
The parameters for this translation are:
Target language = Cedar;
Default parameter passing = VALUE;
Deallocate server heap arguments = TRUE;
Inline RpcServerImpl dispatcher stubs = TRUE;
Maximum number of dynamic heap NEWs = 50, MDS NEWs = 50;
Acceptable parameter protocols = VersionRange(1.1].
DIRECTORY
Rope.
Target.
TargetRpcControl USING [InterMdsCallsOnly, LupineProtocolVersion.
ProcedureIndex. SignalIndex].
RPC USING [EncryptionKey, InterfaceName. Principal, standardZones.
Zones] •
RPCLupine --USING SOME OF [Call. DataLength. Dispatcher. ExportHandle.
-- Exportlnterface, GetStubPkt. maxDataLength, maxPrincipalLength,
-- maxShortStr1ngLength, pktOverhead, ReceivefxtraPkt. SendPrelimPkt.
-- StartCall, StartSignal. StubPkt, UnexportInterface]--.
LupineRuntime --USING SOME OF [BindingError, CheckPktLength. CopyFromPkt.
CopyFromMultiplePkts. CopyToPkt. CopyToMultiplePkts. DispatchingError.
FinishThisPkt. ListHeader. MarshalingError, MarshalingExprfrror.
-- NilHeader, Protocol Error. RopeHeader. RpcPktDoubleWord. Runt1meError.
-- SequenceHeader. SHORT. StartNextPkt. StringHeader. StubPktDoubleWord.
-- TranslationError. UnmarshalingError. UnmarshalingExprError. WordsForChars]--.
Atom --USING SOME OF [GetPName. MakeAtom]--.
ConvertUnsafe USING [AppendRope].
Heap USING [systemMDSZone].
RopeInline --USING SOME OF [InlineFlatten. NewText]--.
SaleStorage USING [GetSystemZone].
UnsafeStorage USING [GetSystemUZone];
TargetRpcServerImpl: MONITOR
IMPORTS Target. RpcPrivate: RPCLupine. Lupine: LupineRuntime. Atom.
ConvertUnsafe. Heap. Ropelnline. SafeStorage. UnsafeStorage
EXPORTS TargetRpcControl
SHARES Target. TargetRpcControl. Rope
= BEGIN OPEN Target. RpcControl: TargetRpcControl. RpcPublic: RPC;

Lupine User's Guide-Version 1.0
-- Standard remote binding routines.
bound: BOOLEAN ~ FALSE;
myInterface: RpcPrivate.ExportHandle ~ NULL;
paramZones: RpcPublic.Zones ~ RpcPublic.standardZones;
ExportInterface: PUBLIC ENTRY SAFE PROCEDURE [
interfaceName: RpcPublic.InterfaoeName.
user: RpcPublic.Principal.
password: ,RpcPub 1 i c . Enc rypt ionKey •
parameterStorage: RpcPublic.Zones ] z
TRUSTED BEGIN ENABLE UNWIND ~> NULL;
IsNull: PROCEDURE [string: LONG STRING] RETURNS [BOOLEAN] =
INLINE {RETURN[ string=NIL OR string.lengthaO ]};
IF'bound THEN Lupine.BindingError;
BEGIN
type: STRING = [RpcPrivate.maxShortStringLength];
instance: STRING = [RpcPrivate.maxShortStringLength];
userString: STRING = [RpcPrivate.maxPrincipalLength];
ConvertUnsafe.AppendRope[to: type. from: interfaceName.type]:
ConvertUnsafe.AppendRope[to: instance. from: interfaceName.instance];
ConvertUnsafe.AppendRope[to: userString. from: user]:
myInterface ~ RpcPrivate.ExportInterface [
interface: [
type: IF -IsNull[type]
THEN type ELSE "Target-52#64#37310473537"L.
instance: instance.
version: interfaceName.version ].
user: userString. password: password.
dispatcher: ServerDispatcher.
localOnly: RpcControl.InterMdsCallsOnly.
stubProtocol: RpcControl.LupineProtocolVersion ]:
END:
paramZones ~ [
gc: IF parameterStorage.gc # NIL
THEN parameterStorage.gc ELSE SafeStorage.GetSystemZone(].
heap: IF parameterStorage.heap # NIL
THEN parameterStorage.heap ELSE UnsafeStorage.GetSystemUZone[].
mds: IF parameterStorage.mds # NIL
THEN parameterStorage.mds ELSE Heap.systemMDSZone ]:
bound ~ TRUE:
END;
UnexportInterface: PUBLIC ENTRY SAFE PROCEDURE =
TRUSTED BEGIN ENABLE UNWIND => NULL:
IF -bound THEN Lupine.BindingError:
myInterface ~ RpcPrivate.UnexportInterface[myInterface]:
paramZones ~ RpcPublic.standardZones;
bound ~ FALSE;
END;

35

36

Lupine User's Guide-Version 1.0
•. Public procedure dispatcher and public signal and

e~ror

catcher.

ServerOispatcher: --PROCEDURE [pkt: RPCPkt. callLength: DataLength.
-- lastPkt: BOOLEAN. localConversation: Conversation] RETURNS [returnLength:
-- DataLength]-- RpcPrivate.Dispatcher
BEGIN
-- Catch public signals.
ENABLE BEGIN
Exception --ERROR [why: Reason]-- =>
BEGIN
ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
transferlndex (0): RpcControl.SignalIndex ~ Exception. why
( 1): Reason);
argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[O);
pktLength: RpcPrivate.DataLength ~ 2;
lastPkt: BOOLEAN;
RpcPrivate.StartSignal[signalPkt: pkt];
argPkt~ ~ [why: why];
[returnLength: . lastPkt: lastPkt] ~
RpcPrivate.Call[ pkt: pkt. callLength: pktLength.
maxReturnLength: 0];
Lupine.RuntimeError; -- Impossible to RESUME an ERROR.
END; -- Exception.
Consultation --SIGNAL-- =>
-BEGIN
ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
transferIndex (0): RpcControl.Signallndex ~ Consultation];
argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[O];
pktLength: RpcPrivate.DataLength ~ 1;
lastPkt: BOOLEAN:
RpcPrivate.StartSignal(signalPkt: pkt];
argPkt.transferlndex ~ Consultation;
[returnLength: • lastPkt: lastPkt] ~
RpcPrivate.Call[ pkt: pkt. call1ength: pktlength.
maxReturnLength: 0];
Lupine.CheckPktLength[pkt: pkt. pktLength: 0]:
RESUME[] ;
END; -- Consultation.
END;

-- Catch public signals.

-- Call public procedures (still in dispatcher).
SELECT LOOPHOLE[pkt.data[O]. RpcControl.ProcedureIndex] FROM
Basic =) RETURN(
BasicStub[pkt: pkt. callLength: call1ength. lastPkt: lastPkt.
localConversation: localConversation]];
Simple => RETURN(
SimpleStub[pkt: pkt. cal1Length: call1ength. lastPkt: lastPkt.
localConversation: localConversation]];
ENDCASE => RETURN[Lupine.DispatchingError[]];
END;

-- ServerOispatcher

Public procedure dispatcher stubs.
BasicStub: --PROCEDURE-- RpcPrivate.Oispatcher =
INLINE BEGIN
pktLength: RpcPriv&~e.DataLength;
Lupine.CheckPktLength[pkt: pkt. pktlength: 1];
Basic[];
pktLength ~ 0;
RETURN(returnLength: pktlength);
END; -- BasicStub.
SimpleStub: --PROCEDURE [first: INT. second: REF INT] RETURNS [a:
-- Rope.ROPE. b: ATOM]-- RpcPrivate.Oispatcher =

Lupine User's Guide-Version 1.0
INLINE BEGIN
second: REF INT;
a: Rope.ROPE;
b: ATOM;
ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [
transferIndex (0): RpcControl.ProcedureIndex. first (1): INT];
argPkt: LONG POINTER TO ArgumentOverlay = ipkt.data[O];
pktLength: RpcPrivate.DataLength p 3;
BEGIN -- Unmarshal second: REF INT from pkt.data[pktLength].
isNIL: Lupine.N11Header;
isNIL p pkt.data[pktLength]; pktLength p pktLength+1;
IF isNIL
THEN second p NIL
ELSE BEGIN
second p (paramZones.gc.NEW[INT]);
BEGIN
second~ p Lupine.RpcPktDoubleWord[pkt. pktLength]~;
pktLength p pktLength + 2;
END;
END; -- IF isNIL.
END; -- Unmarshal second.
Lupine.CheckPktLength[pkt: pkt. pktLength: pktLength];
[a. b]

p

Simple[argPkt.first. second];
pktLength to 0;
BEGIN -- Marshal a: Rope.ROPE to pkt.data[pktLength].
IF pktLength+2 > RpcPrivate.maxDataLength
THEN pktLength p Lupine.StartNextPkt[pkt: pkt. pktLength: pktLength];
pkt.data[pktLength] p a-NIL; pktLength p pktLength+l;
IF a II NIL
THEN BEGIN
textRope: Rope.Text • RopeInline.InlineFlatten[r: a];
pkt.data[pktLength] p textRope.length; pktLength p pktLength+1;
pktLength to Lupine.CopyToPkt[pkt: pkt. pktLength: pktLength.
dataAdr: BASE[DESCRIPTOR[textRope.text]). dataLength:
Lupine.WordsForChars(textRope.length].
alwaysOnePkt: FALSE];
END; -- IF a II NIL.
END; -- Marshal a.
BEGIN -- Marshal b: ATOM to pkt.data(pktLength].
pNameOfAtom: Rope.Text = Atom. GetPName[atom: b];
IF pktLength+Z > RpcPrivate.maxDataLength
THEN pktLength p Lupine.StartNextPkt[pkt: pkt. pktLength: pktLength);
pkt.data(pktLength) p pNameOfAtom=NIL; pktLength p pktLength+l;
IF pNameOfAtom II NIL
THEN BEGIN
textRope: Rope.Text • Ropelnline.lnlineFlatten(r: pNameOfAtom];
pkt.data(pktLength) to textRope. length; pktLength p pktLength+1;
pktLength p Lupine.CopyToPkt(pkt: pkt. pktLength: pktLength.
dataAdr: BASE(DESCRIPTOR(textRope.text]). dataLength:
Lupine.WordsForChars[textRope.length].
alwaysOnePkt: FALSE];
END; -- IF pNameOfAtom II NIL.
END; -- Marshal b.
RETURN(returnLength: pktLength];
END; -- SimpleStub.
No module initialization.
END.

-- TargetRpcServerImpl.

37

Lupine User's Guide-Version 1.0
Stub file TargetRpcBinderImpl.mesa was translated on 8-Jul-82
-- 9:59:51 PDT by Lupine of 7-Jul-82 17:14:26 PDT.
Source interface Target came from file Target.bcd. which was created
on 8-Jul-82 9:59:46 PDT with version stamp 52#64#37310473537 from
source of 8-Jul-82 9:33:34 PDT.
The RPC stub modules for Target are:
TargetRpcControl.mesa;
TargetRpcClientImpl.mesa;
TargetRpcBinderImpl.mesa;
TargetRpcServerImpl.mesa.
The parameters for this translation are:
Target language = Cedar;
Default parameter passing = VALUE;
Deallocate server heap arguments = TRUE;
Inline RpcServerImpl dispatcher stubs = TRUE;
Maximum number of dynamic heap NEWs = 50. MDS NEWs = 50:
Acceptable parameter protocols = VersionRange[l.l].
NOTE: Discard this module unless you use dynamic client binding.
DIRECTORY
TargetRpcControl USING [InterfaceRecord. InterfaceRecordObject].
TargetRpcClientImpl.
RPC USING (InterfaceName. Zones].
RTTypesBasic USING [EstablishFinal1zation. FinalizationQueue. FQEmpty.
FQNext. NewFQ]:
TargetRpcB1nderImpl: MONITOR
IMPORTS ClientPrototype: TargetRpcClientImpl. RTT: RTTypesBasic
EXPORTS TargetRpcControl
SHARES TargetRpcControl
= BEGIN OPEN RpcControl: TargetRpcControl. RpcPubl1c: RPC:
-- Dynamic instantiation and binding routines.
ImportNewInterface: PUBLIC SAFE PROCEDURE [
interfaceName: RpcPublic.InterfaceName.
parameterStorage: RpcPublic.Zones ]
RETURNS [interfaceRecord: RpcControl.InterfaceRecord] =
TRUSTED BEGIN
interfaceRecord ~ Newlnterface[];
LupineDetails(interfaceRecord].module.ImportInterface (
interfaceName: interfaceName,
parameterStorage: parameterStorage
! UNWIND => FreeInterface(interfaceRecord] ];
END:
UnimportNewlnterface: SAFE PROCEDURE [
interfaceRecord: RpcControl.InterfaceRecord ] =
TRUSTED BEGIN
LupineDetails(interfaceRecord].module.Unimportlnterfaceel;
FreeInterface[interfaceRecord];
END;
Utility routines for interface instantiation and caching.
ConcreteLupineDetails: TYPE = REF LupineOetailsObject;
LupineOetailsObject: PUBLIC TYPE = RECORD [
module: ClientModule~NIL.
next: RpcControl.InterfaceRecord~NIL.
self: RpcControl.InterfaceRecord~NIL ];
LupineDetails: PROCEDURE [abstractlnterface: RpcControl.lnterfaceRecord]
RETURNS [ConcreteLupineDetails] =
INLINE {RETURN[abstractlnterface.lupineDetails]};

38

Lupine User's Guide-Version 1.0

39

ClientModule: TYPE • POINTER TO FRAME[TargetRpcClientImpl]:
clientInterfaceCache: RpcControl.InterfaceRecord

~

NIL:

NewInterface: PROCEDURE RETURNS [interface: RpcControl.InterfaceRecord]BEGIN
GetCachedInterface: ENTRY PROCEDURE
RETURNS [cachedIR: RpcControl.InterfaceRecord] •
INlINE BEGIN ENABLE UNWIND -> NULL:
IF (cachedIR~clientInterfaceCache) # NIL
THEN clientInterfaceCache ~ LupineDetails[clientInterfaceCache].next:
END:
ReclaimInterfaces:
IF (interface ~ GetCachedInterface[]) • NIL
THEN BEGIN
.
module: ClientModule = NEW ClientPrototype:
interface ~ NEW[
RpcControl.InterfaceRecordObject ~ [
Basic: module.Basic, Simple: module.Simple, Exception: module. Exception,
Consultation: module.Consultation]];
interface.lupineDetails ~ NEW[
LupineDetailsObject ~ [module: module, self: interface]];
END;
END;
FreeInterface: ENTRY PROCEDURE [interface: RpcControl.InterfaceRecord]INLINE BEGIN ENABLE UNWIND -> NULL;
LupineDetails[interface].next ~ clientInterfaceCache;
clientInterfaceCache ~ interface:
END:
Finalization for dynamic interfaces.

Just cache and reuse for now.

freedInterfaces: RTT.FinalizationQueue • RTT.NewFQ[20]:
ReclaimInterfaces: PROCEDURE =
INLINE BEGIN
WHILE -RTT.FQEmpty[freedInterfaces] DO
UnimportNewInterface[
interfaceRecord: NARROW[RTT.FQNext[freedInterfaces]] ];
ENDLOOP:
END:
Module initialization.
RTT.EstablishFinalization[
type: CODE[RpcControl.InterfaceRecordObject],
npr: 1, fq: freedInterfaces ];
END.

-- TargetRpcBinderImpl.

Cedar Creature Comforts

XEROX-

Release as
By

Last edited

FOR INTERNAL USE ONLY

[IndigoJNewStuff.df.) In addition, some of the facilities can be
parameterized. or disabled. via various user profile entries described below.

Ext~nsions

to Abbreviation Expansion

crRL-E can now be used following any expression whose value is of type procedure, record. error, signal,
etc., i.e. any type whose syntax involves square brackets and named fields, to generate an appropriate
"form" for that expression. For example:
User types: Rope.Find{CTRL-E}
produces: Rope.Find{s1:

~ROPE.,

51:

~ROPE ••

pos1: HNT .. 0 •• case:

~BOOL

.. TRUE1)

User types: IO.Error{CTRL-E}
produces: IO.Error[ec:

~IO.ErrorCode •.

stream:

~STREAM.l

The user can move back and forth among the fields using {NEXT} (Spare2) and {SHIfT-NEXT} in the
standard fashion. When finished with the form. he can type CTRL-NEXT which will have the effect of
deleting any fields not filled in. plus advancing the caret to just beyond the terminating 'J. For example:
User types: Rope.Find{CTRL-E}r{NEXT}key{CTRL-='1EXT}
produces: Rope.Find{s1: r. s2: key]
i.e. typing "r" filled in the first ~ ROPE. field. and typing "key" filled in the second ~ ROPE. field. and
{crRL-NEXT} deleted", pos1: ~ iNT ... 0 •. case: ~ BOOL .. TRUE." and moved the caret to after 'J.
Note that CTRL-E can also be used to construct forms when typing to the interpreter in a work-area

(since typescripts are now editable).
Another useful application is typing CTRL·E following an expression whose value is a procedure type.
The will cause the insertion of a comment describing the arguments and return values for the procedure
type, and then an appropriate form for the procedure body. For example:
User types: RedSave: Menus.ClickProc{CTRL·E}
RedSave: Menus.ClickProc .- {parent: REF ANY. dientData: REF ANY ~ NIL. mouseButton:
Menus.MouseButton ~ red. shift: BOOL ~ FALSE. control: BOOL ~ FALSE] --

produces:

={

~Body~

};

Since this operation involves the interpreter. it can be slow (but so is selecting Rope.Find and clicking
Open in order to find out the arguments). especially the first time for a particular interface.
In the case of misspellings. spelling correction will take place according to your user profile. If confirmation
is required, Yes No menu buttons will be posted in the corresponding viewer.

CTRL·NEXT
As described above. CTRL·NEXT is used as a ''I'm finished with this. go on" in conjunction with CTRL·E
abbreviation expansion. It deletes all of the fields that have default values. If there are any fields that
have not been filled out that do not have default values. the first of these fields is selected and a message
printed in the message window. Thus the user can use CTRL-NEXT to eliminate all fields with default
values. and then proceed to fill in the remaining fields.
For convenience, CTRL-NEXT can also be used in other contexts involving forms. If the current selection
is a placeHolder. CTRL-NEXT deletes the placeHolder and then does moves to the next placeholder.

Updating Last Edited Entry
When you (red) click save on a Tioga document. the system will search for a comment containing a date
and your name. and if found, will automatically update the date. The algorithm used is as follows: start
searching at the beginning of the document looking at all comments. where a comment is either a tioga
node with the comment property. or any line beginning with -- or II. (i.e. this feature also works equally
well for documents that have not been converted to Tioga node structure). In each comment. look and
see if your name (Le. the name of the user that is logged in) appears. and if there is also a date. Stop
searching at the first non-empty non-comment node. If a comment of the appropriate form was found.
update the date of the last such comment (so that user can have separate CreatedOn, LastEditedOn
comments). Otherwise. provided that at least one comment was seen, insert a new comment of the form
"Last edited by: your name. date". following the last comment.
For example, the first few lbes of the file CompatibilityPackage.df are:
-- CompatibilityPackage.df
-- last edited by Levin on November 16. 1982 11:33 am
-- last edited by Andrew Birrell on August 5. 1982 11:46 am

2

Directory [Indigo]Top>
CompatibilityPackage.df

CameFrom [Indigo]Top>
1-Dec-82 13:19:57 PST

If Andrew Birrell were to edit this file and click save. the file would look like:
-- CompatibilityPackage.df
-- last edited by Levin on November 16. 1982 11:33 am
-- last edited by Andrew Birrell on December 1. 1982 9:57 pm
Directory [Indigo]Top>
CompatibilityPackage.df

CameFrom [lndigo]Top>
l-Dec-82 13: 19:57 PST

But if Warren Teitelman were to edit the file and click save. the file would look like:
-----

CompatibilityPackage.df
last edited by Levin on November 16. 1982 11:33 am
last edited by Andrew Birrell on August 5. 1982 11:46 am
Last Edited by: Teitelman. December 1. 1982 9:57 pm

Directory [Indigo]Top>
CompatibilityPackage.df

Came From [Indigo]Top>
l-Dec-82 13:19:57 PST

Note that this feature will never insert a comment unless one is already there. and will also never insert
a comment at the top of the file. It can be disabled by including the entry UpdateLastEdited: FALSE in
your profile (the default is TRUE), or can be bypassed for a particular file by clicking the save button
with the blue mouse button. rather than the red.

Updating Cbange Logs
A facility for automatically generating change log entries for documents that employ Tioga node structure
is available through the Change Log menu button, which is added to the first menu line of all Tioga
documents as a result of running NewStuftlmpl.bcd. Red-clicking ChangeLog will cause the system to
create a change log entry at the end of the document being edited. The entry consists of a Tioga node
of the form: "Edited on", the date. "by", your name, followed by a nested node beginning with "changes
co:", followed by a list of the items changed. PlaceHolders for comments are inserted following each
item. (Filling in these comments is optional: any placeHolder in the change log entry that is not filled
in will be automatically deleted when the file is saved.)
The changed list is generated as follows: for each Tioga node that has been edited. add an entry to the
changed list. if one does not already exist. corresponding to the first (most tightly bound) type declaration
that this node is under. Only consider type declarations which contain a block as part of its definition
(i.e. local variable declarations of a procedure that are 'edited do not rate separate entries, local procedures
do). If there is no such declaration. e.g. the edit is co the DIRECTORY list. or to some expression in the
start code, etc., use the highest node that is not a comment. If there is such a declaration. and it is local
to some higher declaration. indicate that declaration also when printing the change entry.
For example. if I edit the file PrintTVlmpl.mesa by changing: ~a) several of the DIRECTORY clauses. (b)
the IMPORTS list. (c) the cop level declaration for the type UnderLongString. and (d) the procedures
EnsureInit. PutCardRope. and innerPut. the latter two of which are local procedures. the change log
entry that would be produced would look like:
Edtted on December I. 1982 /0;36 pm. by Teitelman

3

general commentst
changes to: DlRECTORY~ •. [MPORTS~~. UnderLongString~ •. EnsureInit~ •• PutCardRope
(local of Print)~ •• innerPut (local of PutRecord. local of Print)~.

Continuing an edit "session"
A new change log entry is' created only once for a particular edit session. This change log entry is said
to be active as long as the corresponding document exists. and the corresponding node is pan of that
document. i.e. has not been deleted. [n other words. the system will continue to treat edits as pan of the
same session as long as the user edits in the same viewer (or a viewer created as a result of splitting this
viewer), and as lortg as the corresponding change log entry still exists. [n this case. when the user clicks
ChangeLog or Save (see below). a new change log entry is not created. but instead the active change log
entry is updated by appending those entries that were not previously written to it at the end of the entry.
(Thus the user can edit comments in the change log entry and when that entry is subsequently updated. the comments will not be
touched.)

Often a single edit session will logically span several boot or rollback operations, e.g. the user makes
some edits, recompiles, rollsback, reloads the file, discovers some additional problems which require more
editing. [n this case, it is desirable to have the latter set of edits look as though they had been performed
in the same session as those performed a shon while previously. In order to accomodate this behaviour,
if a previous change log entry is found. and this entry is dated within 24 hours of the current time, the
current set of changes will be merged with those in the previous entry, Le. the effect is the same as
though they occurred in the same edit session. (The test for whether or not such an entry exists is to search backwards
from the end of the file looking at nodes with comment properues. If a node is found which contains a date. and one of the node's
children begins with the characters "changes to: .. , then the test succeeds. The test fails at the first non-empty. non-comment node.)

The user can override the merging of change logs and force a new change log entry by yellow-clicking
ChangeLog. Similarly, the user can explicitly request merging with the previous change log. even if
more than 24 hours have elapsed (e.g. to continue Friday afternoon edits on Monday morning) by
blue-clicking ChangeLog.
Note that if the user clears or destroys the viewer. and then subsequently opens another viewer on the
same document. or if the user deletes the active change log entry from the document. the effect is the
same as though the user had booted or rolledback. i.e. a new session is staned unless the previous change
log entry occurred within 24 hours. etc.

Sa ving the file
In many situations. the user does not want to insen any comments in the change log. but simply wants
to save the file with the list of changes. Rather than forcing the user to first click Change Log and then
click Save. in those cases where the user has already indicated that he wants a change log maintained
for this file, either by vinue of having previously created one by clicking Change Log, or by an appropriate
declaration in his user profile. the user can simply click Save. Thus
(a) If there is an active change log entry. Red-clicking Save will update it. Le. is the same as
red-clicking ChangeLog and then doing the save.
(b) If the user has an 'entry in his profile of the form UpdateChangeLog: addIfPrevious (the default),
and a change log entry was insened by this facility in some previous edit session. then merge the two
entries if their times are within 24 hours. otherwise create a new entry.
(c) If the user has an entry in his profile of the form UpdateChangeLog: createNew, and the file
looks like a mesa file. then proceed as in (b). (The test for this is to search backwards from the end of the file for

4

the first non-empty. non-comment node. This node must begin with the characters .. END....
for files that do not use Tioga node structure.)

:-.rote that this test will always

fail

(d) If you are feeling paranoid. Blue-clicking Save will simply cause the file to be saved without
doing anything to the change log (or the Last-Edited date). regardless of your user profile. and
regardless of whether a change log entry is currently active.

Summary
RedClick ChangeLog
[f there is an active change log entry, update it. otherwise if there is a change log entry in the file created
within the past 24 hours. merge with this entry. otherwise create a new change log entry.

YellowClick Change Log
Create a new change log entry.

BlueClick ChangeLog
Merge with previous change log entry if one exists•• regardless of when it was written. otherwise Create
a new change log entry.

RedClick Save
If there is an active change log entry, update it. otherwise. if UpdateChangeLog = addltPrevious. and
there is a previous change log entry. create a new one (or merge with previous one if within 24 hours.
otherwise. if UpdateChangeLog = createNewand file looks like a mesa file. create a new one or merge
with previous one if within 24 hours.

BlueC1ick Saye
Just write out the file.

Note that the system will never mess with your change log unless:
(1) You explicitly click Change Log.
(2) You explicitly clicked ChangeLog once before in this edit session.
(3) Your user profile contains UpdateChangeLog: addItPrevious (the default). and there is already at
least one change log entry there of the recognized form. In other words. in this mode. you have co stan
each file off with a change log the first time by explicitly yellow-clicking Change Log.
(4) Your user profile contains UpdateChangeLog: createNew, and the file looks like a mesa file. In other
words. in this mode. change logs will automatically be staned for you. but only if the file looks like a
mesa file with node structure.

The system will never add duplicate entries to the change log.
The system will never wsturb any changes that you make by hand to your change log. e.g. editing
comments.
Remember: this facility is designed to be used ONLY in conjunction with Tioga node structures.· The
change log will be singularly uninteresting for a flat structured document. since all of the changes will
appear to be at the same place.

5

Master Change Log
A facility for generating a log of all of the files that you save during a session is automatically enabled
when NewStuffimpl is loaded. unless you have an entry in your user profile of the form
CreateChangesLog: FALSE. This log is kept on the file Changes.Log which is created when it is first
needed. Each time you save a file. the date. file name. and changes log entry that was inserted in your
file via the facility Updating Changes Log discussed above. if there is such an entry. is added to this
log. Here is an example of such a log:
Changes log created at 1O-Mar-83 15:20:27 PST
Changed File: my.dfs
Edited on 1O-Mar-83 15:20:27 PST (no change log entry)
Changed File: io.DF
Edited on 1O-Mar-83 15:52:10 PST (no change log entry)
Changed File: teitelman.profile
Edited on 10-Mar-83 17:16:44 PST (no change log entry)
Changed File: UserProfile.doc
Edited on March 10. 1983 5:22 pm. by Teitelman
changes to: Hardcopy .
Changed File: UserExecImpl.df
Edited on 1O-Mar-83 17:23:44 PST (no change log entry)
The first time in a particular session that you save a file. a new Changes.Log tile is created. and the
existing one renamed to be Changes.LogS. For the purposes of this facility. a new session starts
when you boot: rolling back reopens the existing change log. if any, and continues the previous
session.

Remembering Previous Search
Whenever a Tioga document is searched via the Find. Word. or Def menu buttons. the target of the
search is saved. If the target for this particular search. i.e. the current selection. is either empty (point
selection). or consists of a single character. then the previous target is used instead. This enables searching
for Foo. deleting it. and then searching for the next Foo by simply clicking the menu button again. It
also enables searching for a particular target. changing the input focus in order to type something
somewhere else. for· example. to obtain a new viewer and load it with a particular file. and then searching
again without having to reselect the target

Swapping icons with opened viewers
The viewers package allows you to load an existing viewer with a tile while requesting that the current
contents of the viewer be made iconic. This is accomplished by selecting the name of the tile. and then
right clicking get. NewStuff extends this feature to allow you to select an icon. and then right-click get
in a viewer. This causes the icon to be opened in place of the viewer. and the viewer to be made iconic.
i.e. the two are swapped. Similarly. selecting an icon and then middle clicking get will open the icon just
below the viewer. and left clicking get will cause the icon to replace the viewer.

6

Inter-Office Memorandum
May 26,1982

To

Cedar Implementors

Date

From

Roy Levin

Location

Subject

Cedar Releases: Policies and Procedures

Organization

.

Palo Alto
PARC/CSL

XEROX
Filed on: [lndigojDocumentatlon>ReleaseProcedures.press

This memo describes the policies and procedures that individuals contributing to Cedar releases
need to understand and observe. It assumes general familiarity with Cedar and OF files.
The Release Process

Components and DF Files
Throughout this memo, we call the unit of software submitted to the Cedar release process a
component. Each component is described by a DF flle, a simple description mechanism that is
chiefly a list of file names (complete IFS paths) and creation dates (either explicit or implicit). This
memo assumes familiarity with OF files: complete information may be found in the reference
manual stored on (lndigo)Z>" is an abbreviation for "has
a ReleaseAs clause with path [X)Z)".
1)

The DF file name is considered to be the "name" of the component and should generally
correspond to Ihe name of the major exported interface (in Ihe Mesa sense) supplied by the
component. This rule is most easily applied to straightforward packages with a single public
interface.

2)

The DF file must contain a self--reference that is released to [Indigo/Top>.
reference must be exported
.

3)

If separate documentation files accompany the component. they should be included in the DF file
and released to [Indigo/Documentation>. Documentation files in suitable form for online
use (not press files) should also be exported. It is not mandatory that documentation tiles
accompany a component; comments in the public interfaces may be sufficient for use.
However. most substantial components will have separate documentation tiles. and these
should be included in the OF tile as indicated. If a component has recently undergone a
substantial revision that is visible to its users. the implementor should probably release
separate tiles containing the "change summary" and the "complete truth".

4)

All component-specific files other than the DF file and documentation should be released to a
subdirectory with the same name as the component (e.g.• the interfaces and implementation of
SomePackage.df should be released to [lndigo/SomePackage>. It is permissible to have
additional subdirectory structure within the component-specitic subdirectory. Subdirectories
of either rIndigo) or [Indigo]Oocumencation> are not permitted.

5)

If the component supplies a "public interface': the source and object files must be exported from
the DF file. ·The debugging and help facilities tend to work better if they can access the
sources of interfaces as well as their compiled representations. Disk space concerns are
irrelevant here. since the tiles involved are small and improvements in the tile system will
soon eliminate the size limitations of the local disk.

6)

The BCD or BeDs that contain the bound-up implementation of the component must be
exported from the DF file. Exception: if the implementation is intended for inclusion in the
Cedar boot file, it should not be exported The motivation here is obvious: the component ..anOt
be used unless its implemencation is available.

The self-

Cedar Releases:

Policies and Procedures

4

7)

The entry in the DF file for the bound-up implementation of the component must be preceded by
a "+" to indicate that it is a root BCD for processing by VerifyDF. If the component exports
multiple BCDs, each of them must obey this rule. It is permissible to have other BCDs
marked with a "+", e.g., test programs.

8)

A file that is not a part of the component should be referenced using al. "Imports" entry with a
USING list The entry forms introduced by "ReadOnly" and "@", while documented in the
OF reference manual. are obsolete and should not be used. The USING list documents
explicitly dependencies on other components, protects against certain mistakes in imported OF
files, and speeds up BringOver.

9)

An import from the release directory may include either an explicit or an implicit (i.e., ")" or
"-='') date. An import from a working directory must specify an implicit date. While these
rules may seem a bit unintuitive at first. experience shows that they greatly streamline the
release process. Last-minute, minor changes in a OF file are common during a release
integration, and a failure to observe the second rule in a OF file depending on the one that
changed forces an otherwise unnecessary reconstruction of the dependent OF file. The lastminute changes are rarely significant t-o the importer(s): when they are, inconsistencies will
detected by the release machinery.

10)

The DF file for a component should usually include a text file containing command lines for
compiling and binding the package. This is not mandatory, but strongly recommended. It is
not necessary that this file be a complete command file; rather, it is intended more as an
documentary aid to someone unfamiliar with the structure of the component who finds it
necessary to make a small change and rebuild it. There is no standardization on the name of
such text files; most have the extension ".cm" (whether or not they are true command files)
and many include the word "Make" and the component name in their names.

11)

If programs other than the Compiler and Binder are needed to build the component entries
importing them should be included in the DF file. Examples of such programs include the
Packager, MakeBoot. and the TableCompiler. If specific versions of the Compiler andlor Binder are
required (a rare situation). entries for them should be Included as well: however. it is not necessary to reference
the standard ones.

12)

The working directory used for all non-imported files must grant read and create access to
CedarAdministratorst.PA. The need for read access is obvious; the component can't be
released unless it can be read. The need for create access is rarely exercised but is
occasionally needed when a small change to a component is required in order to complete a
release integration and the implementor is not available. Note that the heavily-used working
directories [Indigo] and [Indigo] satisfy these requirements, while
personal directories typically do not Implementors who use their personal directories for
release submissions must explicitly alter the IFS access controls to their directories to conform
to this rule.

A Sample DF File

The OF file below satisfies the requirements for submission to a Cedar release. It describes a
component named Samp 1e. which consists of a single configuration named Samp 1e Imp 1.
Sample has two public interfaces. named Sample and SampleExtras. The implementation
consists of two modules. Samp 1 e Imp 1A and S amp 1 e Imp 1B, which share a private definitions
module named Samp 1 eP r i va teo It requires three other components, defined by OF files named
PilotInterfaces.df. Rigging.df. and Runtime.df. Finally. the component is documented
by a press file whose source is a Tioga document.

Cedar Releases:

Policies and Procedures

5

Notations of the form {n} are not actually pan of the" OF file. They indicate that the entry so
marked conforms to rule n. above.
II
II

Sample.df
last edited by Harry Bovik: May 10. 1982

Exports [Ivy]Runtime)Runtime.df Of >
Using [SafeStorage.bcd] {8,9}
Notice that the files that make up the component are all stored on a working directory chosen by
the implementor. in this case his personal directory on Ivy. (Note that. in accordance with rule 12.
Bovik must grant create access on [Ivy]. where the tiles are to be stored at release time.
The component depends on three other components. two of which have been previously released
(since they are on the release directory) and one of which (Runt ime. df) is not (and presumably
will be released when Samp 1 e is).

Cedar Releases:

Policies and Procedures

6

Rules for Submitting a Component for Release
The message from the Release Master that announces the integration phase of a release contains a
message form. This form. properly completed and returned. serves thre~ important functions:
1)

It enables the Release Master to include the OF file describing the component in the
top-level description of the release.

2)

It notifies other implementors that the component is now available for reference in other
OF files.

3)

It provides the information to be included in the release message that will announce the
release to all Cedar users.

The message form has been constructed to facilitate all three of these purposes. Since deviations
from the standard form complicate and delay the integration phase. implementors must observe the
following rules for submission of components:
13)

The component must satisfy the construction rules before the submission form is senL Sending
the form before the OF files are ready and stored confuses everyone.

14)

The implementor must have run VerifyDF on the component's DF file before submitting it for
release. VerifyOF performs most of the completeness checks that the Release Tool's second
phase does; consequently, most errors of this form can be detected early in the integration
phase and without delaying other implementors.

IS)

The submission form is the only acceptable way of announcing a release submission. Free-form
messages are not acceptable and will be rejected by the Release Master. If an implementor
expects to be unavailable during the integration phase and wishes to prepare his submission
"in advance", it is his responsibility to obtain from the Release Master a copy of the form and
use it.

16)

All fields of the form must be completed appropriately. In particular, the working path and
release path must be filled in correctly and expressed in conventional syntax (server name in
square brackets, directory and subdirectories in angle brackets); "I" syntax is not acceptable.
The documentation pointer must conform to the requirements stated on the form. The
ponion of the form that contains information destined for the release message should be filled
in judiciously; it is generally not necessary or desirable to describe every bug fix and minor
enhancement. The reference 'documentation should include this kind of information. while the
release message should contain a summary of the significant changes in the component since
the last release. A chronology of changes is not appropriate. The release message portion of
the form must also be coherent English prose that observes accepted standards of
capitalization. spelling, punctuation. and grammar.

Avoiding Common Mistakes
When the integration phase of a release cycle is underway. it is easy to forget one or more of the
above rules. Experience has shown that some rules are more likely to be broken than others and
that cenain mistakes occur repeatedly. Careful observation of the following rules will help
implementors avoid the most common errors that delay release integrations.

Cedar Releases:
17)

Policies and Procedures

7

When beginning development of a ,component following a release. use the released DF file as the
base, not the working DF file supplied 10 the previous release. Obsolete working OF files are
perhaps the single greatest source of trouble in the integration phase. When an implementor
uses a working OF file from a previous release as the base for new development. he invites
inconsistencies that cannot be easily detected until the Release Tool is run. The typical
problem is a reference to a working OF file that is either obsolete or non-existant. SModel can
only cletect the latter of these problems. and then typically only if Iv is specified.

18)

Be certain that all imports come from the correct location (working directory or release
directory). In a sense. this rule includes the preceding one. since incorrect imports frequently
arise when an obsolete OF file has been used as the starting point for development of the
component.

19)

When correcting a problem uncovered by the Release Tool during the integration phase. always
run VerifyDF before notifYing the Release Master that the component is again ready for
inclusion. It is quite common for phase one of the Release Tool to uncover a problem in a
OF file which. when .. fixed" quicldy by the implementor, leads to a problem in phase two.
This causes unnecessary delay while the implementor once again fixes the problem; running
VerifyOF before the first resubmission will nearly always avoid such delays.

20)

Before submitling a component for release. double-check the subdirectories to which files are
being released. The Release Tool cannot, in general. check that rules 2-4 are obeyed.
Uniformity here greatly simplifies browsing.

21)

After successfUlly running VerifyDF (rule 19). be sure to run SModel /V.. In the course of
making a OF file acceptable to Verify OF. it is useful to run SModel In. Which, although it
improves the state of the files on the local disk. performs no transfers to file servers. SModel
Iv ensures that the cumulative effect of repeated runs of SModel In is moved to the file
servers.

Cedar Document Style A Sample Sheet Release as
Came from
Last edited

title node

subtitle node

[Indigo ]Documentation>SampleSheet. tioga, .press
[lndigo]

Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.3
Linearized                      : No
XMP Toolkit                     : Adobe XMP Core 4.2.1-c041 52.342996, 2008/05/07-21:37:19
Create Date                     : 2018:06:02 12:22:30-08:00
Modify Date                     : 2018:06:02 12:47:57-07:00
Metadata Date                   : 2018:06:02 12:47:57-07:00
Producer                        : Adobe Acrobat 9.0 Paper Capture Plug-in
Format                          : application/pdf
Document ID                     : uuid:56f6eaed-fb07-084d-8889-1267c9fbc2e9
Instance ID                     : uuid:a7a3987e-f35a-e14b-871e-2569794a2277
Page Layout                     : SinglePage
Page Mode                       : UseNone
Page Count                      : 400
EXIF Metadata provided by
EXIF.tools

Navigation menu