2 |
- |
1 |
<?xml version="1.0" encoding="utf-8"?>
|
|
|
2 |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
|
3 |
"http://www.w3.org/TR/html4/loose.dtd">
|
|
|
4 |
<html>
|
|
|
5 |
<head>
|
|
|
6 |
<meta http-equiv=Content-Type content="text/html; charset=utf8">
|
|
|
7 |
<title>The Text Editor sam</title>
|
|
|
8 |
</meta>
|
|
|
9 |
</head>
|
|
|
10 |
<body>
|
|
|
11 |
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
|
|
|
12 |
<p style="margin-top: 0; margin-bottom: 0.21in"></p>
|
|
|
13 |
|
|
|
14 |
<p style="line-height: 1.4em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
|
|
|
15 |
<span style="font-size: 12pt"><b>The Text Editor </b></span><span style="font-size: 12pt"><tt>sam</tt></span><span style="font-size: 12pt"><b></b></span></p>
|
|
|
16 |
<p style="margin-top: 0; margin-bottom: 0.21in"></p>
|
|
|
17 |
|
|
|
18 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
19 |
<p style="line-height: 1.4em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
|
|
|
20 |
<span style="font-size: 10pt"><i>Rob Pike</i></span></p>
|
|
|
21 |
<p style="line-height: 1.4em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
|
|
|
22 |
<span style="font-size: 10pt"><i>rob@plan9.bell-labs.com</i></span></p>
|
|
|
23 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
24 |
|
|
|
25 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
26 |
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
|
|
|
27 |
<p style="line-height: 1.4em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
|
|
|
28 |
<span style="font-size: 10pt"><i>ABSTRACT</i></span></p>
|
|
|
29 |
<p style="margin-top: 0; margin-bottom: 0.19in"></p>
|
|
|
30 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
31 |
<p style="line-height: 1.2em; margin-left: 1.50in; text-indent: 0.50in; margin-right: 1.50in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
32 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
33 |
is an interactive multi-file text editor intended for
|
|
|
34 |
bitmap displays.
|
|
|
35 |
A textual command language
|
|
|
36 |
supplements the mouse-driven, cut-and-paste interface
|
|
|
37 |
to make complex or
|
|
|
38 |
repetitive editing tasks easy to specify.
|
|
|
39 |
The language is characterized by the composition of regular expressions
|
|
|
40 |
to describe the structure of the text being modified.
|
|
|
41 |
The treatment of files as a database, with changes logged
|
|
|
42 |
as atomic transactions, guides the implementation and
|
|
|
43 |
makes a general ‘undo’ mechanism straightforward.
|
|
|
44 |
</span><span style="font-size: 10pt"></span><span style="font-size: 10pt"></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
45 |
<p style="line-height: 1.2em; margin-left: 1.50in; text-indent: 0.35in; margin-right: 1.50in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
46 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
47 |
is implemented as two processes connected by a low-bandwidth stream,
|
|
|
48 |
one process handling the display and the other the editing
|
|
|
49 |
algorithms. Therefore it can run with the display process
|
|
|
50 |
in a bitmap terminal and the editor on a local host,
|
|
|
51 |
with both processes on a bitmap-equipped host, or with
|
|
|
52 |
the display process in the terminal and the editor in a
|
|
|
53 |
remote host.
|
|
|
54 |
By suppressing the display process,
|
|
|
55 |
it can even run without a bitmap terminal.
|
|
|
56 |
</span><span style="font-size: 10pt"></span><span style="font-size: 10pt"></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
57 |
<p style="line-height: 1.2em; margin-left: 1.50in; text-indent: 0.35in; margin-right: 1.50in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
58 |
<span style="font-size: 10pt">This paper is reprinted from Software—Practice and Experience,
|
|
|
59 |
Vol 17, number 11, pp. 813-845, November 1987.
|
|
|
60 |
The paper has not been updated for the Plan 9 manuals. Although
|
|
|
61 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
62 |
has not changed much since the paper was written, the system around it certainly has.
|
|
|
63 |
Nonetheless, the description here still stands as the best introduction to the editor.
|
|
|
64 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
65 |
|
|
|
66 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
67 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
68 |
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
|
|
|
69 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
70 |
<span style="font-size: 10pt"><b>Introduction
|
|
|
71 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
72 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
73 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
74 |
is an interactive text editor that combines cut-and-paste interactive editing with
|
|
|
75 |
an unusual command language based on the composition of regular expressions.
|
|
|
76 |
It is written as two programs: one, the ‘host part,’ runs on a UNIX system
|
|
|
77 |
and implements the command language and provides file access; the other, the
|
|
|
78 |
‘terminal part,’ runs asynchronously
|
|
|
79 |
on a machine with a mouse and bitmap display
|
|
|
80 |
and supports the display and interactive editing.
|
|
|
81 |
The host part may be even run in isolation on an ordinary terminal
|
|
|
82 |
to edit text using the command
|
|
|
83 |
language, much like a traditional line editor,
|
|
|
84 |
without assistance from a mouse or display.
|
|
|
85 |
Most often,
|
|
|
86 |
the terminal part runs on a Blit<sup></sup></span><sup><span style="font-size: 6pt">1</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt"> terminal
|
|
|
87 |
(actually on a Teletype DMD 5620, the production version of the Blit), whose
|
|
|
88 |
host connection is an ordinary 9600 bps RS232 link;
|
|
|
89 |
on the SUN computer the host and display processes run on a single machine,
|
|
|
90 |
connected by a pipe.
|
|
|
91 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
92 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
93 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
94 |
edits uninterpreted
|
|
|
95 |
ASCII text.
|
|
|
96 |
It has no facilities for multiple fonts, graphics or tables,
|
|
|
97 |
unlike MacWrite,<sup></sup></span><sup><span style="font-size: 6pt">2</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt"> Bravo,<sup></sup></span><sup><span style="font-size: 6pt">3</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt"> Tioga<sup></sup></span><sup><span style="font-size: 6pt">4</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
98 |
or Lara.<sup></sup></span><sup><span style="font-size: 6pt">5</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
99 |
Also unlike them, it has a rich command language.
|
|
|
100 |
(Throughout this paper, the phrase
|
|
|
101 |
</span><span style="font-size: 10pt"><i>command language
|
|
|
102 |
</i></span><span style="font-size: 10pt">refers to
|
|
|
103 |
textual commands; commands activated from the mouse form the
|
|
|
104 |
</span><span style="font-size: 10pt"><i>mouse</i></span><span style="font-size: 10pt">
|
|
|
105 |
</span><span style="font-size: 10pt"><i>language.</i></span><span style="font-size: 10pt">)
|
|
|
106 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
107 |
developed as an editor for use by programmers, and tries to join
|
|
|
108 |
the styles of the UNIX text editor
|
|
|
109 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt"><sup></sup></span><sup><span style="font-size: 6pt">6,7</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
110 |
with that of interactive cut-and-paste editors by
|
|
|
111 |
providing a comfortable mouse-driven interface
|
|
|
112 |
to a program with a solid command language driven by regular expressions.
|
|
|
113 |
The command language developed more than the mouse language, and
|
|
|
114 |
acquired a notation for describing the structure of files
|
|
|
115 |
more richly than as a sequence of lines,
|
|
|
116 |
using a dataflow-like syntax for specifying changes.
|
|
|
117 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
118 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
119 |
<span style="font-size: 10pt">The interactive style was influenced by
|
|
|
120 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">,<sup></sup></span><sup><span style="font-size: 6pt">1</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
121 |
an early cut-and-paste editor for the Blit, and by
|
|
|
122 |
</span><span style="font-size: 10pt"><tt>mux</tt></span><span style="font-size: 10pt">,<sup></sup></span><sup><span style="font-size: 6pt">8</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
123 |
the Blit window system.
|
|
|
124 |
</span><span style="font-size: 10pt"><tt>Mux</tt></span><span style="font-size: 10pt">
|
|
|
125 |
merges the original Blit window system,
|
|
|
126 |
</span><span style="font-size: 10pt"><tt>mpx</tt></span><span style="font-size: 10pt">,<sup></sup></span><sup><span style="font-size: 6pt">1</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
127 |
with cut-and-paste editing, forming something like a
|
|
|
128 |
multiplexed version of
|
|
|
129 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
130 |
that edits the output of (and input to) command sessions rather than files.
|
|
|
131 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
132 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
133 |
<span style="font-size: 10pt">The first part of this paper describes the command language, then the mouse
|
|
|
134 |
language, and explains how they interact.
|
|
|
135 |
That is followed by a description of the implementation,
|
|
|
136 |
first of the host part, then of the terminal part.
|
|
|
137 |
A principle that influenced the design of
|
|
|
138 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
139 |
is that it should have no explicit limits, such as upper limits on
|
|
|
140 |
file size or line length.
|
|
|
141 |
A secondary consideration is that it be efficient.
|
|
|
142 |
To honor these two goals together requires a method for efficiently
|
|
|
143 |
manipulating
|
|
|
144 |
huge strings (files) without breaking them into lines,
|
|
|
145 |
perhaps while making thousands of changes
|
|
|
146 |
under control of the command language.
|
|
|
147 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">’s
|
|
|
148 |
method is to
|
|
|
149 |
treat the file as a transaction database, implementing changes as atomic
|
|
|
150 |
updates. These updates may be unwound easily to ‘undo’ changes.
|
|
|
151 |
Efficiency is achieved through a collection of caches that minimizes
|
|
|
152 |
disc traffic and data motion, both within the two parts of the program
|
|
|
153 |
and between them.
|
|
|
154 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
155 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
156 |
<span style="font-size: 10pt">The terminal part of
|
|
|
157 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
158 |
is fairly straightforward.
|
|
|
159 |
More interesting is how the two halves of the editor stay
|
|
|
160 |
synchronized when either half may initiate a change.
|
|
|
161 |
This is achieved through a data structure that organizes the
|
|
|
162 |
communications and is maintained in parallel by both halves.
|
|
|
163 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
164 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
165 |
<span style="font-size: 10pt">The last part of the paper chronicles the writing of
|
|
|
166 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
167 |
and discusses the lessons that were learned through its development and use.
|
|
|
168 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
169 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
170 |
<span style="font-size: 10pt">The paper is long, but is composed largely of two papers of reasonable length:
|
|
|
171 |
a description of the user interface of
|
|
|
172 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
173 |
and a discussion of its implementation.
|
|
|
174 |
They are combined because the implementation is strongly influenced by
|
|
|
175 |
the user interface, and vice versa.
|
|
|
176 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
177 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
178 |
<span style="font-size: 10pt"><b>The Interface
|
|
|
179 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
180 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
181 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
182 |
is a text editor for multiple files.
|
|
|
183 |
File names may be provided when it is invoked:
|
|
|
184 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
185 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
186 |
<span style="font-size: 9pt"><tt>sam file1 file2 ...</tt></span></p>
|
|
|
187 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
188 |
|
|
|
189 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
190 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
191 |
<span style="font-size: 10pt">and there are commands
|
|
|
192 |
to add new files and discard unneeded ones.
|
|
|
193 |
Files are not read until necessary
|
|
|
194 |
to complete some command.
|
|
|
195 |
Editing operations apply to an internal copy
|
|
|
196 |
made when the file is read; the UNIX file associated with the copy
|
|
|
197 |
is changed only by an explicit command.
|
|
|
198 |
To simplify the discussion, the internal copy is here called a
|
|
|
199 |
</span><span style="font-size: 10pt"><i>file</i></span><span style="font-size: 10pt">,
|
|
|
200 |
while the disc-resident original is called a
|
|
|
201 |
</span><span style="font-size: 10pt"><i>disc file.
|
|
|
202 |
</i></span><span style="font-size: 10pt"></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
203 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
204 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
205 |
is usually connected to a bitmap display that presents a cut-and-paste
|
|
|
206 |
editor driven by the mouse.
|
|
|
207 |
In this mode, the command language is still available:
|
|
|
208 |
text typed in a special window, called the
|
|
|
209 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
210 |
</span><span style="font-size: 10pt"><i>window,</i></span><span style="font-size: 10pt">
|
|
|
211 |
is interpreted
|
|
|
212 |
as commands to be executed in the current file.
|
|
|
213 |
Cut-and-paste editing may be used in any window — even in the
|
|
|
214 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
215 |
window to construct commands.
|
|
|
216 |
The other mode of operation, invoked by starting
|
|
|
217 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
218 |
with the option
|
|
|
219 |
</span><span style="font-size: 10pt"><tt>-d</tt></span><span style="font-size: 10pt">
|
|
|
220 |
(for ‘no download’),
|
|
|
221 |
does not use the mouse or bitmap display, but still permits
|
|
|
222 |
editing using the textual command language, even on an ordinary terminal,
|
|
|
223 |
interactively or from a script.
|
|
|
224 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
225 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
226 |
<span style="font-size: 10pt">The following sections describe first the command language (under
|
|
|
227 |
</span><span style="font-size: 10pt"><tt>sam\fP-d
|
|
|
228 |
and in the
|
|
|
229 |
</tt></span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt"><tt>
|
|
|
230 |
window), and then the mouse interface.
|
|
|
231 |
These two languages are nearly independent, but connect through the
|
|
|
232 |
</tt></span><span style="font-size: 10pt"><i>current</i></span><span style="font-size: 10pt"><tt>
|
|
|
233 |
</tt></span><span style="font-size: 10pt"><i>text,</i></span><span style="font-size: 10pt"><tt>
|
|
|
234 |
described below.
|
|
|
235 |
</tt></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
236 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
237 |
<span style="font-size: 10pt"><b>The Command Language
|
|
|
238 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
239 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
240 |
<span style="font-size: 10pt">A file consists of its contents, which are an array of characters
|
|
|
241 |
(that is, a string); the
|
|
|
242 |
</span><span style="font-size: 10pt"><i>name</i></span><span style="font-size: 10pt">
|
|
|
243 |
of the associated disc file; the
|
|
|
244 |
</span><span style="font-size: 10pt"><i>modified bit
|
|
|
245 |
</i></span><span style="font-size: 10pt">that states whether the contents match those of
|
|
|
246 |
the disc file;
|
|
|
247 |
and a substring of the contents, called the
|
|
|
248 |
</span><span style="font-size: 10pt"><i>current text
|
|
|
249 |
</i></span><span style="font-size: 10pt">or
|
|
|
250 |
</span><span style="font-size: 10pt"><i>dot</i></span><span style="font-size: 10pt">
|
|
|
251 |
(see Figures 1 and 2).
|
|
|
252 |
If the current text is a null string, dot falls between characters.
|
|
|
253 |
The
|
|
|
254 |
</span><span style="font-size: 10pt"><i>value</i></span><span style="font-size: 10pt">
|
|
|
255 |
of dot is the location of the current text; the
|
|
|
256 |
</span><span style="font-size: 10pt"><i>contents</i></span><span style="font-size: 10pt">
|
|
|
257 |
of dot are the characters it contains.
|
|
|
258 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
259 |
imparts to the text no two-dimensional interpretation such as columns
|
|
|
260 |
or fields; text is always one-dimensional.
|
|
|
261 |
Even the idea of a ‘line’ of text as understood by most UNIX programs
|
|
|
262 |
— a sequence of characters terminated by a newline character —
|
|
|
263 |
is only weakly supported.
|
|
|
264 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
265 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
266 |
<span style="font-size: 10pt">The
|
|
|
267 |
</span><span style="font-size: 10pt"><i>current file
|
|
|
268 |
</i></span><span style="font-size: 10pt">is the file to which editing commands refer.
|
|
|
269 |
The current text is therefore dot in the current file.
|
|
|
270 |
If a command doesn’t explicitly name a particular file or piece of text,
|
|
|
271 |
the command is assumed to apply to the current text.
|
|
|
272 |
For the moment, ignore the presence of multiple files and consider
|
|
|
273 |
editing a single file.
|
|
|
274 |
</span><span style="font-size: 10pt"></span></p><center><img src="fig1.gif" /></center>
|
|
|
275 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
276 |
<span style="font-size: 8pt"><i>Figure 1. A typical
|
|
|
277 |
</i></span><span style="font-size: 8pt"><tt>sam</tt></span><span style="font-size: 8pt"><i>
|
|
|
278 |
screen, with the editing menu presented.
|
|
|
279 |
The
|
|
|
280 |
</i></span><span style="font-size: 8pt"><tt>sam</tt></span><span style="font-size: 8pt"><i>
|
|
|
281 |
(command language) window is in the middle, with file windows above and below.
|
|
|
282 |
(The user interface makes it easy to create these abutting windows.)
|
|
|
283 |
The partially obscured window is a third file window.
|
|
|
284 |
The uppermost window is that to which typing and mouse operations apply,
|
|
|
285 |
as indicated by its heavy border.
|
|
|
286 |
Each window has its current text highlighted in reverse video.
|
|
|
287 |
The
|
|
|
288 |
</i></span><span style="font-size: 8pt"><tt>sam</tt></span><span style="font-size: 8pt"><i>
|
|
|
289 |
window’s current text is the null string on the last visible line,
|
|
|
290 |
indicated by a vertical bar.
|
|
|
291 |
See also Figure 2.
|
|
|
292 |
</i></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
293 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
294 |
|
|
|
295 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
296 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
297 |
<span style="font-size: 10pt">Commands have one-letter names.
|
|
|
298 |
Except for non-editing commands such as writing
|
|
|
299 |
the file to disc, most commands make some change
|
|
|
300 |
to the text in dot and leave dot set to the text resulting from the change.
|
|
|
301 |
For example, the delete command,
|
|
|
302 |
</span><span style="font-size: 10pt"><tt>d</tt></span><span style="font-size: 10pt">,
|
|
|
303 |
deletes the text in dot, replacing it by the null string and setting dot
|
|
|
304 |
to the result.
|
|
|
305 |
The change command,
|
|
|
306 |
</span><span style="font-size: 10pt"><tt>c</tt></span><span style="font-size: 10pt">,
|
|
|
307 |
replaces dot by text delimited by an arbitrary punctuation character,
|
|
|
308 |
conventionally
|
|
|
309 |
a slash. Thus,
|
|
|
310 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
311 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
312 |
<span style="font-size: 9pt"><tt>c/Peter/</tt></span></p>
|
|
|
313 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
314 |
|
|
|
315 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
316 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
317 |
<span style="font-size: 10pt">replaces the text in dot by the string
|
|
|
318 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">.
|
|
|
319 |
Similarly,
|
|
|
320 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
321 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
322 |
<span style="font-size: 9pt"><tt>a/Peter/</tt></span></p>
|
|
|
323 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
324 |
|
|
|
325 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
326 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
327 |
<span style="font-size: 10pt">(append) adds the string after dot, and
|
|
|
328 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
329 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
330 |
<span style="font-size: 9pt"><tt>i/Peter/</tt></span></p>
|
|
|
331 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
332 |
|
|
|
333 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
334 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
335 |
<span style="font-size: 10pt">(insert) inserts before dot.
|
|
|
336 |
All three leave dot set to the new text,
|
|
|
337 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">.
|
|
|
338 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
339 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
340 |
<span style="font-size: 10pt">Newlines are part of the syntax of commands:
|
|
|
341 |
the newline character lexically terminates a command.
|
|
|
342 |
Within the inserted text, however, newlines are never implicit.
|
|
|
343 |
But since it is often convenient to insert multiple lines of text,
|
|
|
344 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
345 |
has a special
|
|
|
346 |
syntax for that case:
|
|
|
347 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
348 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
349 |
<span style="font-size: 9pt"><tt>a</tt></span></p>
|
|
|
350 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
351 |
<span style="font-size: 9pt"><tt>some lines of text</tt></span></p>
|
|
|
352 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
353 |
<span style="font-size: 9pt"><tt>to be inserted in the file,</tt></span></p>
|
|
|
354 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
355 |
<span style="font-size: 9pt"><tt>terminated by a period</tt></span></p>
|
|
|
356 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
357 |
<span style="font-size: 9pt"><tt>on a line by itself</tt></span></p>
|
|
|
358 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
359 |
<span style="font-size: 9pt"><tt>.</tt></span></p>
|
|
|
360 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
361 |
|
|
|
362 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
363 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
364 |
<span style="font-size: 10pt">In the one-line syntax, a newline character may be specified by a C-like
|
|
|
365 |
escape, so
|
|
|
366 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
367 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
368 |
<span style="font-size: 9pt"><tt>c/\n/</tt></span></p>
|
|
|
369 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
370 |
|
|
|
371 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
372 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
373 |
<span style="font-size: 10pt">replaces dot by a single newline character.
|
|
|
374 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
375 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
376 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
377 |
also has a substitute command,
|
|
|
378 |
</span><span style="font-size: 10pt"><tt>s</tt></span><span style="font-size: 10pt">:
|
|
|
379 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
380 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
381 |
<span style="font-size: 9pt"><tt>s/</tt></span><span style="font-size: 9pt"><i>expression</i></span><span style="font-size: 9pt"><tt>/</tt></span><span style="font-size: 9pt"><i>replacement</i></span><span style="font-size: 9pt"><tt>/</tt></span></p>
|
|
|
382 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
383 |
|
|
|
384 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
385 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
386 |
<span style="font-size: 10pt">substitutes the replacement text for the first match, in dot,
|
|
|
387 |
of the regular expression.
|
|
|
388 |
Thus, if dot is the string
|
|
|
389 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">,
|
|
|
390 |
the command
|
|
|
391 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
392 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
393 |
<span style="font-size: 9pt"><tt>s/t/st/</tt></span></p>
|
|
|
394 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
395 |
|
|
|
396 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
397 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
398 |
<span style="font-size: 10pt">changes it to
|
|
|
399 |
</span><span style="font-size: 10pt"><tt>Pester</tt></span><span style="font-size: 10pt">.
|
|
|
400 |
In general,
|
|
|
401 |
</span><span style="font-size: 10pt"><tt>s</tt></span><span style="font-size: 10pt">
|
|
|
402 |
is unnecessary, but it was inherited from
|
|
|
403 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
404 |
and it has some convenient variations.
|
|
|
405 |
For instance, the replacement text may include the matched text,
|
|
|
406 |
specified by
|
|
|
407 |
</span><span style="font-size: 10pt"><tt>&</tt></span><span style="font-size: 10pt">:
|
|
|
408 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
409 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
410 |
<span style="font-size: 9pt"><tt>s/Peter/Oh, &, &, &, &!/</tt></span></p>
|
|
|
411 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
412 |
|
|
|
413 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
414 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
415 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
416 |
<span style="font-size: 10pt">There are also three commands that apply programs
|
|
|
417 |
to text:
|
|
|
418 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
419 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
420 |
<span style="font-size: 9pt"><tt>< </tt></span><span style="font-size: 9pt"><i>UNIX program</i></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
421 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
422 |
|
|
|
423 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
424 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
425 |
<span style="font-size: 10pt">replaces dot by the output of the UNIX program.
|
|
|
426 |
Similarly, the
|
|
|
427 |
</span><span style="font-size: 10pt"><tt>></tt></span><span style="font-size: 10pt">
|
|
|
428 |
command
|
|
|
429 |
runs the program with dot as its standard input, and
|
|
|
430 |
</span><span style="font-size: 10pt"><tt>|</tt></span><span style="font-size: 10pt">
|
|
|
431 |
does both. For example,
|
|
|
432 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
433 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
434 |
<span style="font-size: 9pt"><tt>| sort</tt></span></p>
|
|
|
435 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
436 |
|
|
|
437 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
438 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
439 |
<span style="font-size: 10pt">replaces dot by the result of applying the standard sorting utility to it.
|
|
|
440 |
Again, newlines have no special significance for these
|
|
|
441 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
442 |
commands.
|
|
|
443 |
The text acted upon and resulting from these commands is not necessarily
|
|
|
444 |
bounded by newlines, although for connection with UNIX programs,
|
|
|
445 |
newlines may be necessary to obey conventions.
|
|
|
446 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
447 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
448 |
<span style="font-size: 10pt">One more command:
|
|
|
449 |
</span><span style="font-size: 10pt"><tt>p</tt></span><span style="font-size: 10pt">
|
|
|
450 |
prints the contents of dot.
|
|
|
451 |
Table I summarizes
|
|
|
452 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
453 |
commands.
|
|
|
454 |
</span><span style="font-size: 10pt"></span></p><center><img src="sam0.png"></center>
|
|
|
455 |
</center>
|
|
|
456 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
457 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
458 |
|
|
|
459 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
460 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
461 |
<span style="font-size: 10pt">The value of dot may be changed by
|
|
|
462 |
specifying an
|
|
|
463 |
</span><span style="font-size: 10pt"><i>address</i></span><span style="font-size: 10pt">
|
|
|
464 |
for the command.
|
|
|
465 |
The simplest address is a line number:
|
|
|
466 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
467 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
468 |
<span style="font-size: 9pt"><tt>3</tt></span></p>
|
|
|
469 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
470 |
|
|
|
471 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
472 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
473 |
<span style="font-size: 10pt">refers to the third line of the file, so
|
|
|
474 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
475 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
476 |
<span style="font-size: 9pt"><tt>3d</tt></span></p>
|
|
|
477 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
478 |
|
|
|
479 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
480 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
481 |
<span style="font-size: 10pt">deletes the third line of the file, and implicitly renumbers
|
|
|
482 |
the lines so the old line 4 is now numbered 3.
|
|
|
483 |
(This is one of the few places where
|
|
|
484 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
485 |
deals with lines directly.)
|
|
|
486 |
Line
|
|
|
487 |
</span><span style="font-size: 10pt"><tt>0</tt></span><span style="font-size: 10pt">
|
|
|
488 |
is the null string at the beginning of the file.
|
|
|
489 |
If a command consists of only an address, a
|
|
|
490 |
</span><span style="font-size: 10pt"><tt>p</tt></span><span style="font-size: 10pt">
|
|
|
491 |
command is assumed, so typing an unadorned
|
|
|
492 |
</span><span style="font-size: 10pt"><tt>3</tt></span><span style="font-size: 10pt">
|
|
|
493 |
prints line 3 on the terminal.
|
|
|
494 |
There are a couple of other basic addresses:
|
|
|
495 |
a period addresses dot itself; and
|
|
|
496 |
a dollar sign
|
|
|
497 |
(</span><span style="font-size: 10pt"><tt>$</tt></span><span style="font-size: 10pt">)
|
|
|
498 |
addresses the null string at the end of the file.
|
|
|
499 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
500 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
501 |
<span style="font-size: 10pt">An address is always a single substring of the file.
|
|
|
502 |
Thus, the address
|
|
|
503 |
</span><span style="font-size: 10pt"><tt>3</tt></span><span style="font-size: 10pt">
|
|
|
504 |
addresses the characters
|
|
|
505 |
after the second newline of
|
|
|
506 |
the file through the third newline of the file.
|
|
|
507 |
A
|
|
|
508 |
</span><span style="font-size: 10pt"><i>compound address
|
|
|
509 |
</i></span><span style="font-size: 10pt">is constructed by the comma operator
|
|
|
510 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
511 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
512 |
<span style="font-size: 9pt"><i>address1</i></span><span style="font-size: 9pt"><tt>,</tt></span><span style="font-size: 9pt"><i>address2</i></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
513 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
514 |
|
|
|
515 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
516 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
517 |
<span style="font-size: 10pt">and addresses the substring of the file from the beginning of
|
|
|
518 |
</span><span style="font-size: 10pt"><i>address1</i></span><span style="font-size: 10pt">
|
|
|
519 |
to the end of
|
|
|
520 |
</span><span style="font-size: 10pt"><i>address2</i></span><span style="font-size: 10pt">.
|
|
|
521 |
For example, the command
|
|
|
522 |
</span><span style="font-size: 10pt"><tt>3,5p</tt></span><span style="font-size: 10pt">
|
|
|
523 |
prints the third through fifth lines of the file and
|
|
|
524 |
</span><span style="font-size: 10pt"><tt>.,$d</tt></span><span style="font-size: 10pt">
|
|
|
525 |
deletes the text from the beginning of dot to the end of the file.
|
|
|
526 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
527 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
528 |
<span style="font-size: 10pt">These addresses are all absolute positions in the file, but
|
|
|
529 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
530 |
also has relative addresses, indicated by
|
|
|
531 |
</span><span style="font-size: 10pt"><tt>+</tt></span><span style="font-size: 10pt">
|
|
|
532 |
or
|
|
|
533 |
</span><span style="font-size: 10pt"><tt>-</tt></span><span style="font-size: 10pt">.
|
|
|
534 |
For example,
|
|
|
535 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
536 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
537 |
<span style="font-size: 9pt"><tt>$-3</tt></span></p>
|
|
|
538 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
539 |
|
|
|
540 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
541 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
542 |
<span style="font-size: 10pt">is the third line before the end of the file and
|
|
|
543 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
544 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
545 |
<span style="font-size: 9pt"><tt>.+1</tt></span></p>
|
|
|
546 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
547 |
|
|
|
548 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
549 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
550 |
<span style="font-size: 10pt">is the line after dot.
|
|
|
551 |
If no address appears to the left of the
|
|
|
552 |
</span><span style="font-size: 10pt"><tt>+</tt></span><span style="font-size: 10pt">
|
|
|
553 |
or
|
|
|
554 |
</span><span style="font-size: 10pt"><tt>-</tt></span><span style="font-size: 10pt">,
|
|
|
555 |
dot is assumed;
|
|
|
556 |
if nothing appears to the right,
|
|
|
557 |
</span><span style="font-size: 10pt"><tt>1</tt></span><span style="font-size: 10pt">
|
|
|
558 |
is assumed.
|
|
|
559 |
Therefore,
|
|
|
560 |
</span><span style="font-size: 10pt"><tt>.+1</tt></span><span style="font-size: 10pt">
|
|
|
561 |
may be abbreviated to just a plus sign.
|
|
|
562 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
563 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
564 |
<span style="font-size: 10pt">The
|
|
|
565 |
</span><span style="font-size: 10pt"><tt>+</tt></span><span style="font-size: 10pt">
|
|
|
566 |
operator acts relative to the end of its first argument, while the
|
|
|
567 |
</span><span style="font-size: 10pt"><tt>-</tt></span><span style="font-size: 10pt">
|
|
|
568 |
operator acts relative to the beginning. Thus
|
|
|
569 |
</span><span style="font-size: 10pt"><tt>.+1</tt></span><span style="font-size: 10pt">
|
|
|
570 |
addresses the first line after dot,
|
|
|
571 |
</span><span style="font-size: 10pt"><tt>.-</tt></span><span style="font-size: 10pt">
|
|
|
572 |
addresses the first line before dot, and
|
|
|
573 |
</span><span style="font-size: 10pt"><tt>+-</tt></span><span style="font-size: 10pt">
|
|
|
574 |
refers to the line containing the end of dot. (Dot may span multiple lines, and
|
|
|
575 |
</span><span style="font-size: 10pt"><tt>+</tt></span><span style="font-size: 10pt">
|
|
|
576 |
selects the line after the end of dot, then
|
|
|
577 |
</span><span style="font-size: 10pt"><tt>-</tt></span><span style="font-size: 10pt">
|
|
|
578 |
backs up one line.)
|
|
|
579 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
580 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
581 |
<span style="font-size: 10pt">The final type of address is a regular expression, which addresses the
|
|
|
582 |
text matched by the expression. The expression is enclosed in slashes, as in
|
|
|
583 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
584 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
585 |
<span style="font-size: 9pt"><tt>/</tt></span><span style="font-size: 9pt"><i>expression</i></span><span style="font-size: 9pt"><tt>/</tt></span></p>
|
|
|
586 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
587 |
|
|
|
588 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
589 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
590 |
<span style="font-size: 10pt">The expressions are the same as those in the UNIX program
|
|
|
591 |
</span><span style="font-size: 10pt"><tt>egrep</tt></span><span style="font-size: 10pt">,<sup></sup></span><sup><span style="font-size: 6pt">6,7</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
592 |
and include closures, alternations, and so on.
|
|
|
593 |
They find the
|
|
|
594 |
</span><span style="font-size: 10pt"><i>leftmost longest
|
|
|
595 |
</i></span><span style="font-size: 10pt">string that matches the expression, that is,
|
|
|
596 |
the first match after the point where the search is started,
|
|
|
597 |
and if more than one match begins at the same spot, the longest such match.
|
|
|
598 |
(I assume familiarity with the syntax for regular expressions in UNIX programs.<sup></sup></span><sup><span style="font-size: 6pt">9</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">)
|
|
|
599 |
For example,
|
|
|
600 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
601 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
602 |
<span style="font-size: 9pt"><tt>/x/</tt></span></p>
|
|
|
603 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
604 |
|
|
|
605 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
606 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
607 |
<span style="font-size: 10pt">matches the next
|
|
|
608 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
609 |
character in the file,
|
|
|
610 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
611 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
612 |
<span style="font-size: 9pt"><tt>/xx*/</tt></span></p>
|
|
|
613 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
614 |
|
|
|
615 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
616 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
617 |
<span style="font-size: 10pt">matches the next run of one or more
|
|
|
618 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">’s,
|
|
|
619 |
and
|
|
|
620 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
621 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
622 |
<span style="font-size: 9pt"><tt>/x|Peter/</tt></span></p>
|
|
|
623 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
624 |
|
|
|
625 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
626 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
627 |
<span style="font-size: 10pt">matches the next
|
|
|
628 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
629 |
or
|
|
|
630 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">.
|
|
|
631 |
For compatibility with other UNIX programs, the ‘any character’ operator,
|
|
|
632 |
a period,
|
|
|
633 |
does not match a newline, so
|
|
|
634 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
635 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
636 |
<span style="font-size: 9pt"><tt>/.*/</tt></span></p>
|
|
|
637 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
638 |
|
|
|
639 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
640 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
641 |
<span style="font-size: 10pt">matches the text from dot to the end of the line, but excludes the newline
|
|
|
642 |
and so will not match across
|
|
|
643 |
the line boundary.
|
|
|
644 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
645 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
646 |
<span style="font-size: 10pt">Regular expressions are always relative addresses.
|
|
|
647 |
The direction is forwards by default,
|
|
|
648 |
so
|
|
|
649 |
</span><span style="font-size: 10pt"><tt>/Peter/</tt></span><span style="font-size: 10pt">
|
|
|
650 |
is really an abbreviation for
|
|
|
651 |
</span><span style="font-size: 10pt"><tt>+/Peter/</tt></span><span style="font-size: 10pt">.
|
|
|
652 |
The search can be reversed with a minus sign, so
|
|
|
653 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
654 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
655 |
<span style="font-size: 9pt"><tt></tt></span><span style="font-size: 9pt"><tt>-/Peter/</tt></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
656 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
657 |
|
|
|
658 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
659 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
660 |
<span style="font-size: 10pt">finds the first
|
|
|
661 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">
|
|
|
662 |
before dot.
|
|
|
663 |
Regular expressions may be used with other address forms, so
|
|
|
664 |
</span><span style="font-size: 10pt"><tt>0+/Peter/</tt></span><span style="font-size: 10pt">
|
|
|
665 |
finds the first
|
|
|
666 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">
|
|
|
667 |
in the file and
|
|
|
668 |
</span><span style="font-size: 10pt"><tt>$-/Peter/</tt></span><span style="font-size: 10pt">
|
|
|
669 |
finds the last.
|
|
|
670 |
Table II summarizes
|
|
|
671 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
672 |
addresses.
|
|
|
673 |
</span><span style="font-size: 10pt"></span></p><center><img src="sam1.png"></center>
|
|
|
674 |
</center>
|
|
|
675 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
676 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
677 |
|
|
|
678 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
679 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
680 |
<span style="font-size: 10pt">The language discussed so far will not seem novel
|
|
|
681 |
to people who use UNIX text editors
|
|
|
682 |
such as
|
|
|
683 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
684 |
or
|
|
|
685 |
</span><span style="font-size: 10pt"><tt>vi</tt></span><span style="font-size: 10pt">.<sup></sup></span><sup><span style="font-size: 6pt">9</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
686 |
Moreover, the kinds of editing operations these commands allow, with the exception
|
|
|
687 |
of regular expressions and line numbers,
|
|
|
688 |
are clearly more conveniently handled by a mouse-based interface.
|
|
|
689 |
Indeed,
|
|
|
690 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
691 |
mouse language (discussed at length below) is the means by which
|
|
|
692 |
simple changes are usually made.
|
|
|
693 |
For large or repetitive changes, however, a textual language
|
|
|
694 |
outperforms a manual interface.
|
|
|
695 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
696 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
697 |
<span style="font-size: 10pt">Imagine that, instead of deleting just one occurrence of the string
|
|
|
698 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">,
|
|
|
699 |
we wanted to eliminate every
|
|
|
700 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">.
|
|
|
701 |
What’s needed is an iterator that runs a command for each occurrence of some
|
|
|
702 |
text.
|
|
|
703 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">’s
|
|
|
704 |
iterator is called
|
|
|
705 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">,
|
|
|
706 |
for extract:
|
|
|
707 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
708 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
709 |
<span style="font-size: 9pt"><tt>x/</tt></span><span style="font-size: 9pt"><i>expression</i></span><span style="font-size: 9pt"><tt>/ </tt></span><span style="font-size: 9pt"><i>command</i></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
710 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
711 |
|
|
|
712 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
713 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
714 |
<span style="font-size: 10pt">finds all matches in dot of the specified expression, and for each
|
|
|
715 |
such match, sets dot to the text matched and runs the command.
|
|
|
716 |
So to delete all the
|
|
|
717 |
</span><span style="font-size: 10pt"><tt>Peters:</tt></span><span style="font-size: 10pt">
|
|
|
718 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
719 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
720 |
<span style="font-size: 9pt"><tt>0,$ x/Peter/ d</tt></span></p>
|
|
|
721 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
722 |
|
|
|
723 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
724 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
725 |
<span style="font-size: 10pt">(Blanks in these examples are to improve readability;
|
|
|
726 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
727 |
neither requires nor interprets them.)
|
|
|
728 |
This searches the entire file
|
|
|
729 |
(</span><span style="font-size: 10pt"><tt>0,$</tt></span><span style="font-size: 10pt">)
|
|
|
730 |
for occurrences of the string
|
|
|
731 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">,
|
|
|
732 |
and runs the
|
|
|
733 |
</span><span style="font-size: 10pt"><tt>d</tt></span><span style="font-size: 10pt">
|
|
|
734 |
command with dot set to each such occurrence.
|
|
|
735 |
(By contrast, the comparable
|
|
|
736 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
737 |
command would delete all
|
|
|
738 |
</span><span style="font-size: 10pt"><i>lines</i></span><span style="font-size: 10pt">
|
|
|
739 |
containing
|
|
|
740 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">;
|
|
|
741 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
742 |
deletes only the
|
|
|
743 |
</span><span style="font-size: 10pt"><tt>Peters</tt></span><span style="font-size: 10pt">.)
|
|
|
744 |
The address
|
|
|
745 |
</span><span style="font-size: 10pt"><tt>0,$</tt></span><span style="font-size: 10pt">
|
|
|
746 |
is commonly used, and may be abbreviated to just a comma.
|
|
|
747 |
As another example,
|
|
|
748 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
749 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
750 |
<span style="font-size: 9pt"><tt>, x/Peter/ p</tt></span></p>
|
|
|
751 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
752 |
|
|
|
753 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
754 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
755 |
<span style="font-size: 10pt">prints a list of
|
|
|
756 |
</span><span style="font-size: 10pt"><tt>Peters,</tt></span><span style="font-size: 10pt">
|
|
|
757 |
one for each appearance in the file, with no intervening text (not even newlines
|
|
|
758 |
to separate the instances).
|
|
|
759 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
760 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
761 |
<span style="font-size: 10pt">Of course, the text extracted by
|
|
|
762 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
763 |
may be selected by a regular expression,
|
|
|
764 |
which complicates deciding what set of matches is chosen —
|
|
|
765 |
matches may overlap. This is resolved by generating the matches
|
|
|
766 |
starting from the beginning of dot using the leftmost-longest rule,
|
|
|
767 |
and searching for each match starting from the end of the previous one.
|
|
|
768 |
Regular expressions may also match null strings, but a null match
|
|
|
769 |
adjacent to a non-null match is never selected; at least one character
|
|
|
770 |
must intervene.
|
|
|
771 |
For example,
|
|
|
772 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
773 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
774 |
<span style="font-size: 9pt"><tt>, c/AAA/</tt></span></p>
|
|
|
775 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
776 |
<span style="font-size: 9pt"><tt>x/B*/ c/-/</tt></span></p>
|
|
|
777 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
778 |
<span style="font-size: 9pt"><tt>, p</tt></span></p>
|
|
|
779 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
780 |
|
|
|
781 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
782 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
783 |
<span style="font-size: 10pt">produces as output
|
|
|
784 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
785 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
786 |
<span style="font-size: 9pt"><tt>-A-A-A-</tt></span></p>
|
|
|
787 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
788 |
|
|
|
789 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
790 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
791 |
<span style="font-size: 10pt">because the pattern
|
|
|
792 |
</span><span style="font-size: 10pt"><tt>B*</tt></span><span style="font-size: 10pt">
|
|
|
793 |
matches the null strings separating the
|
|
|
794 |
</span><span style="font-size: 10pt"><tt>A</tt></span><span style="font-size: 10pt">’s.
|
|
|
795 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
796 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
797 |
<span style="font-size: 10pt">The
|
|
|
798 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
799 |
command has a complement,
|
|
|
800 |
</span><span style="font-size: 10pt"><tt>y</tt></span><span style="font-size: 10pt">,
|
|
|
801 |
with similar syntax, that executes the command with dot set to the text
|
|
|
802 |
</span><span style="font-size: 10pt"><i>between</i></span><span style="font-size: 10pt">
|
|
|
803 |
the matches of the expression.
|
|
|
804 |
For example,
|
|
|
805 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
806 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
807 |
<span style="font-size: 9pt"><tt>, c/AAA/</tt></span></p>
|
|
|
808 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
809 |
<span style="font-size: 9pt"><tt>y/A/ c/-/</tt></span></p>
|
|
|
810 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
811 |
<span style="font-size: 9pt"><tt>, p</tt></span></p>
|
|
|
812 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
813 |
|
|
|
814 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
815 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
816 |
<span style="font-size: 10pt">produces the same result as the example above.
|
|
|
817 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
818 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
819 |
<span style="font-size: 10pt">The
|
|
|
820 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
821 |
and
|
|
|
822 |
</span><span style="font-size: 10pt"><tt>y</tt></span><span style="font-size: 10pt">
|
|
|
823 |
commands are looping constructs, and
|
|
|
824 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
825 |
has a pair of conditional commands to go with them.
|
|
|
826 |
They have similar syntax:
|
|
|
827 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
828 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
829 |
<span style="font-size: 9pt"><tt>g/</tt></span><span style="font-size: 9pt"><i>expression</i></span><span style="font-size: 9pt"><tt>/ </tt></span><span style="font-size: 9pt"><i>command</i></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
830 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
831 |
|
|
|
832 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
833 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
834 |
<span style="font-size: 10pt">(guard)
|
|
|
835 |
runs the command exactly once if dot contains a match of the expression.
|
|
|
836 |
This is different from
|
|
|
837 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">,
|
|
|
838 |
which runs the command for
|
|
|
839 |
</span><span style="font-size: 10pt"><i>each</i></span><span style="font-size: 10pt">
|
|
|
840 |
match:
|
|
|
841 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
842 |
loops;
|
|
|
843 |
</span><span style="font-size: 10pt"><tt>g</tt></span><span style="font-size: 10pt">
|
|
|
844 |
merely tests, without changing the value of dot.
|
|
|
845 |
Thus,
|
|
|
846 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
847 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
848 |
<span style="font-size: 9pt"><tt>, x/Peter/ d</tt></span></p>
|
|
|
849 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
850 |
|
|
|
851 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
852 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
853 |
<span style="font-size: 10pt">deletes all occurrences of
|
|
|
854 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">,
|
|
|
855 |
but
|
|
|
856 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
857 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
858 |
<span style="font-size: 9pt"><tt>, g/Peter/ d</tt></span></p>
|
|
|
859 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
860 |
|
|
|
861 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
862 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
863 |
<span style="font-size: 10pt">deletes the whole file (reduces it to a null string) if
|
|
|
864 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">
|
|
|
865 |
occurs anywhere in the text.
|
|
|
866 |
The complementary conditional is
|
|
|
867 |
</span><span style="font-size: 10pt"><tt>v</tt></span><span style="font-size: 10pt">,
|
|
|
868 |
which runs the command if there is
|
|
|
869 |
</span><span style="font-size: 10pt"><i>no</i></span><span style="font-size: 10pt">
|
|
|
870 |
match of the expression.
|
|
|
871 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
872 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
873 |
<span style="font-size: 10pt">These control-structure-like commands may be composed to construct more
|
|
|
874 |
involved operations. For example, to print those lines of text that
|
|
|
875 |
contain the string
|
|
|
876 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">:
|
|
|
877 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
878 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
879 |
<span style="font-size: 9pt"><tt>, x/.*\n/ g/Peter/ p</tt></span></p>
|
|
|
880 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
881 |
|
|
|
882 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
883 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
884 |
<span style="font-size: 10pt">The
|
|
|
885 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
886 |
breaks the file into lines, the
|
|
|
887 |
</span><span style="font-size: 10pt"><tt>g</tt></span><span style="font-size: 10pt">
|
|
|
888 |
selects those lines containing
|
|
|
889 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">,
|
|
|
890 |
and the
|
|
|
891 |
</span><span style="font-size: 10pt"><tt>p</tt></span><span style="font-size: 10pt">
|
|
|
892 |
prints them.
|
|
|
893 |
This command gives an address for the
|
|
|
894 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
895 |
command (the whole file), but because
|
|
|
896 |
</span><span style="font-size: 10pt"><tt>g</tt></span><span style="font-size: 10pt">
|
|
|
897 |
does not have an explicit address, it applies to the value of
|
|
|
898 |
dot produced by the
|
|
|
899 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
900 |
command, that is, to each line.
|
|
|
901 |
All commands in
|
|
|
902 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
903 |
except for the command to write a file to disc use dot for the
|
|
|
904 |
default address.
|
|
|
905 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
906 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
907 |
<span style="font-size: 10pt">Composition may be continued indefinitely.
|
|
|
908 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
909 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
910 |
<span style="font-size: 9pt"><tt>, x/.*\n/ g/Peter/ v/SaltPeter/ p</tt></span></p>
|
|
|
911 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
912 |
|
|
|
913 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
914 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
915 |
<span style="font-size: 10pt">prints those lines containing
|
|
|
916 |
</span><span style="font-size: 10pt"><tt>Peter</tt></span><span style="font-size: 10pt">
|
|
|
917 |
but
|
|
|
918 |
</span><span style="font-size: 10pt"><i>not</i></span><span style="font-size: 10pt">
|
|
|
919 |
those containing
|
|
|
920 |
</span><span style="font-size: 10pt"><tt>SaltPeter</tt></span><span style="font-size: 10pt">.
|
|
|
921 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
922 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
923 |
<span style="font-size: 10pt"><b>Structural Regular Expressions
|
|
|
924 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
925 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
926 |
<span style="font-size: 10pt">Unlike other UNIX text editors,
|
|
|
927 |
including the non-interactive ones such as
|
|
|
928 |
</span><span style="font-size: 10pt"><tt>sed</tt></span><span style="font-size: 10pt">
|
|
|
929 |
and
|
|
|
930 |
</span><span style="font-size: 10pt"><tt>awk</tt></span><span style="font-size: 10pt">,<sup></sup></span><sup><span style="font-size: 6pt">7</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
931 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
932 |
is good for manipulating files with multi-line ‘records.’
|
|
|
933 |
An example is an on-line phone book composed of records,
|
|
|
934 |
separated by blank lines, of the form
|
|
|
935 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
936 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
937 |
<span style="font-size: 9pt"><tt>Herbert Tic</tt></span></p>
|
|
|
938 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
939 |
<span style="font-size: 9pt"><tt>44 Turnip Ave., Endive, NJ</tt></span></p>
|
|
|
940 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
941 |
<span style="font-size: 9pt"><tt>201-5555642</tt></span></p>
|
|
|
942 |
<p style="margin-top: 0; margin-bottom: 0.15in"></p>
|
|
|
943 |
|
|
|
944 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
945 |
<span style="font-size: 9pt"><tt>Norbert Twinge</tt></span></p>
|
|
|
946 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
947 |
<span style="font-size: 9pt"><tt>16 Potato St., Cabbagetown, NJ</tt></span></p>
|
|
|
948 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
949 |
<span style="font-size: 9pt"><tt>201-5553145</tt></span></p>
|
|
|
950 |
<p style="margin-top: 0; margin-bottom: 0.15in"></p>
|
|
|
951 |
|
|
|
952 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
953 |
<span style="font-size: 9pt"><tt>...</tt></span></p>
|
|
|
954 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
955 |
|
|
|
956 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
957 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
958 |
<span style="font-size: 10pt">The format may be encoded as a regular expression:
|
|
|
959 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
960 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
961 |
<span style="font-size: 9pt"><tt>(.+\n)+</tt></span></p>
|
|
|
962 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
963 |
|
|
|
964 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
965 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
966 |
<span style="font-size: 10pt">that is, a sequence of one or more non-blank lines.
|
|
|
967 |
The command to print Mr. Tic’s entire record is then
|
|
|
968 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
969 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
970 |
<span style="font-size: 9pt"><tt>, x/(.+\n)+/ g/^Herbert Tic$/ p</tt></span></p>
|
|
|
971 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
972 |
|
|
|
973 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
974 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
975 |
<span style="font-size: 10pt">and that to extract just the phone number is
|
|
|
976 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
977 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
978 |
<span style="font-size: 9pt"><tt>, x/(.+\n)+/ g/^Herbert Tic$/ x/^[0-9]*-[0-9]*\n/ p</tt></span></p>
|
|
|
979 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
980 |
|
|
|
981 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
982 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
983 |
<span style="font-size: 10pt">The latter command breaks the file into records,
|
|
|
984 |
chooses Mr. Tic’s record,
|
|
|
985 |
extracts the phone number from the record,
|
|
|
986 |
and finally prints the number.
|
|
|
987 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
988 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
989 |
<span style="font-size: 10pt">A more involved problem is that of
|
|
|
990 |
renaming a particular variable, say
|
|
|
991 |
</span><span style="font-size: 10pt"><tt>n</tt></span><span style="font-size: 10pt">,
|
|
|
992 |
to
|
|
|
993 |
</span><span style="font-size: 10pt"><tt>num</tt></span><span style="font-size: 10pt">
|
|
|
994 |
in a C program.
|
|
|
995 |
The obvious first attempt,
|
|
|
996 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
997 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
998 |
<span style="font-size: 9pt"><tt>, x/n/ c/num/</tt></span></p>
|
|
|
999 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1000 |
|
|
|
1001 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1002 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1003 |
<span style="font-size: 10pt">is badly flawed: it changes not only the variable
|
|
|
1004 |
</span><span style="font-size: 10pt"><tt>n</tt></span><span style="font-size: 10pt">
|
|
|
1005 |
but any letter
|
|
|
1006 |
</span><span style="font-size: 10pt"><tt>n</tt></span><span style="font-size: 10pt">
|
|
|
1007 |
that appears.
|
|
|
1008 |
We need to extract all the variables, and select those that match
|
|
|
1009 |
</span><span style="font-size: 10pt"><tt>n</tt></span><span style="font-size: 10pt">
|
|
|
1010 |
and only
|
|
|
1011 |
</span><span style="font-size: 10pt"><tt>n</tt></span><span style="font-size: 10pt">:
|
|
|
1012 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1013 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1014 |
<span style="font-size: 9pt"><tt>, x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/</tt></span></p>
|
|
|
1015 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1016 |
|
|
|
1017 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1018 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1019 |
<span style="font-size: 10pt">The pattern
|
|
|
1020 |
</span><span style="font-size: 10pt"><tt>[A-Za-z_][A-Za-z_0-9]*</tt></span><span style="font-size: 10pt">
|
|
|
1021 |
matches C identifiers.
|
|
|
1022 |
Next
|
|
|
1023 |
</span><span style="font-size: 10pt"><tt>g/n/</tt></span><span style="font-size: 10pt">
|
|
|
1024 |
selects those containing an
|
|
|
1025 |
</span><span style="font-size: 10pt"><tt>n</tt></span><span style="font-size: 10pt">.
|
|
|
1026 |
Then
|
|
|
1027 |
</span><span style="font-size: 10pt"><tt>v/../</tt></span><span style="font-size: 10pt">
|
|
|
1028 |
rejects those containing two (or more) characters, and finally
|
|
|
1029 |
</span><span style="font-size: 10pt"><tt>c/num/</tt></span><span style="font-size: 10pt">
|
|
|
1030 |
changes the remainder (identifiers
|
|
|
1031 |
</span><span style="font-size: 10pt"><tt>n</tt></span><span style="font-size: 10pt">)
|
|
|
1032 |
to
|
|
|
1033 |
</span><span style="font-size: 10pt"><tt>num</tt></span><span style="font-size: 10pt">.
|
|
|
1034 |
This version clearly works much better, but there may still be problems.
|
|
|
1035 |
For example, in C character and string constants, the sequence
|
|
|
1036 |
</span><span style="font-size: 10pt"><tt>\n</tt></span><span style="font-size: 10pt">
|
|
|
1037 |
is interpreted as a newline character, and we don’t want to change it to
|
|
|
1038 |
</span><span style="font-size: 10pt"><tt>\num.</tt></span><span style="font-size: 10pt">
|
|
|
1039 |
This problem can be forestalled with a
|
|
|
1040 |
</span><span style="font-size: 10pt"><tt>y</tt></span><span style="font-size: 10pt">
|
|
|
1041 |
command:
|
|
|
1042 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1043 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1044 |
<span style="font-size: 9pt"><tt>, y/\\n/ x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/</tt></span></p>
|
|
|
1045 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1046 |
|
|
|
1047 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1048 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1049 |
<span style="font-size: 10pt">(the second
|
|
|
1050 |
</span><span style="font-size: 10pt"><tt>\</tt></span><span style="font-size: 10pt">
|
|
|
1051 |
is necessary because of lexical conventions in regular expressions),
|
|
|
1052 |
or we could even reject character constants and strings outright:
|
|
|
1053 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1054 |
<p style="line-height: 1.1em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1055 |
<span style="font-size: 9pt"><tt>,y/’[^’]*’/ y/"[^"]*"/ x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/</tt></span></p>
|
|
|
1056 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1057 |
|
|
|
1058 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1059 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1060 |
<span style="font-size: 10pt">The
|
|
|
1061 |
</span><span style="font-size: 10pt"><tt>y</tt></span><span style="font-size: 10pt">
|
|
|
1062 |
commands in this version exclude from consideration all character constants
|
|
|
1063 |
and strings.
|
|
|
1064 |
The only remaining problem is to deal with the possible occurrence of
|
|
|
1065 |
</span><span style="font-size: 10pt"><tt>\’</tt></span><span style="font-size: 10pt">
|
|
|
1066 |
or
|
|
|
1067 |
</span><span style="font-size: 10pt"><tt>\"</tt></span><span style="font-size: 10pt">
|
|
|
1068 |
within these sequences, but it’s easy to see how to resolve this difficulty.
|
|
|
1069 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1070 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1071 |
<span style="font-size: 10pt">The point of these composed commands is successive refinement.
|
|
|
1072 |
A simple version of the command is tried, and if it’s not good enough,
|
|
|
1073 |
it can be honed by adding a clause or two.
|
|
|
1074 |
(Mistakes can be undone; see below.
|
|
|
1075 |
Also, the mouse language makes it unnecessary to retype the command each time.)
|
|
|
1076 |
The resulting chains of commands are somewhat reminiscent of
|
|
|
1077 |
shell pipelines.<sup></sup></span><sup><span style="font-size: 6pt">7</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
1078 |
Unlike pipelines, though, which pass along modified
|
|
|
1079 |
</span><span style="font-size: 10pt"><i>data</i></span><span style="font-size: 10pt">,
|
|
|
1080 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1081 |
commands pass a
|
|
|
1082 |
</span><span style="font-size: 10pt"><i>view</i></span><span style="font-size: 10pt">
|
|
|
1083 |
of the data.
|
|
|
1084 |
The text at each step of the command is the same, but which pieces
|
|
|
1085 |
are selected is refined step by step until the correct piece is
|
|
|
1086 |
available to the final step of the command line, which ultimately makes the change.
|
|
|
1087 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1088 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1089 |
<span style="font-size: 10pt">In other UNIX programs, regular expressions are used only for selection,
|
|
|
1090 |
as in the
|
|
|
1091 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1092 |
</span><span style="font-size: 10pt"><tt>g</tt></span><span style="font-size: 10pt">
|
|
|
1093 |
command, never for extraction as in the
|
|
|
1094 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
1095 |
or
|
|
|
1096 |
</span><span style="font-size: 10pt"><tt>y</tt></span><span style="font-size: 10pt">
|
|
|
1097 |
command.
|
|
|
1098 |
For example, patterns in
|
|
|
1099 |
</span><span style="font-size: 10pt"><tt>awk</tt></span><span style="font-size: 10pt"><sup></sup></span><sup><span style="font-size: 6pt">7</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
1100 |
are used to select lines to be operated on, but cannot be used
|
|
|
1101 |
to describe the format of the input text, or to handle newline-free text.
|
|
|
1102 |
The use of regular expressions to describe the structure of a piece
|
|
|
1103 |
of text rather than its contents, as in the
|
|
|
1104 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
1105 |
command,
|
|
|
1106 |
has been given a name:
|
|
|
1107 |
</span><span style="font-size: 10pt"><i>structural regular expressions.
|
|
|
1108 |
</i></span><span style="font-size: 10pt">When they are composed, as in the above example,
|
|
|
1109 |
they are pleasantly expressive.
|
|
|
1110 |
Their use is discussed at greater length elsewhere.<sup></sup></span><sup><span style="font-size: 6pt">10</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
1111 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1112 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1113 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1114 |
<span style="font-size: 10pt"><b>Multiple files
|
|
|
1115 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1116 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1117 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
1118 |
has a few other commands, mostly relating to input and output.
|
|
|
1119 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1120 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1121 |
<span style="font-size: 9pt"><tt>e discfilename</tt></span></p>
|
|
|
1122 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1123 |
|
|
|
1124 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1125 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1126 |
<span style="font-size: 10pt">replaces the contents and name of the current file with those of the named
|
|
|
1127 |
disc file;
|
|
|
1128 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1129 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1130 |
<span style="font-size: 9pt"><tt>w discfilename</tt></span></p>
|
|
|
1131 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1132 |
|
|
|
1133 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1134 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1135 |
<span style="font-size: 10pt">writes the contents to the named disc file; and
|
|
|
1136 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1137 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1138 |
<span style="font-size: 9pt"><tt>r discfilename</tt></span></p>
|
|
|
1139 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1140 |
|
|
|
1141 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1142 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1143 |
<span style="font-size: 10pt">replaces dot with the contents of the named disc file.
|
|
|
1144 |
All these commands use the current file’s name if none is specified.
|
|
|
1145 |
Finally,
|
|
|
1146 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1147 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1148 |
<span style="font-size: 9pt"><tt>f discfilename</tt></span></p>
|
|
|
1149 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1150 |
|
|
|
1151 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1152 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1153 |
<span style="font-size: 10pt">changes the name associated with the file and displays the result:
|
|
|
1154 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1155 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1156 |
<span style="font-size: 9pt"><tt>’-. discfilename</tt></span></p>
|
|
|
1157 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1158 |
|
|
|
1159 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1160 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1161 |
<span style="font-size: 10pt">This output is called the file’s
|
|
|
1162 |
</span><span style="font-size: 10pt"><i>menu line,
|
|
|
1163 |
</i></span><span style="font-size: 10pt">because it is the contents of the file’s line in the button 3 menu (described
|
|
|
1164 |
in the
|
|
|
1165 |
next section).
|
|
|
1166 |
The first three characters are a concise notation for the state of the file.
|
|
|
1167 |
The apostrophe signifies that the file is modified.
|
|
|
1168 |
The minus sign indicates the number of windows
|
|
|
1169 |
open on the file (see the next section):
|
|
|
1170 |
</span><span style="font-size: 10pt"><tt>-</tt></span><span style="font-size: 10pt">
|
|
|
1171 |
means none,
|
|
|
1172 |
</span><span style="font-size: 10pt"><tt>+</tt></span><span style="font-size: 10pt">
|
|
|
1173 |
means one, and
|
|
|
1174 |
</span><span style="font-size: 10pt"><tt>*</tt></span><span style="font-size: 10pt">
|
|
|
1175 |
means more than one.
|
|
|
1176 |
Finally, the period indicates that this is the current file.
|
|
|
1177 |
These characters are useful for controlling the
|
|
|
1178 |
</span><span style="font-size: 10pt"><tt>X</tt></span><span style="font-size: 10pt">
|
|
|
1179 |
command, described shortly.
|
|
|
1180 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1181 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1182 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
1183 |
may be started with a set of disc files (such as all the source for
|
|
|
1184 |
a program) by invoking it with a list of file names as arguments, and
|
|
|
1185 |
more may be added or deleted on demand.
|
|
|
1186 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1187 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1188 |
<span style="font-size: 9pt"><tt>B discfile1 discfile2 ...</tt></span></p>
|
|
|
1189 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1190 |
|
|
|
1191 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1192 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1193 |
<span style="font-size: 10pt">adds the named files to
|
|
|
1194 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
1195 |
list, and
|
|
|
1196 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1197 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1198 |
<span style="font-size: 9pt"><tt>D discfile1 discfile2 ...</tt></span></p>
|
|
|
1199 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1200 |
|
|
|
1201 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1202 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1203 |
<span style="font-size: 10pt">removes them from
|
|
|
1204 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
1205 |
memory (without effect on associated disc files).
|
|
|
1206 |
Both these commands have a syntax for using the shell<sup></sup></span><sup><span style="font-size: 6pt">7</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
1207 |
(the UNIX command interpreter) to generate the lists:
|
|
|
1208 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1209 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1210 |
<span style="font-size: 9pt"><tt>B <echo *.c</tt></span></p>
|
|
|
1211 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1212 |
|
|
|
1213 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1214 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1215 |
<span style="font-size: 10pt">will add all C source files, and
|
|
|
1216 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1217 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1218 |
<span style="font-size: 9pt"><tt>B <grep -l variable *.c</tt></span></p>
|
|
|
1219 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1220 |
|
|
|
1221 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1222 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1223 |
<span style="font-size: 10pt">will add all C source files referencing a particular variable
|
|
|
1224 |
(the UNIX command
|
|
|
1225 |
</span><span style="font-size: 10pt"><tt>grep\fP-l
|
|
|
1226 |
lists all files in its arguments that contain matches of
|
|
|
1227 |
the specified regular expression).
|
|
|
1228 |
Finally,
|
|
|
1229 |
</tt></span><span style="font-size: 10pt"><tt>D</tt></span><span style="font-size: 10pt"><tt>
|
|
|
1230 |
without arguments deletes the current file.
|
|
|
1231 |
</tt></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1232 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1233 |
<span style="font-size: 10pt">There are two ways to change which file is current:
|
|
|
1234 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1235 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1236 |
<span style="font-size: 9pt"><tt>b filename</tt></span></p>
|
|
|
1237 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1238 |
|
|
|
1239 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1240 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1241 |
<span style="font-size: 10pt">makes the named file current.
|
|
|
1242 |
The
|
|
|
1243 |
</span><span style="font-size: 10pt"><tt>B</tt></span><span style="font-size: 10pt">
|
|
|
1244 |
command
|
|
|
1245 |
does the same, but also adds any new files to
|
|
|
1246 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
1247 |
list.
|
|
|
1248 |
(In practice, of course, the current file
|
|
|
1249 |
is usually chosen by mouse actions, not by textual commands.)
|
|
|
1250 |
The other way is to use a form of address that refers to files:
|
|
|
1251 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1252 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1253 |
<span style="font-size: 9pt"><tt>"</tt></span><span style="font-size: 9pt"><i>expression</i></span><span style="font-size: 9pt"><tt>" </tt></span><span style="font-size: 9pt"><i>address</i></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
1254 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1255 |
|
|
|
1256 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1257 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1258 |
<span style="font-size: 10pt">refers to the address evaluated in the file whose menu line
|
|
|
1259 |
matches the expression (there must be exactly one match).
|
|
|
1260 |
For example,
|
|
|
1261 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1262 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1263 |
<span style="font-size: 9pt"><tt>"peter.c" 3</tt></span></p>
|
|
|
1264 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1265 |
|
|
|
1266 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1267 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1268 |
<span style="font-size: 10pt">refers to the third line of the file whose name matches
|
|
|
1269 |
</span><span style="font-size: 10pt"><tt>peter.c</tt></span><span style="font-size: 10pt">.
|
|
|
1270 |
This is most useful in the move
|
|
|
1271 |
(</span><span style="font-size: 10pt"><tt>m</tt></span><span style="font-size: 10pt">)
|
|
|
1272 |
and copy
|
|
|
1273 |
(</span><span style="font-size: 10pt"><tt>t</tt></span><span style="font-size: 10pt">)
|
|
|
1274 |
commands:
|
|
|
1275 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1276 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1277 |
<span style="font-size: 9pt"><tt>0,$ t "peter.c" 0</tt></span></p>
|
|
|
1278 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1279 |
|
|
|
1280 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1281 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1282 |
<span style="font-size: 10pt">makes a copy of the current file at the beginning of
|
|
|
1283 |
</span><span style="font-size: 10pt"><tt>peter.c</tt></span><span style="font-size: 10pt">.
|
|
|
1284 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1285 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1286 |
<span style="font-size: 10pt">The
|
|
|
1287 |
</span><span style="font-size: 10pt"><tt>X</tt></span><span style="font-size: 10pt">
|
|
|
1288 |
command
|
|
|
1289 |
is a looping construct, like
|
|
|
1290 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">,
|
|
|
1291 |
that refers to files instead of strings:
|
|
|
1292 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1293 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1294 |
<span style="font-size: 9pt"><tt>X/</tt></span><span style="font-size: 9pt"><i>expression</i></span><span style="font-size: 9pt"><tt>/ </tt></span><span style="font-size: 9pt"><i>command</i></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
1295 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1296 |
|
|
|
1297 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1298 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1299 |
<span style="font-size: 10pt">runs the command in all
|
|
|
1300 |
files whose menu lines match the expression. The best example is
|
|
|
1301 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1302 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1303 |
<span style="font-size: 9pt"><tt>X/’/ w</tt></span></p>
|
|
|
1304 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1305 |
|
|
|
1306 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1307 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1308 |
<span style="font-size: 10pt">which writes to disc all modified files.
|
|
|
1309 |
</span><span style="font-size: 10pt"><tt>Y</tt></span><span style="font-size: 10pt">
|
|
|
1310 |
is the complement of
|
|
|
1311 |
</span><span style="font-size: 10pt"><tt>X</tt></span><span style="font-size: 10pt">:
|
|
|
1312 |
it runs the command on all files whose menu lines don’t match the expression:
|
|
|
1313 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1314 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1315 |
<span style="font-size: 9pt"><tt>Y/\.c/ D</tt></span></p>
|
|
|
1316 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1317 |
|
|
|
1318 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1319 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1320 |
<span style="font-size: 10pt">deletes all files that don’t have
|
|
|
1321 |
</span><span style="font-size: 10pt"><tt>.c</tt></span><span style="font-size: 10pt">
|
|
|
1322 |
in their names, that is, it keeps all C source files and deletes the rest.
|
|
|
1323 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1324 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1325 |
<span style="font-size: 10pt">Braces allow commands to be grouped, so
|
|
|
1326 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1327 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1328 |
<span style="font-size: 9pt"><tt>{</tt></span></p>
|
|
|
1329 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1330 |
<span style="font-size: 9pt"><tt> </tt></span><span style="font-size: 9pt"><i>command1</i></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
1331 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1332 |
<span style="font-size: 9pt"><tt> </tt></span><span style="font-size: 9pt"><i>command2</i></span><span style="font-size: 9pt"><tt></tt></span></p>
|
|
|
1333 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1334 |
<span style="font-size: 9pt"><tt>}</tt></span></p>
|
|
|
1335 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1336 |
|
|
|
1337 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1338 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1339 |
<span style="font-size: 10pt">is syntactically a single command that runs two commands.
|
|
|
1340 |
Thus,
|
|
|
1341 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1342 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1343 |
<span style="font-size: 9pt"><tt>X/\.c/ ,g/variable/ {</tt></span></p>
|
|
|
1344 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1345 |
<span style="font-size: 9pt"><tt> f</tt></span></p>
|
|
|
1346 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1347 |
<span style="font-size: 9pt"><tt> , x/.*\n/ g/variable/ p</tt></span></p>
|
|
|
1348 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1349 |
<span style="font-size: 9pt"><tt>}</tt></span></p>
|
|
|
1350 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1351 |
|
|
|
1352 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1353 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1354 |
<span style="font-size: 10pt">finds all occurrences of
|
|
|
1355 |
</span><span style="font-size: 10pt"><tt>variable</tt></span><span style="font-size: 10pt">
|
|
|
1356 |
in C source files, and prints
|
|
|
1357 |
out the file names and lines of each match.
|
|
|
1358 |
The precise semantics of compound operations is discussed in the implementation
|
|
|
1359 |
sections below.
|
|
|
1360 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1361 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1362 |
<span style="font-size: 10pt">Finally,
|
|
|
1363 |
the undo command,
|
|
|
1364 |
</span><span style="font-size: 10pt"><tt>u</tt></span><span style="font-size: 10pt">,
|
|
|
1365 |
undoes the last command,
|
|
|
1366 |
no matter how many files were affected.
|
|
|
1367 |
Multiple undo operations move further back in time, so
|
|
|
1368 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1369 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1370 |
<span style="font-size: 9pt"><tt>u</tt></span></p>
|
|
|
1371 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1372 |
<span style="font-size: 9pt"><tt>u</tt></span></p>
|
|
|
1373 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1374 |
|
|
|
1375 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1376 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1377 |
<span style="font-size: 10pt">(which may be abbreviated
|
|
|
1378 |
</span><span style="font-size: 10pt"><tt>u2</tt></span><span style="font-size: 10pt">)
|
|
|
1379 |
undoes the last two commands. An undo may not be undone, however, nor
|
|
|
1380 |
may any command that adds or deletes files.
|
|
|
1381 |
Everything else is undoable, though, including for example
|
|
|
1382 |
</span><span style="font-size: 10pt"><tt>e</tt></span><span style="font-size: 10pt">
|
|
|
1383 |
commands:
|
|
|
1384 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1385 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1386 |
<span style="font-size: 9pt"><tt>e filename</tt></span></p>
|
|
|
1387 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1388 |
<span style="font-size: 9pt"><tt>u</tt></span></p>
|
|
|
1389 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1390 |
|
|
|
1391 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1392 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1393 |
<span style="font-size: 10pt">restores the state of the file completely, including its name, dot,
|
|
|
1394 |
and modified bit. Because of the undo, potentially dangerous commands
|
|
|
1395 |
are not guarded by confirmations. Only
|
|
|
1396 |
</span><span style="font-size: 10pt"><tt>D</tt></span><span style="font-size: 10pt">,
|
|
|
1397 |
which destroys the information necessary to restore itself, is protected.
|
|
|
1398 |
It will not delete a modified file, but a second
|
|
|
1399 |
</span><span style="font-size: 10pt"><tt>D</tt></span><span style="font-size: 10pt">
|
|
|
1400 |
of the same file will succeed regardless.
|
|
|
1401 |
The
|
|
|
1402 |
</span><span style="font-size: 10pt"><tt>q</tt></span><span style="font-size: 10pt">
|
|
|
1403 |
command, which exits
|
|
|
1404 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">,
|
|
|
1405 |
is similarly guarded.
|
|
|
1406 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1407 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1408 |
<span style="font-size: 10pt"><b>Mouse Interface
|
|
|
1409 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1410 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1411 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
1412 |
is most commonly run
|
|
|
1413 |
connected to a bitmap display and mouse for interactive editing.
|
|
|
1414 |
The only difference in the command language
|
|
|
1415 |
between regular, mouse-driven
|
|
|
1416 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1417 |
and
|
|
|
1418 |
</span><span style="font-size: 10pt"><tt>sam\fP-d
|
|
|
1419 |
is that if an address
|
|
|
1420 |
is provided without a command,
|
|
|
1421 |
</tt></span><span style="font-size: 10pt"><tt>sam\fP-d
|
|
|
1422 |
will print the text referenced by the address, but
|
|
|
1423 |
regular
|
|
|
1424 |
</tt></span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt"><tt>
|
|
|
1425 |
will highlight it on the screen — in fact,
|
|
|
1426 |
dot is always highlighted (see Figure 2).
|
|
|
1427 |
</tt></span><span style="font-size: 10pt"></span></p><center><img src="fig3.gif" /></center>
|
|
|
1428 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1429 |
<span style="font-size: 8pt"><i>Figure 2. A
|
|
|
1430 |
</i></span><span style="font-size: 8pt"><tt>sam</tt></span><span style="font-size: 8pt"><i>
|
|
|
1431 |
window. The scroll bar down the left
|
|
|
1432 |
represents the file, with the bubble showing the fraction
|
|
|
1433 |
visible in the window.
|
|
|
1434 |
The scroll bar may be manipulated by the mouse for convenient browsing.
|
|
|
1435 |
The current text,
|
|
|
1436 |
which is highlighted, need not fit on a line. Here it consists of one partial
|
|
|
1437 |
line, one complete line, and final partial line.
|
|
|
1438 |
</i></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1439 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
1440 |
|
|
|
1441 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1442 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1443 |
<span style="font-size: 10pt">Each file may have zero or more windows open on the display.
|
|
|
1444 |
At any time, only one window in all of
|
|
|
1445 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1446 |
is the
|
|
|
1447 |
</span><span style="font-size: 10pt"><i>current window,
|
|
|
1448 |
</i></span><span style="font-size: 10pt">that is, the window to which typing and mouse actions refer;
|
|
|
1449 |
this may be the
|
|
|
1450 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1451 |
window (that in which commands may be typed)
|
|
|
1452 |
or one of the file windows.
|
|
|
1453 |
When a file has multiple windows, the image of the file in each window
|
|
|
1454 |
is always kept up to date.
|
|
|
1455 |
The current file is the last file affected by a command,
|
|
|
1456 |
so if the
|
|
|
1457 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1458 |
window is current,
|
|
|
1459 |
the current window is not a window on the current file.
|
|
|
1460 |
However, each window on a file has its own value of dot,
|
|
|
1461 |
and when switching between windows on a single file,
|
|
|
1462 |
the file’s value of dot is changed to that of the window.
|
|
|
1463 |
Thus, flipping between windows behaves in the obvious, convenient way.
|
|
|
1464 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1465 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1466 |
<span style="font-size: 10pt">The mouse on the Blit has three buttons, numbered left to right.
|
|
|
1467 |
Button 3 has a list of commands to manipulate windows,
|
|
|
1468 |
followed by a list of ‘menu lines’ exactly as printed by the
|
|
|
1469 |
</span><span style="font-size: 10pt"><tt>f</tt></span><span style="font-size: 10pt">
|
|
|
1470 |
command, one per file (not one per window).
|
|
|
1471 |
These menu lines are sorted by file name.
|
|
|
1472 |
If the list is long, the Blit menu software will make it more manageable
|
|
|
1473 |
by generating a scrolling menu instead of an unwieldy long list.
|
|
|
1474 |
Using the menu to select a file from the list makes that file the current
|
|
|
1475 |
file, and the most recently current window in that file the current window.
|
|
|
1476 |
But if that file is already current, selecting it in the menu cycles through
|
|
|
1477 |
the windows on the file; this simple trick avoids a special menu to
|
|
|
1478 |
choose windows on a file.
|
|
|
1479 |
If there is no window open on the file,
|
|
|
1480 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1481 |
changes the mouse cursor to prompt the user to create one.
|
|
|
1482 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1483 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1484 |
<span style="font-size: 10pt">The commands on the button 3 menu are straightforward (see Figure 3), and
|
|
|
1485 |
are like the commands to manipulate windows in
|
|
|
1486 |
</span><span style="font-size: 10pt"><tt>mux</tt></span><span style="font-size: 10pt">,<sup></sup></span><sup><span style="font-size: 6pt">8</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
1487 |
the Blit’s window system.
|
|
|
1488 |
</span><span style="font-size: 10pt"><tt>New</tt></span><span style="font-size: 10pt">
|
|
|
1489 |
makes a new file, and gives it one empty window, whose size is determined
|
|
|
1490 |
by a rectangle swept by the mouse.
|
|
|
1491 |
</span><span style="font-size: 10pt"><tt>Zerox</tt></span><span style="font-size: 10pt">
|
|
|
1492 |
prompts for a window to be selected, and
|
|
|
1493 |
makes a clone of that window; this is how multiple windows are created on one file.
|
|
|
1494 |
</span><span style="font-size: 10pt"><tt>Reshape</tt></span><span style="font-size: 10pt">
|
|
|
1495 |
changes the size of the indicated window, and
|
|
|
1496 |
</span><span style="font-size: 10pt"><tt>close</tt></span><span style="font-size: 10pt">
|
|
|
1497 |
deletes it. If that is the last window open on the file,
|
|
|
1498 |
</span><span style="font-size: 10pt"><tt>close</tt></span><span style="font-size: 10pt">
|
|
|
1499 |
first does a
|
|
|
1500 |
</span><span style="font-size: 10pt"><tt>D</tt></span><span style="font-size: 10pt">
|
|
|
1501 |
command on the file.
|
|
|
1502 |
</span><span style="font-size: 10pt"><tt>Write</tt></span><span style="font-size: 10pt">
|
|
|
1503 |
is identical to a
|
|
|
1504 |
</span><span style="font-size: 10pt"><tt>w</tt></span><span style="font-size: 10pt">
|
|
|
1505 |
command on the file; it is in the menu purely for convenience.
|
|
|
1506 |
Finally,
|
|
|
1507 |
</span><span style="font-size: 10pt"><tt>~~sam~~</tt></span><span style="font-size: 10pt">
|
|
|
1508 |
is a menu item that appears between the commands and the file names.
|
|
|
1509 |
Selecting it makes the
|
|
|
1510 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1511 |
window the current window,
|
|
|
1512 |
causing subsequent typing to be interpreted as commands.
|
|
|
1513 |
</span><span style="font-size: 10pt"></span></p><center><img src="fig2.gif" /></center>
|
|
|
1514 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1515 |
<span style="font-size: 8pt"><i>Figure 3. The menu on button 3.
|
|
|
1516 |
The black rectangle on the left is a scroll bar; the menu is limited to
|
|
|
1517 |
the length shown to prevent its becoming unwieldy.
|
|
|
1518 |
Above the
|
|
|
1519 |
</i></span><span style="font-size: 8pt"><tt>~~sam~~</tt></span><span style="font-size: 8pt"><i>
|
|
|
1520 |
line is a list of commands;
|
|
|
1521 |
beneath it is a list of files, presented exactly as with the
|
|
|
1522 |
</i></span><span style="font-size: 8pt"><tt>f</tt></span><span style="font-size: 8pt"><i>
|
|
|
1523 |
command.
|
|
|
1524 |
</i></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1525 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
1526 |
|
|
|
1527 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1528 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1529 |
<span style="font-size: 10pt">When
|
|
|
1530 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1531 |
requests that a window be swept, in response to
|
|
|
1532 |
</span><span style="font-size: 10pt"><tt>new</tt></span><span style="font-size: 10pt">,
|
|
|
1533 |
</span><span style="font-size: 10pt"><tt>zerox</tt></span><span style="font-size: 10pt">
|
|
|
1534 |
or
|
|
|
1535 |
</span><span style="font-size: 10pt"><tt>reshape</tt></span><span style="font-size: 10pt">,
|
|
|
1536 |
it changes the mouse cursor from the usual arrow to a box with
|
|
|
1537 |
a small arrow.
|
|
|
1538 |
In this state, the mouse may be used to indicate an arbitrary rectangle by
|
|
|
1539 |
pressing button 3 at one corner and releasing it at the opposite corner.
|
|
|
1540 |
More conveniently,
|
|
|
1541 |
button 3 may simply be clicked,
|
|
|
1542 |
whereupon
|
|
|
1543 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1544 |
creates the maximal rectangle that contains the cursor
|
|
|
1545 |
and abuts the
|
|
|
1546 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1547 |
window.
|
|
|
1548 |
By placing the
|
|
|
1549 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1550 |
window in the middle of the screen, the user can define two regions (one above,
|
|
|
1551 |
one below) in which stacked fully-overlapping
|
|
|
1552 |
windows can be created with minimal fuss (see Figure 1).
|
|
|
1553 |
This simple user interface trick makes window creation noticeably easier.
|
|
|
1554 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1555 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1556 |
<span style="font-size: 10pt">The cut-and-paste editor is essentially the same as that in Smalltalk-80.<sup></sup></span><sup><span style="font-size: 6pt">11</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
1557 |
The text in dot is always highlighted on the screen.
|
|
|
1558 |
When a character is typed it replaces dot, and sets dot to the null
|
|
|
1559 |
string after the character. Thus, ordinary typing inserts text.
|
|
|
1560 |
Button 1 is used for selection:
|
|
|
1561 |
pressing the button, moving the mouse, and lifting the button
|
|
|
1562 |
selects (sets dot to) the text between the points where the
|
|
|
1563 |
button was pressed and released.
|
|
|
1564 |
Pressing and releasing at the same point selects a null string; this
|
|
|
1565 |
is called clicking. Clicking twice quickly, or
|
|
|
1566 |
</span><span style="font-size: 10pt"><i>double clicking,
|
|
|
1567 |
</i></span><span style="font-size: 10pt">selects larger objects;
|
|
|
1568 |
for example, double clicking in a word selects the word,
|
|
|
1569 |
double clicking just inside an opening bracket selects the text
|
|
|
1570 |
contained in the brackets (handling nested brackets correctly),
|
|
|
1571 |
and similarly for
|
|
|
1572 |
parentheses, quotes, and so on.
|
|
|
1573 |
The double-clicking rules reflect a bias toward
|
|
|
1574 |
programmers.
|
|
|
1575 |
If
|
|
|
1576 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1577 |
were intended more for word processing, double-clicks would probably
|
|
|
1578 |
select linguistic structures such as sentences.
|
|
|
1579 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1580 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1581 |
<span style="font-size: 10pt">If button 1 is pressed outside the current window, it makes the indicated
|
|
|
1582 |
window current.
|
|
|
1583 |
This is the easiest way to switch between windows and files.
|
|
|
1584 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1585 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1586 |
<span style="font-size: 10pt">Pressing button 2 brings up a menu of editing functions (see Figure 4).
|
|
|
1587 |
These mostly apply to the selected text:
|
|
|
1588 |
</span><span style="font-size: 10pt"><tt>cut</tt></span><span style="font-size: 10pt">
|
|
|
1589 |
deletes the selected text, and remembers it in a hidden buffer called the
|
|
|
1590 |
</span><span style="font-size: 10pt"><i>snarf buffer,
|
|
|
1591 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>paste</tt></span><span style="font-size: 10pt">
|
|
|
1592 |
replaces the selected text by the contents of the snarf buffer,
|
|
|
1593 |
</span><span style="font-size: 10pt"><tt>snarf</tt></span><span style="font-size: 10pt">
|
|
|
1594 |
just copies the selected text to the snarf buffer,
|
|
|
1595 |
</span><span style="font-size: 10pt"><tt>look</tt></span><span style="font-size: 10pt">
|
|
|
1596 |
searches forward for the next literal occurrence of the selected text, and
|
|
|
1597 |
</span><span style="font-size: 10pt"><tt><mux></tt></span><span style="font-size: 10pt">
|
|
|
1598 |
exchanges snarf buffers with the window system in which
|
|
|
1599 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1600 |
is running.
|
|
|
1601 |
Finally, the last regular expression used appears as a menu entry
|
|
|
1602 |
to search
|
|
|
1603 |
forward for the next occurrence of a match for the expression.
|
|
|
1604 |
</span><span style="font-size: 10pt"></span></p><center><img src="fig4.gif" /></center>
|
|
|
1605 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1606 |
<span style="font-size: 8pt"><i>Figure 4. The menu on button 2.
|
|
|
1607 |
The bottom entry tracks the most recently used regular expression, which may
|
|
|
1608 |
be literal text.
|
|
|
1609 |
</i></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1610 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
1611 |
|
|
|
1612 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1613 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1614 |
<span style="font-size: 10pt">The relationship between the command language and the mouse language is
|
|
|
1615 |
entirely due to the equality of dot and the selected text chosen
|
|
|
1616 |
with button 1 on the mouse.
|
|
|
1617 |
For example, to make a set of changes in a C subroutine, dot can be
|
|
|
1618 |
set by double clicking on the left brace that begins the subroutine,
|
|
|
1619 |
which sets dot for the command language.
|
|
|
1620 |
An address-free command then typed in the
|
|
|
1621 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1622 |
window will apply only to the text between the opening and closing
|
|
|
1623 |
braces of the function.
|
|
|
1624 |
The idea is to select what you want, and then say what you want
|
|
|
1625 |
to do with it, whether invoked by a menu selection or by a typed command.
|
|
|
1626 |
And of course, the value of dot is highlighted on
|
|
|
1627 |
the display after the command completes.
|
|
|
1628 |
This relationship between mouse interface and command language
|
|
|
1629 |
is clumsy to explain, but comfortable, even natural, in practice.
|
|
|
1630 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1631 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1632 |
<span style="font-size: 10pt"><b>The Implementation
|
|
|
1633 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1634 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1635 |
<span style="font-size: 10pt">The next few sections describe how
|
|
|
1636 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1637 |
is put together, first the host part,
|
|
|
1638 |
then the inter-component communication,
|
|
|
1639 |
then the terminal part.
|
|
|
1640 |
After explaining how the command language is implemented,
|
|
|
1641 |
the discussion follows (roughly) the path of a character
|
|
|
1642 |
from the temporary file on disc to the screen.
|
|
|
1643 |
The presentation centers on the data structures,
|
|
|
1644 |
because that is how the program was designed and because
|
|
|
1645 |
the algorithms are easy to provide, given the right data
|
|
|
1646 |
structures.
|
|
|
1647 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1648 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1649 |
<span style="font-size: 10pt"><b>Parsing and execution
|
|
|
1650 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1651 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1652 |
<span style="font-size: 10pt">The command language is interpreted by parsing each command with a
|
|
|
1653 |
table-driven recursive
|
|
|
1654 |
descent parser, and when a complete command is assembled, invoking a top-down
|
|
|
1655 |
executor.
|
|
|
1656 |
Most editors instead employ a simple character-at-a-time
|
|
|
1657 |
lexical scanner.
|
|
|
1658 |
Use of a parser makes it
|
|
|
1659 |
easy and unambiguous to detect when a command is complete,
|
|
|
1660 |
which has two advantages.
|
|
|
1661 |
First, escape conventions such as backslashes to quote
|
|
|
1662 |
multiple-line commands are unnecessary; if the command isn’t finished,
|
|
|
1663 |
the parser keeps reading. For example, a multiple-line append driven by an
|
|
|
1664 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
1665 |
command is straightforward:
|
|
|
1666 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1667 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1668 |
<span style="font-size: 9pt"><tt>x/.*\n/ g/Peter/ a</tt></span></p>
|
|
|
1669 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1670 |
<span style="font-size: 9pt"><tt>one line about Peter</tt></span></p>
|
|
|
1671 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1672 |
<span style="font-size: 9pt"><tt>another line about Peter</tt></span></p>
|
|
|
1673 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1674 |
<span style="font-size: 9pt"><tt>.</tt></span></p>
|
|
|
1675 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1676 |
|
|
|
1677 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1678 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1679 |
<span style="font-size: 10pt">Other UNIX editors would require a backslash after all but the last line.
|
|
|
1680 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1681 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1682 |
<span style="font-size: 10pt">The other advantage is specific to the two-process structure of
|
|
|
1683 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">.
|
|
|
1684 |
The host process must decide when a command is completed so the
|
|
|
1685 |
command interpreter can be called. This problem is easily resolved
|
|
|
1686 |
by having the lexical analyzer read the single stream of events from the
|
|
|
1687 |
terminal, directly executing all typing and mouse commands,
|
|
|
1688 |
but passing to the parser characters typed to the
|
|
|
1689 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1690 |
command window.
|
|
|
1691 |
This scheme is slightly complicated by the availability of cut-and-paste
|
|
|
1692 |
editing in the
|
|
|
1693 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1694 |
window, but that difficulty is resolved by applying the rules
|
|
|
1695 |
used in
|
|
|
1696 |
</span><span style="font-size: 10pt"><tt>mux</tt></span><span style="font-size: 10pt">:
|
|
|
1697 |
when a newline is typed to the
|
|
|
1698 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1699 |
window, all text between the newline and the previously typed newline
|
|
|
1700 |
is made available to the parser.
|
|
|
1701 |
This permits arbitrary editing to be done to a command before
|
|
|
1702 |
typing newline and thereby requesting execution.
|
|
|
1703 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1704 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1705 |
<span style="font-size: 10pt">The parser is driven by a table because the syntax of addresses
|
|
|
1706 |
and commands is regular enough
|
|
|
1707 |
to be encoded compactly. There are few special cases, such as the
|
|
|
1708 |
replacement text in a substitution, so the syntax of almost all commands
|
|
|
1709 |
can be encoded with a few flags.
|
|
|
1710 |
These include whether the command allows an address (for example,
|
|
|
1711 |
</span><span style="font-size: 10pt"><tt>e</tt></span><span style="font-size: 10pt">
|
|
|
1712 |
does not), whether it takes a regular expression (as in
|
|
|
1713 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
1714 |
and
|
|
|
1715 |
</span><span style="font-size: 10pt"><tt>s</tt></span><span style="font-size: 10pt">),
|
|
|
1716 |
whether it takes replacement text (as in
|
|
|
1717 |
</span><span style="font-size: 10pt"><tt>c</tt></span><span style="font-size: 10pt">
|
|
|
1718 |
or
|
|
|
1719 |
</span><span style="font-size: 10pt"><tt>i</tt></span><span style="font-size: 10pt">),
|
|
|
1720 |
which may be multi-line, and so on.
|
|
|
1721 |
The internal syntax of regular expressions is handled by a separate
|
|
|
1722 |
parser; a regular expression is a leaf of the command parse tree.
|
|
|
1723 |
Regular expressions are discussed fully in the next section.
|
|
|
1724 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1725 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1726 |
<span style="font-size: 10pt">The parser table also has information about defaults, so the interpreter
|
|
|
1727 |
is always called with a complete tree. For example, the parser fills in
|
|
|
1728 |
the implicit
|
|
|
1729 |
</span><span style="font-size: 10pt"><tt>0</tt></span><span style="font-size: 10pt">
|
|
|
1730 |
and
|
|
|
1731 |
</span><span style="font-size: 10pt"><tt>$</tt></span><span style="font-size: 10pt">
|
|
|
1732 |
in the abbreviated address
|
|
|
1733 |
</span><span style="font-size: 10pt"><tt>,</tt></span><span style="font-size: 10pt">
|
|
|
1734 |
(comma),
|
|
|
1735 |
inserts a
|
|
|
1736 |
</span><span style="font-size: 10pt"><tt>+</tt></span><span style="font-size: 10pt">
|
|
|
1737 |
to the left of an unadorned regular expression in an address,
|
|
|
1738 |
and provides the usual default address
|
|
|
1739 |
</span><span style="font-size: 10pt"><tt>.</tt></span><span style="font-size: 10pt">
|
|
|
1740 |
(dot) for commands that expect an address but are not given one.
|
|
|
1741 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1742 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1743 |
<span style="font-size: 10pt">Once a complete command is parsed, the evaluation is easy.
|
|
|
1744 |
The address is evaluated left-to-right starting from the value of dot,
|
|
|
1745 |
with a mostly ordinary expression evaluator.
|
|
|
1746 |
Addresses, like many of the data structures in
|
|
|
1747 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">,
|
|
|
1748 |
are held in a C structure and passed around by value:
|
|
|
1749 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1750 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1751 |
<span style="font-size: 9pt"><tt>typedef long Posn; /* Position in a file */</tt></span></p>
|
|
|
1752 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1753 |
<span style="font-size: 9pt"><tt>typedef struct Range{</tt></span></p>
|
|
|
1754 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1755 |
<span style="font-size: 9pt"><tt> Posn p1, p2;</tt></span></p>
|
|
|
1756 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1757 |
<span style="font-size: 9pt"><tt>}Range;</tt></span></p>
|
|
|
1758 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1759 |
<span style="font-size: 9pt"><tt>typedef struct Address{</tt></span></p>
|
|
|
1760 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1761 |
<span style="font-size: 9pt"><tt> Range r;</tt></span></p>
|
|
|
1762 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1763 |
<span style="font-size: 9pt"><tt> File *f;</tt></span></p>
|
|
|
1764 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1765 |
<span style="font-size: 9pt"><tt>}Address;</tt></span></p>
|
|
|
1766 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1767 |
|
|
|
1768 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1769 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1770 |
<span style="font-size: 10pt">An address is encoded as a substring (character positions
|
|
|
1771 |
</span><span style="font-size: 10pt"><tt>p1</tt></span><span style="font-size: 10pt">
|
|
|
1772 |
to
|
|
|
1773 |
</span><span style="font-size: 10pt"><tt>p2</tt></span><span style="font-size: 10pt">)
|
|
|
1774 |
in a file
|
|
|
1775 |
</span><span style="font-size: 10pt"><tt>f</tt></span><span style="font-size: 10pt">.
|
|
|
1776 |
(The data type
|
|
|
1777 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
1778 |
is described in detail below.)
|
|
|
1779 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1780 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1781 |
<span style="font-size: 10pt">The address interpreter is an
|
|
|
1782 |
</span><span style="font-size: 10pt"><tt>Address</tt></span><span style="font-size: 10pt">-valued
|
|
|
1783 |
function that traverses the parse tree describing an address (the
|
|
|
1784 |
parse tree for the address has type
|
|
|
1785 |
</span><span style="font-size: 10pt"><tt>Addrtree</tt></span><span style="font-size: 10pt">):
|
|
|
1786 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1787 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1788 |
<span style="font-size: 9pt"><tt>Address</tt></span></p>
|
|
|
1789 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1790 |
<span style="font-size: 9pt"><tt>address(ap, a, sign)</tt></span></p>
|
|
|
1791 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1792 |
<span style="font-size: 9pt"><tt> Addrtree *ap;</tt></span></p>
|
|
|
1793 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1794 |
<span style="font-size: 9pt"><tt> Address a;</tt></span></p>
|
|
|
1795 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1796 |
<span style="font-size: 9pt"><tt> int sign;</tt></span></p>
|
|
|
1797 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1798 |
<span style="font-size: 9pt"><tt>{</tt></span></p>
|
|
|
1799 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1800 |
<span style="font-size: 9pt"><tt> Address a2;</tt></span></p>
|
|
|
1801 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1802 |
<span style="font-size: 9pt"><tt> do</tt></span></p>
|
|
|
1803 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1804 |
<span style="font-size: 9pt"><tt> switch(ap->type){</tt></span></p>
|
|
|
1805 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1806 |
<span style="font-size: 9pt"><tt> case ’.’:</tt></span></p>
|
|
|
1807 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1808 |
<span style="font-size: 9pt"><tt> a=a.f->dot;</tt></span></p>
|
|
|
1809 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1810 |
<span style="font-size: 9pt"><tt> break;</tt></span></p>
|
|
|
1811 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1812 |
<span style="font-size: 9pt"><tt> case ’$’:</tt></span></p>
|
|
|
1813 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1814 |
<span style="font-size: 9pt"><tt> a.r.p1=a.r.p2=a.f->nbytes;</tt></span></p>
|
|
|
1815 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1816 |
<span style="font-size: 9pt"><tt> break;</tt></span></p>
|
|
|
1817 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1818 |
<span style="font-size: 9pt"><tt> case ’"’: </tt></span></p>
|
|
|
1819 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1820 |
<span style="font-size: 9pt"><tt> a=matchfile(a, ap->aregexp)->dot; </tt></span></p>
|
|
|
1821 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1822 |
<span style="font-size: 9pt"><tt> break;</tt></span></p>
|
|
|
1823 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1824 |
<span style="font-size: 9pt"><tt> case ’,’:</tt></span></p>
|
|
|
1825 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1826 |
<span style="font-size: 9pt"><tt> a2=address(ap->right, a, 0);</tt></span></p>
|
|
|
1827 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1828 |
<span style="font-size: 9pt"><tt> a=address(ap->left, a, 0);</tt></span></p>
|
|
|
1829 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1830 |
<span style="font-size: 9pt"><tt> if(a.f!=a2.f || a2.r.p2<a.r.p1)</tt></span></p>
|
|
|
1831 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1832 |
<span style="font-size: 9pt"><tt> error(Eorder);</tt></span></p>
|
|
|
1833 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1834 |
<span style="font-size: 9pt"><tt> a.r.p2=a2.r.p2;</tt></span></p>
|
|
|
1835 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1836 |
<span style="font-size: 9pt"><tt> return a;</tt></span></p>
|
|
|
1837 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1838 |
<span style="font-size: 9pt"><tt> /* and so on */</tt></span></p>
|
|
|
1839 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1840 |
<span style="font-size: 9pt"><tt> }</tt></span></p>
|
|
|
1841 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1842 |
<span style="font-size: 9pt"><tt> while((ap=ap->right)!=0);</tt></span></p>
|
|
|
1843 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1844 |
<span style="font-size: 9pt"><tt> return a;</tt></span></p>
|
|
|
1845 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1846 |
<span style="font-size: 9pt"><tt>}</tt></span></p>
|
|
|
1847 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1848 |
|
|
|
1849 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1850 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1851 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1852 |
<span style="font-size: 10pt">Throughout, errors are handled by a non-local
|
|
|
1853 |
</span><span style="font-size: 10pt"><tt>goto</tt></span><span style="font-size: 10pt">
|
|
|
1854 |
(a
|
|
|
1855 |
</span><span style="font-size: 10pt"><tt>setjmp/longjmp</tt></span><span style="font-size: 10pt">
|
|
|
1856 |
in C terminology)
|
|
|
1857 |
hidden in a routine called
|
|
|
1858 |
</span><span style="font-size: 10pt"><tt>error</tt></span><span style="font-size: 10pt">
|
|
|
1859 |
that immediately aborts the execution, retracts any
|
|
|
1860 |
partially made changes (see the section below on ‘undoing’), and
|
|
|
1861 |
returns to the top level of the parser.
|
|
|
1862 |
The argument to
|
|
|
1863 |
</span><span style="font-size: 10pt"><tt>error</tt></span><span style="font-size: 10pt">
|
|
|
1864 |
is an enumeration type that
|
|
|
1865 |
is translated to a terse but possibly helpful
|
|
|
1866 |
message such as ‘?addresses out of order.’
|
|
|
1867 |
Very common messages are kept short; for example the message for
|
|
|
1868 |
a failed regular expression search is ‘?search.’
|
|
|
1869 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1870 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1871 |
<span style="font-size: 10pt">Character addresses such as
|
|
|
1872 |
</span><span style="font-size: 10pt"><tt>#3</tt></span><span style="font-size: 10pt">
|
|
|
1873 |
are trivial to implement, as the
|
|
|
1874 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
1875 |
data structure is accessible by character number.
|
|
|
1876 |
However,
|
|
|
1877 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1878 |
keeps no information about the position of newlines — it is too
|
|
|
1879 |
expensive to track dynamically — so line addresses are computed by reading
|
|
|
1880 |
the file, counting newlines. Except in very large files, this has proven
|
|
|
1881 |
acceptable: file access is fast enough to make the technique practical,
|
|
|
1882 |
and lines are not central to the structure of the command language.
|
|
|
1883 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1884 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1885 |
<span style="font-size: 10pt">The command interpreter, called
|
|
|
1886 |
</span><span style="font-size: 10pt"><tt>cmdexec</tt></span><span style="font-size: 10pt">,
|
|
|
1887 |
is also straightforward. The parse table includes a
|
|
|
1888 |
function to call to interpret a particular command. That function
|
|
|
1889 |
receives as arguments
|
|
|
1890 |
the calculated address
|
|
|
1891 |
for the command
|
|
|
1892 |
and the command tree (of type
|
|
|
1893 |
</span><span style="font-size: 10pt"><tt>Cmdtree</tt></span><span style="font-size: 10pt">),
|
|
|
1894 |
which may contain information such as the subtree for compound commands.
|
|
|
1895 |
Here, for example, is the function for the
|
|
|
1896 |
</span><span style="font-size: 10pt"><tt>g</tt></span><span style="font-size: 10pt">
|
|
|
1897 |
and
|
|
|
1898 |
</span><span style="font-size: 10pt"><tt>v</tt></span><span style="font-size: 10pt">
|
|
|
1899 |
commands:
|
|
|
1900 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1901 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1902 |
<span style="font-size: 9pt"><tt>int</tt></span></p>
|
|
|
1903 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1904 |
<span style="font-size: 9pt"><tt>g_cmd(a, cp)</tt></span></p>
|
|
|
1905 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1906 |
<span style="font-size: 9pt"><tt> Address a;</tt></span></p>
|
|
|
1907 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1908 |
<span style="font-size: 9pt"><tt> Cmdtree *cp;</tt></span></p>
|
|
|
1909 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1910 |
<span style="font-size: 9pt"><tt>{</tt></span></p>
|
|
|
1911 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1912 |
<span style="font-size: 9pt"><tt> compile(cp->regexp);</tt></span></p>
|
|
|
1913 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1914 |
<span style="font-size: 9pt"><tt> if(execute(a.f, a.r.p1, a.r.p2)!=(cp->cmdchar==’v’)){</tt></span></p>
|
|
|
1915 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1916 |
<span style="font-size: 9pt"><tt> a.f->dot=a;</tt></span></p>
|
|
|
1917 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1918 |
<span style="font-size: 9pt"><tt> return cmdexec(a, cp->subcmd);</tt></span></p>
|
|
|
1919 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1920 |
<span style="font-size: 9pt"><tt> }</tt></span></p>
|
|
|
1921 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1922 |
<span style="font-size: 9pt"><tt> return TRUE; /* cause execution to continue */</tt></span></p>
|
|
|
1923 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1924 |
<span style="font-size: 9pt"><tt>}</tt></span></p>
|
|
|
1925 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1926 |
|
|
|
1927 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1928 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1929 |
<span style="font-size: 10pt">(</span><span style="font-size: 10pt"><tt>Compile</tt></span><span style="font-size: 10pt">
|
|
|
1930 |
and
|
|
|
1931 |
</span><span style="font-size: 10pt"><tt>execute</tt></span><span style="font-size: 10pt">
|
|
|
1932 |
are part of the regular expression code, described in the next section.)
|
|
|
1933 |
Because the parser and the
|
|
|
1934 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
1935 |
data structure do most of the work, most commands
|
|
|
1936 |
are similarly brief.
|
|
|
1937 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
1938 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1939 |
<span style="font-size: 10pt"><b>Regular expressions
|
|
|
1940 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1941 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1942 |
<span style="font-size: 10pt">The regular expression code in
|
|
|
1943 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1944 |
is an interpreted, rather than compiled on-the-fly, implementation of Thompson’s
|
|
|
1945 |
non-deterministic finite automaton algorithm.<sup></sup></span><sup><span style="font-size: 6pt">12</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
1946 |
The syntax and semantics of the expressions are as in the UNIX program
|
|
|
1947 |
</span><span style="font-size: 10pt"><tt>egrep</tt></span><span style="font-size: 10pt">,
|
|
|
1948 |
including alternation, closures, character classes, and so on.
|
|
|
1949 |
The only changes in the notation are two additions:
|
|
|
1950 |
</span><span style="font-size: 10pt"><tt>\n</tt></span><span style="font-size: 10pt">
|
|
|
1951 |
is translated to, and matches, a newline character, and
|
|
|
1952 |
</span><span style="font-size: 10pt"><tt>@</tt></span><span style="font-size: 10pt">
|
|
|
1953 |
matches any character. In
|
|
|
1954 |
</span><span style="font-size: 10pt"><tt>egrep</tt></span><span style="font-size: 10pt">,
|
|
|
1955 |
the character
|
|
|
1956 |
</span><span style="font-size: 10pt"><tt>.</tt></span><span style="font-size: 10pt">
|
|
|
1957 |
matches any character except newline, and in
|
|
|
1958 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
1959 |
the same rule seemed safest, to prevent idioms like
|
|
|
1960 |
</span><span style="font-size: 10pt"><tt>.*</tt></span><span style="font-size: 10pt">
|
|
|
1961 |
from spanning newlines.
|
|
|
1962 |
</span><span style="font-size: 10pt"><tt>Egrep</tt></span><span style="font-size: 10pt">
|
|
|
1963 |
expressions are arguably too complicated for an interactive editor —
|
|
|
1964 |
certainly it would make sense if all the special characters were two-character
|
|
|
1965 |
sequences, so that most of the punctuation characters wouldn’t have
|
|
|
1966 |
peculiar meanings — but for an interesting command language, full
|
|
|
1967 |
regular expressions are necessary, and
|
|
|
1968 |
</span><span style="font-size: 10pt"><tt>egrep</tt></span><span style="font-size: 10pt">
|
|
|
1969 |
defines the full regular expression syntax for UNIX programs.
|
|
|
1970 |
Also, it seemed superfluous to define a new syntax, since various UNIX programs
|
|
|
1971 |
(</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">,
|
|
|
1972 |
</span><span style="font-size: 10pt"><tt>egrep</tt></span><span style="font-size: 10pt">
|
|
|
1973 |
and
|
|
|
1974 |
</span><span style="font-size: 10pt"><tt>vi</tt></span><span style="font-size: 10pt">)
|
|
|
1975 |
define too many already.
|
|
|
1976 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1977 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1978 |
<span style="font-size: 10pt">The expressions are compiled by a routine,
|
|
|
1979 |
</span><span style="font-size: 10pt"><tt>compile</tt></span><span style="font-size: 10pt">,
|
|
|
1980 |
that generates the description of the non-deterministic finite state machine.
|
|
|
1981 |
A second routine,
|
|
|
1982 |
</span><span style="font-size: 10pt"><tt>execute</tt></span><span style="font-size: 10pt">,
|
|
|
1983 |
interprets the machine to generate the leftmost-longest match of the
|
|
|
1984 |
expression in a substring of the file.
|
|
|
1985 |
The algorithm is described elsewhere.<sup></sup></span><sup><span style="font-size: 6pt">12,13</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
1986 |
</span><span style="font-size: 10pt"><tt>Execute</tt></span><span style="font-size: 10pt">
|
|
|
1987 |
reports
|
|
|
1988 |
whether a match was found, and sets a global variable,
|
|
|
1989 |
of type
|
|
|
1990 |
</span><span style="font-size: 10pt"><tt>Range</tt></span><span style="font-size: 10pt">,
|
|
|
1991 |
to the substring matched.
|
|
|
1992 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
1993 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1994 |
<span style="font-size: 10pt">A trick is required to evaluate the expression in reverse, such as when
|
|
|
1995 |
searching backwards for an expression.
|
|
|
1996 |
For example,
|
|
|
1997 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
1998 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
1999 |
<span style="font-size: 9pt"><tt>-/P.*r/</tt></span></p>
|
|
|
2000 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2001 |
|
|
|
2002 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
2003 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2004 |
<span style="font-size: 10pt">looks backwards through the file for a match of the expression.
|
|
|
2005 |
The expression, however, is defined for a forward search.
|
|
|
2006 |
The solution is to construct a machine identical to the machine
|
|
|
2007 |
for a forward search except for a reversal of all the concatenation
|
|
|
2008 |
operators (the other operators are symmetric under direction reversal),
|
|
|
2009 |
to exchange the meaning of the operators
|
|
|
2010 |
</span><span style="font-size: 10pt"><tt>^</tt></span><span style="font-size: 10pt">
|
|
|
2011 |
and
|
|
|
2012 |
</span><span style="font-size: 10pt"><tt>$</tt></span><span style="font-size: 10pt">,
|
|
|
2013 |
and then to read the file backwards, looking for the
|
|
|
2014 |
usual earliest longest match.
|
|
|
2015 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2016 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2017 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Execute</tt></span><span style="font-size: 10pt">
|
|
|
2018 |
generates only one match each time it is called.
|
|
|
2019 |
To interpret looping constructs such as the
|
|
|
2020 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
2021 |
command,
|
|
|
2022 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2023 |
must therefore synchronize between
|
|
|
2024 |
calls of
|
|
|
2025 |
</span><span style="font-size: 10pt"><tt>execute</tt></span><span style="font-size: 10pt">
|
|
|
2026 |
to avoid
|
|
|
2027 |
problems with null matches.
|
|
|
2028 |
For example, even given the leftmost-longest rule,
|
|
|
2029 |
the expression
|
|
|
2030 |
</span><span style="font-size: 10pt"><tt>a*</tt></span><span style="font-size: 10pt">
|
|
|
2031 |
matches three times in the string
|
|
|
2032 |
</span><span style="font-size: 10pt"><tt>ab</tt></span><span style="font-size: 10pt">
|
|
|
2033 |
(the character
|
|
|
2034 |
</span><span style="font-size: 10pt"><tt>a</tt></span><span style="font-size: 10pt">,
|
|
|
2035 |
the null string between the
|
|
|
2036 |
</span><span style="font-size: 10pt"><tt>a</tt></span><span style="font-size: 10pt">
|
|
|
2037 |
and
|
|
|
2038 |
</span><span style="font-size: 10pt"><tt>b</tt></span><span style="font-size: 10pt">,
|
|
|
2039 |
and the final null string).
|
|
|
2040 |
After returning a match for the
|
|
|
2041 |
</span><span style="font-size: 10pt"><tt>a</tt></span><span style="font-size: 10pt">,
|
|
|
2042 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2043 |
must not match the null string before the
|
|
|
2044 |
</span><span style="font-size: 10pt"><tt>b</tt></span><span style="font-size: 10pt">.
|
|
|
2045 |
The algorithm starts
|
|
|
2046 |
</span><span style="font-size: 10pt"><tt>execute</tt></span><span style="font-size: 10pt">
|
|
|
2047 |
at the end of its previous match, and
|
|
|
2048 |
if the match it returns
|
|
|
2049 |
is null and abuts the previous match, rejects the match and advances
|
|
|
2050 |
the initial position one character.
|
|
|
2051 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2052 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2053 |
<span style="font-size: 10pt"><b>Memory allocation
|
|
|
2054 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2055 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2056 |
<span style="font-size: 10pt">The C language has no memory allocation primitives, although a standard
|
|
|
2057 |
library routine,
|
|
|
2058 |
</span><span style="font-size: 10pt"><tt>malloc</tt></span><span style="font-size: 10pt">,
|
|
|
2059 |
provides adequate service for simple programs.
|
|
|
2060 |
For specific uses, however,
|
|
|
2061 |
it can be better to write a custom allocator.
|
|
|
2062 |
The allocator (or rather, pair of allocators) described here
|
|
|
2063 |
work in both the terminal and host parts of
|
|
|
2064 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">.
|
|
|
2065 |
They are designed for efficient manipulation of strings,
|
|
|
2066 |
which are allocated and freed frequently and vary in length from essentially
|
|
|
2067 |
zero to 32 Kbytes (very large strings are written to disc).
|
|
|
2068 |
More important, strings may be large and change size often,
|
|
|
2069 |
so to minimize memory usage it is helpful to reclaim and to coalesce the
|
|
|
2070 |
unused portions of strings when they are truncated.
|
|
|
2071 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2072 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2073 |
<span style="font-size: 10pt">Objects to be allocated in
|
|
|
2074 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2075 |
are of two flavors:
|
|
|
2076 |
the first is C
|
|
|
2077 |
</span><span style="font-size: 10pt"><tt>structs</tt></span><span style="font-size: 10pt">,
|
|
|
2078 |
which are small and often addressed by pointer variables;
|
|
|
2079 |
the second is variable-sized arrays of characters
|
|
|
2080 |
or integers whose
|
|
|
2081 |
base pointer is always used to access them.
|
|
|
2082 |
The memory allocator in
|
|
|
2083 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2084 |
is therefore in two parts:
|
|
|
2085 |
first, a traditional first-fit allocator that provides fixed storage for
|
|
|
2086 |
</span><span style="font-size: 10pt"><tt>structs</tt></span><span style="font-size: 10pt">;
|
|
|
2087 |
and second, a garbage-compacting allocator that reduces storage
|
|
|
2088 |
overhead for variable-sized objects, at the cost of some bookkeeping.
|
|
|
2089 |
The two types of objects are allocated from adjoining arenas, with
|
|
|
2090 |
the garbage-compacting allocator controlling the arena with higher addresses.
|
|
|
2091 |
Separating into two arenas simplifies compaction and prevents fragmentation due
|
|
|
2092 |
to immovable objects.
|
|
|
2093 |
The access rules for garbage-compactable objects
|
|
|
2094 |
(discussed in the next paragraph) allow them to be relocated, so when
|
|
|
2095 |
the first-fit arena needs space, it moves the garbage-compacted arena
|
|
|
2096 |
to higher addresses to make room. Storage is therefore created only
|
|
|
2097 |
at successively higher addresses, either when more garbage-compacted
|
|
|
2098 |
space is needed or when the first-fit arena pushes up the other arena.
|
|
|
2099 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2100 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2101 |
<span style="font-size: 10pt">Objects that may be compacted declare to the
|
|
|
2102 |
allocator a cell that is guaranteed to be the sole repository of the
|
|
|
2103 |
address of the object whenever a compaction can occur.
|
|
|
2104 |
The compactor can then update the address when the object is moved.
|
|
|
2105 |
For example, the implementation of type
|
|
|
2106 |
</span><span style="font-size: 10pt"><tt>List</tt></span><span style="font-size: 10pt">
|
|
|
2107 |
(really a variable-length array)
|
|
|
2108 |
is:
|
|
|
2109 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
2110 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2111 |
<span style="font-size: 9pt"><tt>typedef struct List{</tt></span></p>
|
|
|
2112 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2113 |
<span style="font-size: 9pt"><tt> int nused;</tt></span></p>
|
|
|
2114 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2115 |
<span style="font-size: 9pt"><tt> long *ptr;</tt></span></p>
|
|
|
2116 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2117 |
<span style="font-size: 9pt"><tt>}List;</tt></span></p>
|
|
|
2118 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2119 |
|
|
|
2120 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
2121 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2122 |
<span style="font-size: 10pt">The
|
|
|
2123 |
</span><span style="font-size: 10pt"><tt>ptr</tt></span><span style="font-size: 10pt">
|
|
|
2124 |
cell must always be used directly, and never copied. When a
|
|
|
2125 |
</span><span style="font-size: 10pt"><tt>List</tt></span><span style="font-size: 10pt">
|
|
|
2126 |
is to be created the
|
|
|
2127 |
</span><span style="font-size: 10pt"><tt>List</tt></span><span style="font-size: 10pt">
|
|
|
2128 |
structure is allocated in the ordinary first-fit arena
|
|
|
2129 |
and its
|
|
|
2130 |
</span><span style="font-size: 10pt"><tt>ptr</tt></span><span style="font-size: 10pt">
|
|
|
2131 |
is allocated in the garbage-compacted arena.
|
|
|
2132 |
A similar data type for strings, called
|
|
|
2133 |
</span><span style="font-size: 10pt"><tt>String</tt></span><span style="font-size: 10pt">,
|
|
|
2134 |
stores variable-length character arrays of up to 32767 elements.
|
|
|
2135 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2136 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2137 |
<span style="font-size: 10pt">A related matter of programming style:
|
|
|
2138 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2139 |
frequently passes structures by value, which
|
|
|
2140 |
simplifies the code.
|
|
|
2141 |
Traditionally, C programs have
|
|
|
2142 |
passed structures by reference, but implicit allocation on
|
|
|
2143 |
the stack is easier to use.
|
|
|
2144 |
Structure passing is a relatively new feature of C
|
|
|
2145 |
(it is not in the
|
|
|
2146 |
standard reference manual for C<sup></sup></span><sup><span style="font-size: 6pt">14</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">), and is poorly supported in most
|
|
|
2147 |
commercial C compilers.
|
|
|
2148 |
It’s convenient and expressive, though,
|
|
|
2149 |
and simplifies memory management by
|
|
|
2150 |
avoiding the allocator altogether
|
|
|
2151 |
and eliminating pointer aliases.
|
|
|
2152 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2153 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2154 |
<span style="font-size: 10pt"><b>Data structures for manipulating files
|
|
|
2155 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2156 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2157 |
<span style="font-size: 10pt">Experience with
|
|
|
2158 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
2159 |
showed that the requirements
|
|
|
2160 |
of the file data structure were few, but strict.
|
|
|
2161 |
First, files need to be read and written quickly;
|
|
|
2162 |
adding a fresh file must be painless.
|
|
|
2163 |
Second, the implementation must place no arbitrary upper limit on
|
|
|
2164 |
the number or sizes of files. (It should be practical to edit many files,
|
|
|
2165 |
and files up to megabytes in length should be handled gracefully.)
|
|
|
2166 |
This implies that files be stored on disc, not in main memory.
|
|
|
2167 |
(Aficionados of virtual memory may argue otherwise, but the
|
|
|
2168 |
implementation of virtual
|
|
|
2169 |
memory in our system is not something to depend on
|
|
|
2170 |
for good performance.)
|
|
|
2171 |
Third, changes to files need be made by only two primitives:
|
|
|
2172 |
deletion and insertion.
|
|
|
2173 |
These are inverses of each other,
|
|
|
2174 |
which simplifies the implementation of the undo operation.
|
|
|
2175 |
Finally,
|
|
|
2176 |
it must be easy and efficient to access the file, either
|
|
|
2177 |
forwards or backwards, a byte at a time.
|
|
|
2178 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2179 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2180 |
<span style="font-size: 10pt">The
|
|
|
2181 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
2182 |
data type is constructed from three simpler data structures that hold arrays
|
|
|
2183 |
of characters.
|
|
|
2184 |
Each of these types has an insertion and deletion operator, and the
|
|
|
2185 |
insertion and deletion operators of the
|
|
|
2186 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
2187 |
type itself are constructed from them.
|
|
|
2188 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2189 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2190 |
<span style="font-size: 10pt">The simplest type is the
|
|
|
2191 |
</span><span style="font-size: 10pt"><tt>String</tt></span><span style="font-size: 10pt">,
|
|
|
2192 |
which is used to hold strings in main memory.
|
|
|
2193 |
The code that manages
|
|
|
2194 |
</span><span style="font-size: 10pt"><tt>Strings</tt></span><span style="font-size: 10pt">
|
|
|
2195 |
guarantees that they will never be longer
|
|
|
2196 |
than some moderate size, and in practice they are rarely larger than 8 Kbytes.
|
|
|
2197 |
</span><span style="font-size: 10pt"><tt>Strings</tt></span><span style="font-size: 10pt">
|
|
|
2198 |
have two purposes: they hold short strings like file names with little overhead,
|
|
|
2199 |
and because they are deliberately small, they are efficient to modify.
|
|
|
2200 |
They are therefore used as the data structure for in-memory caches.
|
|
|
2201 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2202 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2203 |
<span style="font-size: 10pt">The disc copy of the file is managed by a data structure called a
|
|
|
2204 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">,
|
|
|
2205 |
which corresponds to a temporary file. A
|
|
|
2206 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">
|
|
|
2207 |
has no storage in main memory other than bookkeeping information;
|
|
|
2208 |
the actual data being held is all on the disc.
|
|
|
2209 |
To reduce the number of open files needed,
|
|
|
2210 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2211 |
opens a dozen temporary UNIX files and multiplexes the
|
|
|
2212 |
</span><span style="font-size: 10pt"><tt>Discs</tt></span><span style="font-size: 10pt">
|
|
|
2213 |
upon them.
|
|
|
2214 |
This permits many files to
|
|
|
2215 |
be edited; the entire
|
|
|
2216 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2217 |
source (48 files) may be edited comfortably with a single
|
|
|
2218 |
instance of
|
|
|
2219 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">.
|
|
|
2220 |
Allocating one temporary file per
|
|
|
2221 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">
|
|
|
2222 |
would strain the operating system’s limit on the number of open files.
|
|
|
2223 |
Also, spreading the traffic among temporary files keeps the files shorter,
|
|
|
2224 |
and shorter files are more efficiently implemented by the UNIX
|
|
|
2225 |
I/O subsystem.
|
|
|
2226 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2227 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2228 |
<span style="font-size: 10pt">A
|
|
|
2229 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">
|
|
|
2230 |
is an array of fixed-length blocks, each of which contains
|
|
|
2231 |
between 1 and 4096 characters of active data.
|
|
|
2232 |
(The block size of our UNIX file system is 4096 bytes.)
|
|
|
2233 |
The block addresses within the temporary file and the length of each
|
|
|
2234 |
block are stored in a
|
|
|
2235 |
</span><span style="font-size: 10pt"><tt>List</tt></span><span style="font-size: 10pt">.
|
|
|
2236 |
When changes are made the live part of blocks may change size.
|
|
|
2237 |
Blocks are created and coalesced when necessary to try to keep the sizes
|
|
|
2238 |
between 2048 and 4096 bytes.
|
|
|
2239 |
An actively changing part of the
|
|
|
2240 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">
|
|
|
2241 |
therefore typically has about a kilobyte of slop that can be
|
|
|
2242 |
inserted or deleted
|
|
|
2243 |
without changing more than one block or affecting the block order.
|
|
|
2244 |
When an insertion would overflow a block, the block is split, a new one
|
|
|
2245 |
is allocated to receive the overflow, and the memory-resident list of blocks
|
|
|
2246 |
is rearranged to reflect the insertion of the new block.
|
|
|
2247 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2248 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2249 |
<span style="font-size: 10pt">Obviously, going to the disc for every modification to the file is
|
|
|
2250 |
prohibitively expensive.
|
|
|
2251 |
The data type
|
|
|
2252 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">
|
|
|
2253 |
consists of a
|
|
|
2254 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">
|
|
|
2255 |
to hold the data and a
|
|
|
2256 |
</span><span style="font-size: 10pt"><tt>String</tt></span><span style="font-size: 10pt">
|
|
|
2257 |
that acts as a cache.
|
|
|
2258 |
This is the first of a series of caches throughout the data structures in
|
|
|
2259 |
</span><span style="font-size: 10pt"><tt>sam.</tt></span><span style="font-size: 10pt">
|
|
|
2260 |
The caches not only improve performance, they provide a way to organize
|
|
|
2261 |
the flow of data, particularly in the communication between the host
|
|
|
2262 |
and terminal.
|
|
|
2263 |
This idea is developed below, in the section on communications.
|
|
|
2264 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2265 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2266 |
<span style="font-size: 10pt">To reduce disc traffic, changes to a
|
|
|
2267 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">
|
|
|
2268 |
are mediated by a variable-length string, in memory, that acts as a cache.
|
|
|
2269 |
When an insertion or deletion is made to a
|
|
|
2270 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">,
|
|
|
2271 |
if the change can be accommodated by the cache, it is done there.
|
|
|
2272 |
If the cache becomes bigger than a block because of an insertion,
|
|
|
2273 |
some of it is written to the
|
|
|
2274 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">
|
|
|
2275 |
and deleted from the cache.
|
|
|
2276 |
If the change does not intersect the cache, the cache is flushed.
|
|
|
2277 |
The cache is only loaded at the new position if the change is smaller than a block;
|
|
|
2278 |
otherwise, it is sent directly to the
|
|
|
2279 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">.
|
|
|
2280 |
This is because
|
|
|
2281 |
large changes are typically sequential,
|
|
|
2282 |
whereupon the next change is unlikely to overlap the current one.
|
|
|
2283 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2284 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2285 |
<span style="font-size: 10pt">A
|
|
|
2286 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
2287 |
comprises a
|
|
|
2288 |
</span><span style="font-size: 10pt"><tt>String</tt></span><span style="font-size: 10pt">
|
|
|
2289 |
to hold the file name and some ancillary data such as dot and the modified bit.
|
|
|
2290 |
The most important components, though, are a pair of
|
|
|
2291 |
</span><span style="font-size: 10pt"><tt>Buffers</tt></span><span style="font-size: 10pt">,
|
|
|
2292 |
one called the transcript and the other the contents.
|
|
|
2293 |
Their use is described in the next section.
|
|
|
2294 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2295 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2296 |
<span style="font-size: 10pt">The overall structure is shown in Figure 5.
|
|
|
2297 |
Although it may seem that the data is touched many times on its
|
|
|
2298 |
way from the
|
|
|
2299 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">,
|
|
|
2300 |
it is read (by one UNIX system call) directly into the cache of the
|
|
|
2301 |
associated
|
|
|
2302 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">;
|
|
|
2303 |
no extra copy is done.
|
|
|
2304 |
Similarly, when flushing the cache, the text is written
|
|
|
2305 |
directly from the cache to disc.
|
|
|
2306 |
Most operations act directly on the text in the cache.
|
|
|
2307 |
A principle applied throughout
|
|
|
2308 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2309 |
is that the fewer times the data is copied, the faster the program will run
|
|
|
2310 |
(see also the paper by Waite<sup></sup></span><sup><span style="font-size: 6pt">15</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">).
|
|
|
2311 |
</span><span style="font-size: 10pt"></span></p><center><img src="sam2.png"></center>
|
|
|
2312 |
</center>
|
|
|
2313 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2314 |
<span style="font-size: 8pt"><i>Figure 5. File data structures.
|
|
|
2315 |
The temporary files are stored in the standard repository for such files
|
|
|
2316 |
on the host system.
|
|
|
2317 |
</i></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2318 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
2319 |
|
|
|
2320 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2321 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2322 |
<span style="font-size: 10pt">The contents of a
|
|
|
2323 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
2324 |
are accessed by a routine that
|
|
|
2325 |
copies to a buffer a substring of a file starting at a specified offset.
|
|
|
2326 |
To read a byte at a time, a
|
|
|
2327 |
per-</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
2328 |
array is loaded starting from a specified initial position,
|
|
|
2329 |
and bytes may then be read from the array.
|
|
|
2330 |
The implementation is done by a macro similar to the C standard I/O
|
|
|
2331 |
</span><span style="font-size: 10pt"><tt>getc</tt></span><span style="font-size: 10pt">
|
|
|
2332 |
macro.<sup></sup></span><sup><span style="font-size: 6pt">14</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
2333 |
Because the reading may be done at any address, a minor change to the
|
|
|
2334 |
macro allows the file to be read backwards.
|
|
|
2335 |
This array is read-only; there is no
|
|
|
2336 |
</span><span style="font-size: 10pt"><tt>putc</tt></span><span style="font-size: 10pt">.
|
|
|
2337 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2338 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2339 |
<span style="font-size: 10pt"><b>Doing and undoing
|
|
|
2340 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2341 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2342 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
2343 |
has an unusual method for managing changes to files.
|
|
|
2344 |
The command language makes it easy to specify multiple variable-length changes
|
|
|
2345 |
to a file millions of bytes long, and such changes
|
|
|
2346 |
must be made efficiently if the editor is to be practical.
|
|
|
2347 |
The usual techniques for inserting and deleting strings
|
|
|
2348 |
are inadequate under these conditions.
|
|
|
2349 |
The
|
|
|
2350 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">
|
|
|
2351 |
and
|
|
|
2352 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">
|
|
|
2353 |
data structures are designed for efficient random access to long strings,
|
|
|
2354 |
but care must be taken to avoid super-linear behavior when making
|
|
|
2355 |
many changes simultaneously.
|
|
|
2356 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2357 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2358 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
2359 |
uses a two-pass algorithm for making changes, and treats each file as a database
|
|
|
2360 |
against which transactions are registered.
|
|
|
2361 |
Changes are not made directly to the contents.
|
|
|
2362 |
Instead, when a command is started, a ‘mark’ containing
|
|
|
2363 |
a sequence number is placed in the transcript
|
|
|
2364 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">,
|
|
|
2365 |
and each change made to the file, either an insertion or deletion
|
|
|
2366 |
or a change to the file name,
|
|
|
2367 |
is appended to the end of the transcript.
|
|
|
2368 |
When the command is complete, the transcript is rewound to the
|
|
|
2369 |
mark and applied to the contents.
|
|
|
2370 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2371 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2372 |
<span style="font-size: 10pt">One reason for separating evaluation from
|
|
|
2373 |
application in this way is to simplify tracking the addresses of changes
|
|
|
2374 |
made in the middle of a long sequence.
|
|
|
2375 |
The two-pass algorithm also allows all changes to apply to the
|
|
|
2376 |
</span><span style="font-size: 10pt"><i>original</i></span><span style="font-size: 10pt">
|
|
|
2377 |
data: no change can affect another change made in the same command.
|
|
|
2378 |
This is particularly important when evaluating an
|
|
|
2379 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
2380 |
command because it prevents regular expression matches
|
|
|
2381 |
from stumbling over changes made earlier in the execution.
|
|
|
2382 |
Also, the two-pass
|
|
|
2383 |
algorithm is cleaner than the way other UNIX editors allow changes to
|
|
|
2384 |
affect each other;
|
|
|
2385 |
for example,
|
|
|
2386 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">’s
|
|
|
2387 |
idioms to do things like delete every other line
|
|
|
2388 |
depend critically on the implementation.
|
|
|
2389 |
Instead,
|
|
|
2390 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
2391 |
simple model, in which all changes in a command occur effectively
|
|
|
2392 |
simultaneously, is easy to explain and to understand.
|
|
|
2393 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2394 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2395 |
<span style="font-size: 10pt">The records in the transcript are of the form ‘‘delete substring from
|
|
|
2396 |
locations
|
|
|
2397 |
123 to 456’’ and ‘‘insert 11 characters ‘hello there’ at location 789.’’
|
|
|
2398 |
(It is an error if the changes are not at monotonically greater
|
|
|
2399 |
positions through the file.)
|
|
|
2400 |
While the update is occurring, these numbers must be
|
|
|
2401 |
offset by earlier changes, but that is straightforward and
|
|
|
2402 |
local to the update routine;
|
|
|
2403 |
moreover, all the numbers have been computed
|
|
|
2404 |
before the first is examined.
|
|
|
2405 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2406 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2407 |
<span style="font-size: 10pt">Treating the file as a transaction system has another advantage:
|
|
|
2408 |
undo is trivial.
|
|
|
2409 |
All it takes is to invert the transcript after it has been
|
|
|
2410 |
implemented, converting insertions
|
|
|
2411 |
into deletions and vice versa, and saving them in a holding
|
|
|
2412 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">.
|
|
|
2413 |
The ‘do’ transcript can then be deleted from
|
|
|
2414 |
the transcript
|
|
|
2415 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">
|
|
|
2416 |
and replaced by the ‘undo’ transcript.
|
|
|
2417 |
If an undo is requested, the transcript is rewound and the undo transcript
|
|
|
2418 |
executed.
|
|
|
2419 |
Because the transcript
|
|
|
2420 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">
|
|
|
2421 |
is not truncated after each command, it accumulates
|
|
|
2422 |
successive changes.
|
|
|
2423 |
A sequence of undo commands
|
|
|
2424 |
can therefore back up the file arbitrarily,
|
|
|
2425 |
which is more helpful than the more commonly implemented self-inverse form of undo.
|
|
|
2426 |
(</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
2427 |
provides no way to undo an undo, but if it were desired,
|
|
|
2428 |
it would be easy to provide by re-interpreting the ‘do’ transcript.)
|
|
|
2429 |
Each mark in the transcript contains a sequence number and the offset into
|
|
|
2430 |
the transcript of the previous mark, to aid in unwinding the transcript.
|
|
|
2431 |
Marks also contain the value of dot and the modified bit so these can be
|
|
|
2432 |
restored easily.
|
|
|
2433 |
Undoing multiple files is easy; it merely demands undoing all files whose
|
|
|
2434 |
latest change has the same sequence number as the current file.
|
|
|
2435 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2436 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2437 |
<span style="font-size: 10pt">Another benefit of having a transcript is that errors encountered in the middle
|
|
|
2438 |
of a complicated command need not leave the files in an intermediate state.
|
|
|
2439 |
By rewinding the transcript to the mark beginning the command,
|
|
|
2440 |
the partial command can be trivially undone.
|
|
|
2441 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2442 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2443 |
<span style="font-size: 10pt">When the update algorithm was first implemented, it was unacceptably slow,
|
|
|
2444 |
so a cache was added to coalesce nearby changes,
|
|
|
2445 |
replacing multiple small changes by a single larger one.
|
|
|
2446 |
This reduced the number
|
|
|
2447 |
of insertions into the transaction
|
|
|
2448 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">,
|
|
|
2449 |
and made a dramatic improvement in performance,
|
|
|
2450 |
but made it impossible
|
|
|
2451 |
to handle changes in non-monotonic order in the file; the caching method
|
|
|
2452 |
only works if changes don’t overlap.
|
|
|
2453 |
Before the cache was added, the transaction could in principle be sorted
|
|
|
2454 |
if the changes were out of order, although
|
|
|
2455 |
this was never done.
|
|
|
2456 |
The current status is therefore acceptable performance with a minor
|
|
|
2457 |
restriction on global changes, which is sometimes, but rarely, an annoyance.
|
|
|
2458 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2459 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2460 |
<span style="font-size: 10pt">The update algorithm obviously paws the data more than simpler
|
|
|
2461 |
algorithms, but it is not prohibitively expensive;
|
|
|
2462 |
the caches help.
|
|
|
2463 |
(The principle of avoiding copying the data is still honored here,
|
|
|
2464 |
although not as piously:
|
|
|
2465 |
the data is moved from contents’ cache to
|
|
|
2466 |
the transcript’s all at once and through only one internal buffer.)
|
|
|
2467 |
Performance figures confirm the efficiency.
|
|
|
2468 |
To read from a dead start a hundred kilobyte file on a VAX-11/750
|
|
|
2469 |
takes 1.4 seconds of user time, 2.5 seconds of system time,
|
|
|
2470 |
and 5 seconds of real time.
|
|
|
2471 |
Reading the same file in
|
|
|
2472 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
2473 |
takes 6.0 seconds of user time, 1.7 seconds of system time,
|
|
|
2474 |
and 8 seconds of real time.
|
|
|
2475 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
2476 |
uses about half the CPU time.
|
|
|
2477 |
A more interesting example is the one stated above:
|
|
|
2478 |
inserting a character between every pair of characters in the file.
|
|
|
2479 |
The
|
|
|
2480 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2481 |
command is
|
|
|
2482 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
2483 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2484 |
<span style="font-size: 9pt"><tt>,y/@/ a/x/</tt></span></p>
|
|
|
2485 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2486 |
|
|
|
2487 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
2488 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2489 |
<span style="font-size: 10pt">and takes 3 CPU seconds per kilobyte of input file, of which
|
|
|
2490 |
about a third is spent in the regular expression code.
|
|
|
2491 |
This translates to about 500 changes per second.
|
|
|
2492 |
</span><span style="font-size: 10pt"><tt>Ed</tt></span><span style="font-size: 10pt">
|
|
|
2493 |
takes 1.5 seconds per kilobyte to make a similar change (ignoring newlines),
|
|
|
2494 |
but cannot undo it.
|
|
|
2495 |
The same example in
|
|
|
2496 |
</span><span style="font-size: 10pt"><tt>ex</tt></span><span style="font-size: 10pt">,<sup></sup></span><sup><span style="font-size: 6pt">9</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
2497 |
a variant of
|
|
|
2498 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
2499 |
done at the University of California at Berkeley,
|
|
|
2500 |
which allows one level of undoing, again takes 3 seconds.
|
|
|
2501 |
In summary,
|
|
|
2502 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
2503 |
performance is comparable to that of other UNIX editors, although it solves
|
|
|
2504 |
a harder problem.
|
|
|
2505 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2506 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2507 |
<span style="font-size: 10pt"><b>Communications
|
|
|
2508 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2509 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2510 |
<span style="font-size: 10pt">The discussion so far has described the implementation of the host part of
|
|
|
2511 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">;
|
|
|
2512 |
the next few sections explain how a machine with mouse and bitmap display
|
|
|
2513 |
can be engaged to improve interaction.
|
|
|
2514 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
2515 |
is not the first editor to be written as two processes,<sup></sup></span><sup><span style="font-size: 6pt">16</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
2516 |
but its implementation
|
|
|
2517 |
has some unusual aspects.
|
|
|
2518 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2519 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2520 |
<span style="font-size: 10pt">There are several ways
|
|
|
2521 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
2522 |
host and terminal parts may be connected.
|
|
|
2523 |
The first and simplest is to forgo the terminal part and use the host
|
|
|
2524 |
part’s command language to edit text on an ordinary terminal.
|
|
|
2525 |
This mode is invoked by starting
|
|
|
2526 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2527 |
with the
|
|
|
2528 |
</span><span style="font-size: 10pt"><tt>-d</tt></span><span style="font-size: 10pt">
|
|
|
2529 |
option.
|
|
|
2530 |
With no options,
|
|
|
2531 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2532 |
runs separate host and terminal programs,
|
|
|
2533 |
communicating with a message protocol over the physical
|
|
|
2534 |
connection that joins them.
|
|
|
2535 |
Typically, the connection is an RS-232 link between a Blit
|
|
|
2536 |
(the prototypical display for
|
|
|
2537 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">)
|
|
|
2538 |
and a host running
|
|
|
2539 |
the Ninth Edition of the UNIX operating system.<sup></sup></span><sup><span style="font-size: 6pt">8</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
2540 |
(This is the version of the system used in the Computing Sciences Research
|
|
|
2541 |
Center at AT&T Bell Laboratories [now Lucent Technologies, Bell Labs], where I work. Its relevant
|
|
|
2542 |
aspects are discussed in the Blit paper.<sup></sup></span><sup><span style="font-size: 6pt">1</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">)
|
|
|
2543 |
The implementation of
|
|
|
2544 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2545 |
for the SUN computer runs both processes on the same machine and
|
|
|
2546 |
connects them by a pipe.
|
|
|
2547 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2548 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2549 |
<span style="font-size: 10pt">The low bandwidth of an RS-232 link
|
|
|
2550 |
necessitated the split between
|
|
|
2551 |
the two programs.
|
|
|
2552 |
The division is a mixed blessing:
|
|
|
2553 |
a program in two parts is much harder to write and to debug
|
|
|
2554 |
than a self-contained one,
|
|
|
2555 |
but the split makes several unusual configurations possible.
|
|
|
2556 |
The terminal may be physically separated from the host, allowing the conveniences
|
|
|
2557 |
of a mouse and bitmap display to be taken home while leaving the files at work.
|
|
|
2558 |
It is also possible to run the host part on a remote machine:
|
|
|
2559 |
</span></p><p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
2560 |
<p style="line-height: 1.1em; margin-left: 1.28in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2561 |
<span style="font-size: 9pt"><tt>sam -r host</tt></span></p>
|
|
|
2562 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2563 |
|
|
|
2564 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
2565 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2566 |
<span style="font-size: 10pt">connects to the terminal in the usual way, and then makes a call
|
|
|
2567 |
across the network to establish the host part of
|
|
|
2568 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2569 |
on the named machine.
|
|
|
2570 |
Finally, it cross-connects the I/O to join the two parts.
|
|
|
2571 |
This allows
|
|
|
2572 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2573 |
to be run on machines that do not support bitmap displays;
|
|
|
2574 |
for example,
|
|
|
2575 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2576 |
is the editor of choice on our Cray X-MP/24.
|
|
|
2577 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
2578 |
</span><span style="font-size: 10pt"><tt>-r</tt></span><span style="font-size: 10pt">
|
|
|
2579 |
involves
|
|
|
2580 |
</span><span style="font-size: 10pt"><i>three</i></span><span style="font-size: 10pt">
|
|
|
2581 |
machines: the remote host, the terminal, and the local host.
|
|
|
2582 |
The local host’s job is simple but vital: it passes the data
|
|
|
2583 |
between the remote host and terminal.
|
|
|
2584 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2585 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2586 |
<span style="font-size: 10pt">The host and terminal exchange messages asynchronously
|
|
|
2587 |
(rather than, say, as remote procedure calls) but there is no
|
|
|
2588 |
error detection or correction
|
|
|
2589 |
because, whatever the configuration, the connection is reliable.
|
|
|
2590 |
Because the terminal handles mundane interaction tasks such as
|
|
|
2591 |
popping up menus and interpreting the responses, the messages are about
|
|
|
2592 |
data, not actions.
|
|
|
2593 |
For example, the host knows nothing about what is displayed on the screen,
|
|
|
2594 |
and when the user types a character, the message sent to the host says
|
|
|
2595 |
‘‘insert a one-byte string at location 123 in file 7,’’ not ‘‘a character
|
|
|
2596 |
was typed at the current position in the current file.’’
|
|
|
2597 |
In other words, the messages look very much like the transaction records
|
|
|
2598 |
in the transcripts.
|
|
|
2599 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2600 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2601 |
<span style="font-size: 10pt">Either the host or terminal part of
|
|
|
2602 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2603 |
may initiate a change to a file.
|
|
|
2604 |
The command language operates on the host, while typing and some
|
|
|
2605 |
mouse operations are executed directly in the terminal to optimize response.
|
|
|
2606 |
Changes initiated by the host program must be transmitted to the terminal,
|
|
|
2607 |
and
|
|
|
2608 |
vice versa.
|
|
|
2609 |
(A token is exchanged to determine which end is in control,
|
|
|
2610 |
which means that characters typed while a time-consuming command runs
|
|
|
2611 |
must be buffered and do not appear until the command is complete.)
|
|
|
2612 |
To maintain consistent information,
|
|
|
2613 |
the host and terminal track changes through a per-file
|
|
|
2614 |
data structure that records what portions of the file
|
|
|
2615 |
the terminal has received.
|
|
|
2616 |
The data structure, called a
|
|
|
2617 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2618 |
(a weak pun: it’s a file with holes)
|
|
|
2619 |
is held and updated by both the host and terminal.
|
|
|
2620 |
A
|
|
|
2621 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2622 |
is a list of
|
|
|
2623 |
</span><span style="font-size: 10pt"><tt>Strings</tt></span><span style="font-size: 10pt">
|
|
|
2624 |
holding those parts of the file known to the terminal,
|
|
|
2625 |
separated by counts of the number of bytes in the interstices.
|
|
|
2626 |
Of course, the host doesn’t keep a separate copy of the data (it only needs
|
|
|
2627 |
the lengths of the various pieces),
|
|
|
2628 |
but the structure is the same on both ends.
|
|
|
2629 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2630 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2631 |
<span style="font-size: 10pt">The
|
|
|
2632 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2633 |
in the terminal doubles as a cache.
|
|
|
2634 |
Since the terminal keeps the text for portions of the file it has displayed,
|
|
|
2635 |
it need not request data from the host when revisiting old parts of the file
|
|
|
2636 |
or redrawing obscured windows, which speeds things up considerably
|
|
|
2637 |
over low-speed links.
|
|
|
2638 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2639 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2640 |
<span style="font-size: 10pt">It’s trivial for the terminal to maintain its
|
|
|
2641 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">,
|
|
|
2642 |
because all changes made on the terminal apply to parts of the file
|
|
|
2643 |
already loaded there.
|
|
|
2644 |
Changes made by the host are compared against the
|
|
|
2645 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2646 |
during the update sequence after each command.
|
|
|
2647 |
Small changes to pieces of the file loaded in the terminal
|
|
|
2648 |
are sent in their entirety.
|
|
|
2649 |
Larger changes, and changes that fall entirely in the holes,
|
|
|
2650 |
are transmitted as messages without literal data:
|
|
|
2651 |
only the lengths of the deleted and inserted strings are transmitted.
|
|
|
2652 |
When a command is completed, the terminal examines its visible
|
|
|
2653 |
windows to see if any holes in their
|
|
|
2654 |
</span><span style="font-size: 10pt"><tt>Rasps</tt></span><span style="font-size: 10pt">
|
|
|
2655 |
intersect the visible portion of the file.
|
|
|
2656 |
It then requests the missing data from the host,
|
|
|
2657 |
along with up to 512 bytes of surrounding data, to minimize
|
|
|
2658 |
the number of messages when visiting a new portion of the file.
|
|
|
2659 |
This technique provides a kind of two-level lazy evaluation for the terminal.
|
|
|
2660 |
The first level sends a minimum of information about
|
|
|
2661 |
parts of the file not being edited interactively;
|
|
|
2662 |
the second level waits until a change is displayed before
|
|
|
2663 |
transmitting the new data.
|
|
|
2664 |
Of course,
|
|
|
2665 |
performance is also helped by having the terminal respond immediately to typing
|
|
|
2666 |
and simple mouse requests.
|
|
|
2667 |
Except for small changes to active pieces of the file, which are
|
|
|
2668 |
transmitted to the terminal without negotiation,
|
|
|
2669 |
the terminal is wholly responsible for deciding what is displayed;
|
|
|
2670 |
the host uses the
|
|
|
2671 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2672 |
only to tell the terminal what might be relevant.
|
|
|
2673 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2674 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2675 |
<span style="font-size: 10pt">When a change is initiated by the host,
|
|
|
2676 |
the messages to the terminal describing the change
|
|
|
2677 |
are generated by the routine that applies the transcript of the changes
|
|
|
2678 |
to the contents of the
|
|
|
2679 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">.
|
|
|
2680 |
Since changes are undone by the same update routine,
|
|
|
2681 |
undoing requires
|
|
|
2682 |
no extra code in the communications;
|
|
|
2683 |
the usual messages describing changes to the file are sufficient
|
|
|
2684 |
to back up the screen image.
|
|
|
2685 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2686 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2687 |
<span style="font-size: 10pt">The
|
|
|
2688 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2689 |
is a particularly good example of the way caches are used in
|
|
|
2690 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">.
|
|
|
2691 |
First, it facilitates access to the active portion of the text by placing
|
|
|
2692 |
the busy text in main memory.
|
|
|
2693 |
In so doing, it provides efficient access
|
|
|
2694 |
to a large data structure that does not fit in memory.
|
|
|
2695 |
Since the form of data is to be imposed by the user, not by the program,
|
|
|
2696 |
and because characters will frequently be scanned sequentially,
|
|
|
2697 |
files are stored as flat objects.
|
|
|
2698 |
Caches help keep performance good and linear when working with such
|
|
|
2699 |
data.
|
|
|
2700 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2701 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2702 |
<span style="font-size: 10pt">Second, the
|
|
|
2703 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2704 |
and several of the other caches have some
|
|
|
2705 |
</span><span style="font-size: 10pt"><i>read-ahead;</i></span><span style="font-size: 10pt">
|
|
|
2706 |
that is, the cache is loaded with more information than is needed for
|
|
|
2707 |
the job immediately at hand.
|
|
|
2708 |
When manipulating linear structures, the accesses are usually sequential,
|
|
|
2709 |
and read-ahead can significantly reduce the average time to access the
|
|
|
2710 |
next element of the object.
|
|
|
2711 |
Sequential access is a common mode for people as well as programs;
|
|
|
2712 |
consider scrolling through a document while looking for something.
|
|
|
2713 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2714 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2715 |
<span style="font-size: 10pt">Finally, like any good data structure,
|
|
|
2716 |
the cache guides the algorithm, or at least the implementation.
|
|
|
2717 |
The
|
|
|
2718 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2719 |
was actually invented to control the communications between the host and
|
|
|
2720 |
terminal parts, but I realized very early that it was also a form of
|
|
|
2721 |
cache. Other caches were more explicitly intended to serve a double
|
|
|
2722 |
purpose: for example, the caches in
|
|
|
2723 |
</span><span style="font-size: 10pt"><tt>Files</tt></span><span style="font-size: 10pt">
|
|
|
2724 |
that coalesce updates not only reduce traffic to the
|
|
|
2725 |
transcript and contents
|
|
|
2726 |
</span><span style="font-size: 10pt"><tt>Buffers</tt></span><span style="font-size: 10pt">,
|
|
|
2727 |
they also clump screen updates so that complicated changes to the
|
|
|
2728 |
screen are achieved in
|
|
|
2729 |
just a few messages to the terminal.
|
|
|
2730 |
This saved me considerable work: I did not need to write special
|
|
|
2731 |
code to optimize the message traffic to the
|
|
|
2732 |
terminal.
|
|
|
2733 |
Caches pay off in surprising ways.
|
|
|
2734 |
Also, they tend to be independent, so their performance improvements
|
|
|
2735 |
are multiplicative.
|
|
|
2736 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2737 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2738 |
<span style="font-size: 10pt"><b>Data structures in the terminal
|
|
|
2739 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2740 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2741 |
<span style="font-size: 10pt">The terminal’s job is to display and to maintain a consistent image of
|
|
|
2742 |
pieces of the files being edited.
|
|
|
2743 |
Because the text is always in memory, the data structures are
|
|
|
2744 |
considerably simpler than those in the host part.
|
|
|
2745 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2746 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2747 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
2748 |
typically has far more windows than does
|
|
|
2749 |
</span><span style="font-size: 10pt"><tt>mux</tt></span><span style="font-size: 10pt">,
|
|
|
2750 |
the window system within which its Blit implementation runs.
|
|
|
2751 |
</span><span style="font-size: 10pt"><tt>Mux</tt></span><span style="font-size: 10pt">
|
|
|
2752 |
has a fairly small number of asynchronously updated windows;
|
|
|
2753 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2754 |
needs a large number of synchronously updated windows that are
|
|
|
2755 |
usually static and often fully obscured.
|
|
|
2756 |
The different tradeoffs guided
|
|
|
2757 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2758 |
away from the memory-intensive implementation of windows, called
|
|
|
2759 |
</span><span style="font-size: 10pt"><tt>Layers</tt></span><span style="font-size: 10pt">,<sup></sup></span><sup><span style="font-size: 6pt">17</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
2760 |
used in
|
|
|
2761 |
</span><span style="font-size: 10pt"><tt>mux.</tt></span><span style="font-size: 10pt">
|
|
|
2762 |
Rather than depending on a complete bitmap image of the display for each window,
|
|
|
2763 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2764 |
regenerates the image from its in-memory text
|
|
|
2765 |
(stored in the
|
|
|
2766 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">)
|
|
|
2767 |
when necessary, although it will use such an image if it is available.
|
|
|
2768 |
Like
|
|
|
2769 |
</span><span style="font-size: 10pt"><tt>Layers</tt></span><span style="font-size: 10pt">,
|
|
|
2770 |
though,
|
|
|
2771 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2772 |
uses the screen bitmap as active storage in which to update the image using
|
|
|
2773 |
</span><span style="font-size: 10pt"><tt>bitblt</tt></span><span style="font-size: 10pt">.<sup></sup></span><sup><span style="font-size: 6pt">18,19</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
2774 |
The resulting organization, pictured in Figure 6,
|
|
|
2775 |
has a global array of windows, called
|
|
|
2776 |
</span><span style="font-size: 10pt"><tt>Flayers</tt></span><span style="font-size: 10pt">,
|
|
|
2777 |
each of which holds an image of a piece of text held in a data structure
|
|
|
2778 |
called a
|
|
|
2779 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">,
|
|
|
2780 |
which in turn represents
|
|
|
2781 |
a rectangular window full of text displayed in some
|
|
|
2782 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">.
|
|
|
2783 |
Each
|
|
|
2784 |
</span><span style="font-size: 10pt"><tt>Flayer</tt></span><span style="font-size: 10pt">
|
|
|
2785 |
appears in a global list that orders them all front-to-back
|
|
|
2786 |
on the display, and simultaneously as an element of a per-file array
|
|
|
2787 |
that holds all the open windows for that file.
|
|
|
2788 |
The complement in the terminal of the
|
|
|
2789 |
</span><span style="font-size: 10pt"><tt>File</tt></span><span style="font-size: 10pt">
|
|
|
2790 |
on the host is called a
|
|
|
2791 |
</span><span style="font-size: 10pt"><tt>Text</tt></span><span style="font-size: 10pt">;
|
|
|
2792 |
each connects its
|
|
|
2793 |
</span><span style="font-size: 10pt"><tt>Flayers</tt></span><span style="font-size: 10pt">
|
|
|
2794 |
to the associated
|
|
|
2795 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">.
|
|
|
2796 |
</span><span style="font-size: 10pt"></span></p><center><img src="sam3.png"></center>
|
|
|
2797 |
</center>
|
|
|
2798 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2799 |
<span style="font-size: 8pt"><i>Figure 6. Data structures in the terminal.
|
|
|
2800 |
</i></span><span style="font-size: 8pt"><tt>Flayers</tt></span><span style="font-size: 8pt"><i>
|
|
|
2801 |
are also linked together into a front-to-back list.
|
|
|
2802 |
</i></span><span style="font-size: 8pt"><tt>Boxes</tt></span><span style="font-size: 8pt"><i>
|
|
|
2803 |
are discussed in the next section.
|
|
|
2804 |
</i></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2805 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
2806 |
|
|
|
2807 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2808 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2809 |
<span style="font-size: 10pt">The
|
|
|
2810 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2811 |
for a
|
|
|
2812 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
2813 |
contains the image of the text.
|
|
|
2814 |
For a fully visible window, the
|
|
|
2815 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2816 |
will be the screen (or at least the
|
|
|
2817 |
</span><span style="font-size: 10pt"><tt>Layer</tt></span><span style="font-size: 10pt">
|
|
|
2818 |
in which
|
|
|
2819 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2820 |
is being run),
|
|
|
2821 |
while for partially obscured windows the
|
|
|
2822 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2823 |
will be off-screen.
|
|
|
2824 |
If the window is fully obscured, the
|
|
|
2825 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2826 |
will be null.
|
|
|
2827 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2828 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2829 |
<span style="font-size: 10pt">The
|
|
|
2830 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2831 |
is a kind of cache.
|
|
|
2832 |
When making changes to the display, most of the original image will
|
|
|
2833 |
look the same in the final image, and the update algorithms exploit this.
|
|
|
2834 |
The
|
|
|
2835 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
2836 |
software updates the image in the
|
|
|
2837 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2838 |
incrementally; the
|
|
|
2839 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2840 |
is not just an image, it is a data structure.<sup></sup></span><sup><span style="font-size: 6pt">18,19</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
2841 |
The job of the software that updates the display is therefore
|
|
|
2842 |
to use as much as possible of the existing image (converting the
|
|
|
2843 |
text from ASCII characters to pixels is expensive) in a sort of two-dimensional
|
|
|
2844 |
string insertion algorithm.
|
|
|
2845 |
The details of this process are described in the next section.
|
|
|
2846 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2847 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2848 |
<span style="font-size: 10pt">The
|
|
|
2849 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
2850 |
software has no code to support overlapping windows;
|
|
|
2851 |
its job is to keep a single
|
|
|
2852 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2853 |
up to date.
|
|
|
2854 |
It falls to the
|
|
|
2855 |
</span><span style="font-size: 10pt"><tt>Flayer</tt></span><span style="font-size: 10pt">
|
|
|
2856 |
software to multiplex the various
|
|
|
2857 |
</span><span style="font-size: 10pt"><tt>Bitmaps</tt></span><span style="font-size: 10pt">
|
|
|
2858 |
onto the screen.
|
|
|
2859 |
The problem of maintaining overlapping
|
|
|
2860 |
</span><span style="font-size: 10pt"><tt>Flayers</tt></span><span style="font-size: 10pt">
|
|
|
2861 |
is easier than for
|
|
|
2862 |
</span><span style="font-size: 10pt"><tt>Layers</tt></span><span style="font-size: 10pt"><sup></sup></span><sup><span style="font-size: 6pt">17</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt">
|
|
|
2863 |
because changes are made synchronously and because the contents of the window
|
|
|
2864 |
can be reconstructed from the data stored in the
|
|
|
2865 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">;
|
|
|
2866 |
the
|
|
|
2867 |
</span><span style="font-size: 10pt"><tt>Layers</tt></span><span style="font-size: 10pt">
|
|
|
2868 |
software
|
|
|
2869 |
makes no such assumptions.
|
|
|
2870 |
In
|
|
|
2871 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">,
|
|
|
2872 |
the window being changed is almost always fully visible, because the current
|
|
|
2873 |
window is always fully visible, by construction.
|
|
|
2874 |
However, when multi-file changes are being made, or when
|
|
|
2875 |
more than one window is open on a file,
|
|
|
2876 |
it may be necessary to update partially obscured windows.
|
|
|
2877 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2878 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2879 |
<span style="font-size: 10pt">There are three cases: the window is
|
|
|
2880 |
fully visible, invisible (fully obscured), or partially visible.
|
|
|
2881 |
If fully visible, the
|
|
|
2882 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2883 |
is part of the screen, so when the
|
|
|
2884 |
</span><span style="font-size: 10pt"><tt>Flayer</tt></span><span style="font-size: 10pt">
|
|
|
2885 |
update routine calls the
|
|
|
2886 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
2887 |
update routine, the screen will be updated directly.
|
|
|
2888 |
If the window is invisible,
|
|
|
2889 |
there is no associated
|
|
|
2890 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">,
|
|
|
2891 |
and all that is necessary is to update the
|
|
|
2892 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
2893 |
data structure, not the image.
|
|
|
2894 |
If the window is partially visible, the
|
|
|
2895 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
2896 |
routine is called to update the image in the off-screen
|
|
|
2897 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">,
|
|
|
2898 |
which may require regenerating it from the text of the window.
|
|
|
2899 |
The
|
|
|
2900 |
</span><span style="font-size: 10pt"><tt>Flayer</tt></span><span style="font-size: 10pt">
|
|
|
2901 |
code then clips this
|
|
|
2902 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
2903 |
against the
|
|
|
2904 |
</span><span style="font-size: 10pt"><tt>Bitmaps</tt></span><span style="font-size: 10pt">
|
|
|
2905 |
of all
|
|
|
2906 |
</span><span style="font-size: 10pt"><tt>Frames</tt></span><span style="font-size: 10pt">
|
|
|
2907 |
in front of the
|
|
|
2908 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
2909 |
being modified, and the remainder is copied to the display.
|
|
|
2910 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2911 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2912 |
<span style="font-size: 10pt">This is much faster than recreating the image off-screen
|
|
|
2913 |
for every change, or clipping all the changes made to the image
|
|
|
2914 |
during its update.
|
|
|
2915 |
Unfortunately, these caches can also consume prohibitive amounts of
|
|
|
2916 |
memory, so they are freed fairly liberally — after every change to the
|
|
|
2917 |
front-to-back order of the
|
|
|
2918 |
</span><span style="font-size: 10pt"><tt>Flayers</tt></span><span style="font-size: 10pt">.
|
|
|
2919 |
The result is that
|
|
|
2920 |
the off-screen
|
|
|
2921 |
</span><span style="font-size: 10pt"><tt>Bitmaps</tt></span><span style="font-size: 10pt">
|
|
|
2922 |
exist only while multi-window changes are occurring,
|
|
|
2923 |
which is the only time the performance improvement they provide is needed.
|
|
|
2924 |
Also, the user interface causes fully-obscured windows to be the
|
|
|
2925 |
easiest to make —
|
|
|
2926 |
creating a canonically sized and placed window requires only a button click
|
|
|
2927 |
— which reduces the need for caching still further.
|
|
|
2928 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2929 |
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
2930 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2931 |
<span style="font-size: 10pt"><b>Screen update
|
|
|
2932 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2933 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2934 |
<span style="font-size: 10pt">Only two low-level primitives are needed for incremental update:
|
|
|
2935 |
</span><span style="font-size: 10pt"><tt>bitblt</tt></span><span style="font-size: 10pt">,
|
|
|
2936 |
which copies rectangles of pixels, and
|
|
|
2937 |
</span><span style="font-size: 10pt"><tt>string</tt></span><span style="font-size: 10pt">
|
|
|
2938 |
(which in turn calls
|
|
|
2939 |
</span><span style="font-size: 10pt"><tt>bitblt</tt></span><span style="font-size: 10pt">),
|
|
|
2940 |
which draws a null-terminated character string in a
|
|
|
2941 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">.
|
|
|
2942 |
A
|
|
|
2943 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
2944 |
contains a list of
|
|
|
2945 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">,
|
|
|
2946 |
each of which defines a horizontal strip of text in the window
|
|
|
2947 |
(see Figure 7).
|
|
|
2948 |
A
|
|
|
2949 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
2950 |
has a character string
|
|
|
2951 |
</span><span style="font-size: 10pt"><tt>str</tt></span><span style="font-size: 10pt">,
|
|
|
2952 |
and a
|
|
|
2953 |
</span><span style="font-size: 10pt"><tt>Rectangle</tt></span><span style="font-size: 10pt">
|
|
|
2954 |
</span><span style="font-size: 10pt"><tt>rect</tt></span><span style="font-size: 10pt">
|
|
|
2955 |
that defines the location of the strip in the window.
|
|
|
2956 |
(The text in
|
|
|
2957 |
</span><span style="font-size: 10pt"><tt>str</tt></span><span style="font-size: 10pt">
|
|
|
2958 |
is stored in the
|
|
|
2959 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
2960 |
separately from the
|
|
|
2961 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
2962 |
associated with the window’s file, so
|
|
|
2963 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">
|
|
|
2964 |
are self-contained.)
|
|
|
2965 |
The invariant is that
|
|
|
2966 |
the image of the
|
|
|
2967 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
2968 |
can be reproduced by calling
|
|
|
2969 |
</span><span style="font-size: 10pt"><tt>string</tt></span><span style="font-size: 10pt">
|
|
|
2970 |
with argument
|
|
|
2971 |
</span><span style="font-size: 10pt"><tt>str</tt></span><span style="font-size: 10pt">
|
|
|
2972 |
to draw the string in
|
|
|
2973 |
</span><span style="font-size: 10pt"><tt>rect</tt></span><span style="font-size: 10pt">,
|
|
|
2974 |
and the resulting picture fits perfectly within
|
|
|
2975 |
</span><span style="font-size: 10pt"><tt>rect</tt></span><span style="font-size: 10pt">.
|
|
|
2976 |
In other words, the
|
|
|
2977 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">
|
|
|
2978 |
define the tiling of the window.
|
|
|
2979 |
The tiling may be complicated by long lines of text, which
|
|
|
2980 |
are folded onto the next line.
|
|
|
2981 |
Some editors use horizontal scrolling to avoid this complication,
|
|
|
2982 |
but to be comfortable this technique requires that lines not be
|
|
|
2983 |
</span><span style="font-size: 10pt"><i>too</i></span><span style="font-size: 10pt">
|
|
|
2984 |
long;
|
|
|
2985 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
2986 |
has no such restriction.
|
|
|
2987 |
Also, and perhaps more importantly, UNIX programs and terminals traditionally fold
|
|
|
2988 |
long lines to make their contents fully visible.
|
|
|
2989 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
2990 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
2991 |
<span style="font-size: 10pt">Two special kinds of
|
|
|
2992 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">
|
|
|
2993 |
contain a single
|
|
|
2994 |
character: either a newline or a tab.
|
|
|
2995 |
Newlines and tabs are white space.
|
|
|
2996 |
A newline
|
|
|
2997 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
2998 |
always extends to the right edge of the window,
|
|
|
2999 |
forcing the following
|
|
|
3000 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
3001 |
to the next line.
|
|
|
3002 |
The width of a tab depends on where it is located:
|
|
|
3003 |
it forces the next
|
|
|
3004 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
3005 |
to begin at a tab location.
|
|
|
3006 |
Tabs also
|
|
|
3007 |
have a minimum width equivalent to a blank (blanks are
|
|
|
3008 |
drawn by
|
|
|
3009 |
</span><span style="font-size: 10pt"><tt>string</tt></span><span style="font-size: 10pt">
|
|
|
3010 |
and are not treated specially); newlines have a minimum width of zero.
|
|
|
3011 |
</span><span style="font-size: 10pt"></span></p><center><img src="sam4.png"></center>
|
|
|
3012 |
</center>
|
|
|
3013 |
<p style="margin-top: 0; margin-bottom: 0.08in"></p>
|
|
|
3014 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3015 |
<span style="font-size: 8pt"><i>Figure 7. A line of text showing its
|
|
|
3016 |
</i></span><span style="font-size: 8pt"><tt>Boxes</tt></span><span style="font-size: 8pt"><i>.
|
|
|
3017 |
The first two blank
|
|
|
3018 |
</i></span><span style="font-size: 8pt"><tt>Boxes</tt></span><span style="font-size: 8pt"><i>
|
|
|
3019 |
contain tabs; the last contains a newline.
|
|
|
3020 |
Spaces are handled as ordinary characters.
|
|
|
3021 |
</i></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
3022 |
<p style="margin-top: 0; margin-bottom: 0.02in"></p>
|
|
|
3023 |
|
|
|
3024 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3025 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3026 |
<span style="font-size: 10pt">The update algorithms always use the
|
|
|
3027 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">
|
|
|
3028 |
image of the text (either the display or cache
|
|
|
3029 |
</span><span style="font-size: 10pt"><tt>Bitmap</tt></span><span style="font-size: 10pt">);
|
|
|
3030 |
they never examine the characters within a
|
|
|
3031 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
3032 |
except when the
|
|
|
3033 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
3034 |
needs to be split in two.
|
|
|
3035 |
Before a change, the window consists of a tiling of
|
|
|
3036 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">;
|
|
|
3037 |
after the change the window is tiled differently.
|
|
|
3038 |
The update algorithms rearrange the tiles in place, without
|
|
|
3039 |
backup storage.
|
|
|
3040 |
The algorithms are not strictly optimal — for example, they can
|
|
|
3041 |
clear a pixel that is later going to be written upon —
|
|
|
3042 |
but they never move a tile that doesn’t need to be moved,
|
|
|
3043 |
and they move each tile at most once.
|
|
|
3044 |
</span><span style="font-size: 10pt"><tt>Frinsert</tt></span><span style="font-size: 10pt">
|
|
|
3045 |
on a Blit can absorb over a thousand characters a second if the strings
|
|
|
3046 |
being inserted are a few tens of characters long.
|
|
|
3047 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3048 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3049 |
<span style="font-size: 10pt">Consider
|
|
|
3050 |
</span><span style="font-size: 10pt"><tt>frdelete</tt></span><span style="font-size: 10pt">.
|
|
|
3051 |
Its job is to delete a substring from a
|
|
|
3052 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
3053 |
and restore the image of the
|
|
|
3054 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">.
|
|
|
3055 |
The image of a substring has a peculiar shape (see Figure 2) comprising
|
|
|
3056 |
possibly a partial line,
|
|
|
3057 |
zero or more full lines,
|
|
|
3058 |
and possibly a final partial line.
|
|
|
3059 |
For reference, call this the
|
|
|
3060 |
</span><span style="font-size: 10pt"><i>Z-shape.
|
|
|
3061 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Frdelete</tt></span><span style="font-size: 10pt">
|
|
|
3062 |
begins by splitting, if necessary, the
|
|
|
3063 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">
|
|
|
3064 |
containing the ends of
|
|
|
3065 |
the substring so the substring begins and ends on
|
|
|
3066 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
3067 |
boundaries.
|
|
|
3068 |
Because the substring is being deleted, its image is not needed,
|
|
|
3069 |
so the Z-shape is then cleared.
|
|
|
3070 |
Then, tiles (that is, the images of
|
|
|
3071 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">)
|
|
|
3072 |
are copied, using
|
|
|
3073 |
</span><span style="font-size: 10pt"><tt>bitblt</tt></span><span style="font-size: 10pt">,
|
|
|
3074 |
from immediately after the Z-shape to
|
|
|
3075 |
the beginning of the Z-shape,
|
|
|
3076 |
resulting in a new Z-shape.
|
|
|
3077 |
(</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">
|
|
|
3078 |
whose contents would span two lines in the new position must first be split.)
|
|
|
3079 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3080 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3081 |
<span style="font-size: 10pt">Copying the remainder of the
|
|
|
3082 |
</span><span style="font-size: 10pt"><tt>Frame</tt></span><span style="font-size: 10pt">
|
|
|
3083 |
tile by tile
|
|
|
3084 |
this way will clearly accomplish the deletion but eventually,
|
|
|
3085 |
typically when the copying algorithm encounters a tab or newline,
|
|
|
3086 |
the old and new
|
|
|
3087 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
3088 |
coordinates of the tile
|
|
|
3089 |
to be copied are the same.
|
|
|
3090 |
This correspondence implies
|
|
|
3091 |
that the Z-shape has its beginning and ending edges aligned
|
|
|
3092 |
vertically, and a sequence of at most two
|
|
|
3093 |
</span><span style="font-size: 10pt"><tt>bitblts</tt></span><span style="font-size: 10pt">
|
|
|
3094 |
can be used to copy the remaining tiles.
|
|
|
3095 |
The last step is to clear out the resulting empty space at the bottom
|
|
|
3096 |
of the window;
|
|
|
3097 |
the number of lines to be cleared is the number of complete lines in the
|
|
|
3098 |
Z-shape closed by the final
|
|
|
3099 |
</span><span style="font-size: 10pt"><tt>bitblts.</tt></span><span style="font-size: 10pt">
|
|
|
3100 |
The final step is to merge horizontally adjacent
|
|
|
3101 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">
|
|
|
3102 |
of plain text.
|
|
|
3103 |
The complete source to
|
|
|
3104 |
</span><span style="font-size: 10pt"><tt>frdelete</tt></span><span style="font-size: 10pt">
|
|
|
3105 |
is less than 100 lines of C.
|
|
|
3106 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3107 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3108 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>frinsert</tt></span><span style="font-size: 10pt">
|
|
|
3109 |
is more complicated because it must do four passes:
|
|
|
3110 |
one to construct the
|
|
|
3111 |
</span><span style="font-size: 10pt"><tt>Box</tt></span><span style="font-size: 10pt">
|
|
|
3112 |
list for the inserted string,
|
|
|
3113 |
one to reconnoitre,
|
|
|
3114 |
one to copy (in opposite order to
|
|
|
3115 |
</span><span style="font-size: 10pt"><tt>frdelete</tt></span><span style="font-size: 10pt">)
|
|
|
3116 |
the
|
|
|
3117 |
</span><span style="font-size: 10pt"><tt>Boxes</tt></span><span style="font-size: 10pt">
|
|
|
3118 |
to make the hole for the new text,
|
|
|
3119 |
and finally one to copy the new text into place.
|
|
|
3120 |
Overall, though,
|
|
|
3121 |
</span><span style="font-size: 10pt"><tt>frinsert</tt></span><span style="font-size: 10pt">
|
|
|
3122 |
has a similar flavor to
|
|
|
3123 |
</span><span style="font-size: 10pt"><tt>frdelete</tt></span><span style="font-size: 10pt">,
|
|
|
3124 |
and needn’t be described further.
|
|
|
3125 |
</span><span style="font-size: 10pt"><tt>Frinsert</tt></span><span style="font-size: 10pt">
|
|
|
3126 |
and its subsidiary routines comprise 211 lines of C.
|
|
|
3127 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3128 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3129 |
<span style="font-size: 10pt">The terminal source code is 3024 lines of C,
|
|
|
3130 |
and the host source is 5797 lines.
|
|
|
3131 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
3132 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3133 |
<span style="font-size: 10pt"><b>Discussion
|
|
|
3134 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
3135 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3136 |
<span style="font-size: 10pt"><b>History
|
|
|
3137 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3138 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3139 |
<span style="font-size: 10pt">The immediate ancestor of
|
|
|
3140 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3141 |
was the original text editor for the Blit, called
|
|
|
3142 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">.
|
|
|
3143 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
3144 |
inherited
|
|
|
3145 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">’s
|
|
|
3146 |
two-process structure and mouse language almost unchanged, but
|
|
|
3147 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3148 |
suffered from several drawbacks that were addressed in the design of
|
|
|
3149 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">.
|
|
|
3150 |
The most important of these was the lack of a command language.
|
|
|
3151 |
Although
|
|
|
3152 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3153 |
was easy to use for simple editing, it provided no direct help with
|
|
|
3154 |
large or repetitive editing tasks. Instead, it provided a command to pass
|
|
|
3155 |
selected text through a shell pipeline,
|
|
|
3156 |
but this was no more satisfactory than could be expected of a stopgap measure.
|
|
|
3157 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3158 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3159 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Jim</tt></span><span style="font-size: 10pt">
|
|
|
3160 |
was written primarily as a vehicle for experimenting with a mouse-based
|
|
|
3161 |
interface to text, and the experiment was successful.
|
|
|
3162 |
</span><span style="font-size: 10pt"><tt>Jim</tt></span><span style="font-size: 10pt">
|
|
|
3163 |
had some spin-offs:
|
|
|
3164 |
</span><span style="font-size: 10pt"><tt>mux</tt></span><span style="font-size: 10pt">,
|
|
|
3165 |
the second window system for the Blit, is essentially a multiplexed
|
|
|
3166 |
version of the terminal part of
|
|
|
3167 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">;
|
|
|
3168 |
and the debugger
|
|
|
3169 |
</span><span style="font-size: 10pt"><tt>pi</tt></span><span style="font-size: 10pt">’s
|
|
|
3170 |
user interface<sup></sup></span><sup><span style="font-size: 6pt">20</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt"> was closely modeled on
|
|
|
3171 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">’s.
|
|
|
3172 |
But after a couple of years,
|
|
|
3173 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3174 |
had become difficult to maintain and limiting to use,
|
|
|
3175 |
and its replacement was overdue.
|
|
|
3176 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3177 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3178 |
<span style="font-size: 10pt">I began the design of
|
|
|
3179 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3180 |
by asking
|
|
|
3181 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3182 |
customers what they wanted.
|
|
|
3183 |
This was probably a mistake; the answers were essentially a list of features
|
|
|
3184 |
to be found in other editors, which did not provide any of the
|
|
|
3185 |
guiding principles I was seeking.
|
|
|
3186 |
For instance, one common request was for a ‘‘global substitute,’’
|
|
|
3187 |
but no one suggested how to provide it within a cut-and-paste editor.
|
|
|
3188 |
I was looking for a scheme that would
|
|
|
3189 |
support such specialized features comfortably in the context of some
|
|
|
3190 |
general command language.
|
|
|
3191 |
Ideas were not forthcoming, though, particularly given my insistence
|
|
|
3192 |
on removing all limits on file sizes, line lengths and so on.
|
|
|
3193 |
Even worse, I recognized that, since the mouse could easily
|
|
|
3194 |
indicate a region of the screen that was not an integral number of lines,
|
|
|
3195 |
the command language would best forget about newlines altogether,
|
|
|
3196 |
and that meant the command language had to treat the file as a single
|
|
|
3197 |
string, not an array of lines.
|
|
|
3198 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3199 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3200 |
<span style="font-size: 10pt">Eventually, I decided that thinking was not getting me very far and it was
|
|
|
3201 |
time to try building.
|
|
|
3202 |
I knew that the terminal part could be built easily —
|
|
|
3203 |
that part of
|
|
|
3204 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3205 |
behaved acceptably well — and that most of the hard work was going
|
|
|
3206 |
to be in the host part: the file interface, command interpreter and so on.
|
|
|
3207 |
Moreover, I had some ideas about how the architecture of
|
|
|
3208 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3209 |
could be improved without destroying its basic structure, which I liked
|
|
|
3210 |
in principle but which hadn’t worked out as well as I had hoped.
|
|
|
3211 |
So I began by designing the file data structure,
|
|
|
3212 |
starting with the way
|
|
|
3213 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3214 |
worked — comparable to a single structure merging
|
|
|
3215 |
</span><span style="font-size: 10pt"><tt>Disc</tt></span><span style="font-size: 10pt">
|
|
|
3216 |
and
|
|
|
3217 |
</span><span style="font-size: 10pt"><tt>Buffer</tt></span><span style="font-size: 10pt">,
|
|
|
3218 |
which I split to make the cache more general
|
|
|
3219 |
— and thinking about how global substitute could be implemented.
|
|
|
3220 |
The answer was clearly that it had to be done in two passes,
|
|
|
3221 |
and the transcript-oriented implementation fell out naturally.
|
|
|
3222 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3223 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3224 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
3225 |
was written bottom-up,
|
|
|
3226 |
starting from the data structures and algorithms for manipulating text,
|
|
|
3227 |
through the command language and up to the code for maintaining
|
|
|
3228 |
the display.
|
|
|
3229 |
In retrospect, it turned out well, but this implementation method is
|
|
|
3230 |
not recommended in general.
|
|
|
3231 |
There were several times when I had a large body of interesting code
|
|
|
3232 |
assembled and no clue how to proceed with it.
|
|
|
3233 |
The command language, in particular, took almost a year to figure out,
|
|
|
3234 |
but can be implemented (given what was there at the beginning of that year)
|
|
|
3235 |
in a day or two. Similarly, inventing the
|
|
|
3236 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
3237 |
data structure delayed the
|
|
|
3238 |
connection of the host and terminal pieces by another few months.
|
|
|
3239 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
3240 |
took about two years to write, although only about four months were
|
|
|
3241 |
spent actually working on it.
|
|
|
3242 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3243 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3244 |
<span style="font-size: 10pt">Part of the design process was unusual:
|
|
|
3245 |
the subset of the protocol that maintains the
|
|
|
3246 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
3247 |
was simulated, debugged
|
|
|
3248 |
and verified by an automatic protocol analyzer,<sup></sup></span><sup><span style="font-size: 6pt">21</span><span style="font-size: 10pt"></span></sup><span style="font-size: 10pt"> and was bug-free
|
|
|
3249 |
from the start.
|
|
|
3250 |
The rest of the protocol, concerned mostly
|
|
|
3251 |
with keeping menus up to date,
|
|
|
3252 |
was unfortunately too unwieldy for such analysis,
|
|
|
3253 |
and was debugged by more traditional methods, primarily
|
|
|
3254 |
by logging in a file all messages in and out of the host.
|
|
|
3255 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
3256 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3257 |
<span style="font-size: 10pt"><b>Reflections
|
|
|
3258 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3259 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3260 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
3261 |
is essentially the only interactive editor used by the sixty or so members of
|
|
|
3262 |
the computing science research center in which I work.
|
|
|
3263 |
The same could not be said of
|
|
|
3264 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">;
|
|
|
3265 |
the lack of a command language kept some people from adopting it.
|
|
|
3266 |
The union of a user interface as comfortable as
|
|
|
3267 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">’s
|
|
|
3268 |
with a command language as powerful as
|
|
|
3269 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">’s†
|
|
|
3270 |
</span></p><p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.50in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3271 |
<span style="font-size: 10pt">is essential to
|
|
|
3272 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3273 |
success.
|
|
|
3274 |
When
|
|
|
3275 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3276 |
was first made available to the
|
|
|
3277 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3278 |
community,
|
|
|
3279 |
almost everyone switched to it within two or three days.
|
|
|
3280 |
In the months that followed, even people who had never adopted
|
|
|
3281 |
</span><span style="font-size: 10pt"><tt>jim</tt></span><span style="font-size: 10pt">
|
|
|
3282 |
started using
|
|
|
3283 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3284 |
exclusively.
|
|
|
3285 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3286 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3287 |
<span style="font-size: 10pt">To be honest,
|
|
|
3288 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
3289 |
still gets occasional use, but usually when
|
|
|
3290 |
something quick needs to be done and the overhead of
|
|
|
3291 |
downloading the terminal part of
|
|
|
3292 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3293 |
isn’t worth the trouble.
|
|
|
3294 |
Also, as a ‘line’ editor,
|
|
|
3295 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3296 |
</span><span style="font-size: 10pt"><tt>-d</tt></span><span style="font-size: 10pt">
|
|
|
3297 |
is a bit odd;
|
|
|
3298 |
when using a good old ASCII terminal, it’s comforting to have
|
|
|
3299 |
a true line editor.
|
|
|
3300 |
But it is fair to say that
|
|
|
3301 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3302 |
command language has displaced
|
|
|
3303 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">’s
|
|
|
3304 |
for most of the complicated editing that has kept line editors
|
|
|
3305 |
(that is, command-driven editors) with us.
|
|
|
3306 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3307 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3308 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3309 |
command language is even fancier than
|
|
|
3310 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">’s,
|
|
|
3311 |
and most
|
|
|
3312 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3313 |
customers don’t come near to using all its capabilities.
|
|
|
3314 |
Does it need to be so sophisticated?
|
|
|
3315 |
I think the answer is yes, for two reasons.
|
|
|
3316 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3317 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3318 |
<span style="font-size: 10pt">First, the
|
|
|
3319 |
</span><span style="font-size: 10pt"><i>model</i></span><span style="font-size: 10pt">
|
|
|
3320 |
for
|
|
|
3321 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3322 |
command language is really relatively simple, and certainly simpler than that of
|
|
|
3323 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">.
|
|
|
3324 |
For instance, there is only one kind of textual loop in
|
|
|
3325 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3326 |
— the
|
|
|
3327 |
</span><span style="font-size: 10pt"><tt>x</tt></span><span style="font-size: 10pt">
|
|
|
3328 |
command —
|
|
|
3329 |
while
|
|
|
3330 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
3331 |
has three (the
|
|
|
3332 |
</span><span style="font-size: 10pt"><tt>g</tt></span><span style="font-size: 10pt">
|
|
|
3333 |
command, the global flag on substitutions, and the implicit loop over
|
|
|
3334 |
lines in multi-line substitutions).
|
|
|
3335 |
Also,
|
|
|
3336 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">’s
|
|
|
3337 |
substitute command is necessary to make changes within lines, but in
|
|
|
3338 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3339 |
the
|
|
|
3340 |
</span><span style="font-size: 10pt"><tt>s</tt></span><span style="font-size: 10pt">
|
|
|
3341 |
command is more of a familiar convenience than a necessity;
|
|
|
3342 |
</span><span style="font-size: 10pt"><tt>c</tt></span><span style="font-size: 10pt">
|
|
|
3343 |
and
|
|
|
3344 |
</span><span style="font-size: 10pt"><tt>t</tt></span><span style="font-size: 10pt">
|
|
|
3345 |
can do all the work.
|
|
|
3346 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3347 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3348 |
<span style="font-size: 10pt">Second,
|
|
|
3349 |
given a community that expects an editor to be about as powerful as
|
|
|
3350 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">,
|
|
|
3351 |
it’s hard to see how
|
|
|
3352 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3353 |
could really be much simpler and still satisfy that expectation.
|
|
|
3354 |
People want to do ‘‘global substitutes,’’ and most are content
|
|
|
3355 |
to have the recipe for that and a few other fancy changes.
|
|
|
3356 |
The sophistication of the command language is really just a veneer
|
|
|
3357 |
over a design that makes it possible to do global substitutes
|
|
|
3358 |
in a screen editor.
|
|
|
3359 |
Some people will always want something more, however, and it’s gratifying to
|
|
|
3360 |
be able to provide it.
|
|
|
3361 |
The real power of
|
|
|
3362 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3363 |
command language comes from composability of the operators, which is by
|
|
|
3364 |
nature orthogonal to the underlying model.
|
|
|
3365 |
In other words,
|
|
|
3366 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3367 |
is not itself complex, but it makes complex things possible.
|
|
|
3368 |
If you don’t want to do anything complex, you can ignore the
|
|
|
3369 |
complexity altogether, and many people do so.
|
|
|
3370 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3371 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3372 |
<span style="font-size: 10pt">Sometimes I am asked the opposite question: why didn’t I just make
|
|
|
3373 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3374 |
a real programmable editor, with macros and variables and so on?
|
|
|
3375 |
The main reason is a matter of taste: I like the editor
|
|
|
3376 |
to be the same every time I use it.
|
|
|
3377 |
There is one technical reason, though:
|
|
|
3378 |
programmability in editors is largely a workaround for insufficient
|
|
|
3379 |
interactivity.
|
|
|
3380 |
Programmable editors are used to make particular, usually short-term,
|
|
|
3381 |
things easy to do, such as by providing shorthands for common actions.
|
|
|
3382 |
If things are generally easy to do in the first place,
|
|
|
3383 |
shorthands are not as helpful.
|
|
|
3384 |
</span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
3385 |
makes common editing operations very easy, and the solutions to
|
|
|
3386 |
complex editing problems seem commensurate with the problems themselves.
|
|
|
3387 |
Also, the ability to edit the
|
|
|
3388 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3389 |
window makes it easy to repeat commands — it only takes a mouse button click
|
|
|
3390 |
to execute a command again.
|
|
|
3391 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
3392 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3393 |
<span style="font-size: 10pt"><b>Pros and cons
|
|
|
3394 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3395 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3396 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
3397 |
has several other good points,
|
|
|
3398 |
and its share of problems.
|
|
|
3399 |
Among the good things is the idea of
|
|
|
3400 |
structural regular expressions,
|
|
|
3401 |
whose usefulness has only begun to be explored.
|
|
|
3402 |
They were arrived at serendipitously when I attempted to distill the essence of
|
|
|
3403 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">’s
|
|
|
3404 |
way of doing global substitution and recognized that the looping command in
|
|
|
3405 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
3406 |
was implicitly imposing a structure (an array of lines) on the file.
|
|
|
3407 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3408 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3409 |
<span style="font-size: 10pt">Another of
|
|
|
3410 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3411 |
good things is its undo capability.
|
|
|
3412 |
I had never before used an editor with a true undo,
|
|
|
3413 |
but I would never go back now.
|
|
|
3414 |
Undo
|
|
|
3415 |
</span><span style="font-size: 10pt"><i>must</i></span><span style="font-size: 10pt">
|
|
|
3416 |
be done well, but if it is, it can be relied on.
|
|
|
3417 |
For example,
|
|
|
3418 |
it’s safe to experiment if you’re not sure how to write some intricate command,
|
|
|
3419 |
because if you make a mistake, it can be fixed simply and reliably.
|
|
|
3420 |
I learned two things about undo from writing
|
|
|
3421 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">:
|
|
|
3422 |
first, it’s easy to provide if you design it in from the beginning, and
|
|
|
3423 |
second, it’s necessary, particularly if the system has some subtle
|
|
|
3424 |
properties that may be unfamiliar or error-prone for users.
|
|
|
3425 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3426 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3427 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3428 |
lack of internal limits and sizes is a virtue.
|
|
|
3429 |
Because it avoids all fixed-size tables and data structures,
|
|
|
3430 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3431 |
is able to make global changes to files that some of our other
|
|
|
3432 |
tools cannot even read.
|
|
|
3433 |
Moreover, the design keeps the performance linear when doing such
|
|
|
3434 |
operations, although I must admit
|
|
|
3435 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3436 |
does get slow when editing a huge file.
|
|
|
3437 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3438 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3439 |
<span style="font-size: 10pt">Now, the problems.
|
|
|
3440 |
Externally, the most obvious is that it is poorly integrated into the
|
|
|
3441 |
surrounding window system.
|
|
|
3442 |
By design, the user interface in
|
|
|
3443 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3444 |
feels almost identical to that of
|
|
|
3445 |
</span><span style="font-size: 10pt"><tt>mux</tt></span><span style="font-size: 10pt">,
|
|
|
3446 |
but a thick wall separates text in
|
|
|
3447 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3448 |
from the programs running in
|
|
|
3449 |
</span><span style="font-size: 10pt"><tt>mux</tt></span><span style="font-size: 10pt">.
|
|
|
3450 |
For instance, the ‘snarf buffer’ in
|
|
|
3451 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3452 |
must be maintained separately from that in
|
|
|
3453 |
</span><span style="font-size: 10pt"><tt>mux</tt></span><span style="font-size: 10pt">.
|
|
|
3454 |
This is regrettable, but probably necessary given the unusual configuration
|
|
|
3455 |
of the system, with a programmable terminal on the far end of an RS-232 link.
|
|
|
3456 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3457 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3458 |
<span style="font-size: 10pt"></span><span style="font-size: 10pt"><tt>Sam</tt></span><span style="font-size: 10pt">
|
|
|
3459 |
is reliable; otherwise, people wouldn’t use it.
|
|
|
3460 |
But it was written over such a long time, and has so many new (to me)
|
|
|
3461 |
ideas in it, that I would like to see it done over again to clean
|
|
|
3462 |
up the code and remove many of the lingering problems in the implementation.
|
|
|
3463 |
The worst part is in the interconnection of the host and terminal parts,
|
|
|
3464 |
which might even be able to go away in a redesign for a more
|
|
|
3465 |
conventional window system.
|
|
|
3466 |
The program must be split in two to use the terminal effectively,
|
|
|
3467 |
but the low bandwidth of the connection forces the separation to
|
|
|
3468 |
occur in an inconvenient part of the design if performance is to be acceptable.
|
|
|
3469 |
A simple remote procedure call
|
|
|
3470 |
protocol driven by the host, emitting only graphics
|
|
|
3471 |
commands, would be easy to write but wouldn’t have nearly the
|
|
|
3472 |
necessary responsiveness. On the other hand, if the terminal were in control
|
|
|
3473 |
and requested much simpler file services from the host, regular expression
|
|
|
3474 |
searches would require that the terminal read the entire file over its RS-232
|
|
|
3475 |
link, which would be unreasonably slow.
|
|
|
3476 |
A compromise in which either end can take control is necessary.
|
|
|
3477 |
In retrospect, the communications protocol should have been
|
|
|
3478 |
designed and verified formally, although I do not know of any tool
|
|
|
3479 |
that can adequately relate the protocol to
|
|
|
3480 |
its implementation.
|
|
|
3481 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3482 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3483 |
<span style="font-size: 10pt">Not all of
|
|
|
3484 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3485 |
users are comfortable with its command language, and few are adept.
|
|
|
3486 |
Some (venerable) people use a sort of
|
|
|
3487 |
‘‘</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
3488 |
subset’’ of
|
|
|
3489 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3490 |
command language,
|
|
|
3491 |
and even ask why
|
|
|
3492 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3493 |
command language is not exactly
|
|
|
3494 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">’s.
|
|
|
3495 |
(The reason, of course, is that
|
|
|
3496 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3497 |
model for text does not include newlines, which are central to
|
|
|
3498 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">.
|
|
|
3499 |
Making the text an array of newlines to the command language would
|
|
|
3500 |
be too much of a break from the seamless model provided by the mouse.
|
|
|
3501 |
Some editors, such as
|
|
|
3502 |
</span><span style="font-size: 10pt"><tt>vi</tt></span><span style="font-size: 10pt">,
|
|
|
3503 |
are willing to make this break, though.)
|
|
|
3504 |
The difficulty is that
|
|
|
3505 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">’s
|
|
|
3506 |
syntax is so close to
|
|
|
3507 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">’s
|
|
|
3508 |
that people believe it
|
|
|
3509 |
</span><span style="font-size: 10pt"><i>should</i></span><span style="font-size: 10pt">
|
|
|
3510 |
be the same.
|
|
|
3511 |
I thought, with some justification in hindsight,
|
|
|
3512 |
that making
|
|
|
3513 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3514 |
similar to
|
|
|
3515 |
</span><span style="font-size: 10pt"><tt>ed</tt></span><span style="font-size: 10pt">
|
|
|
3516 |
would make it easier to learn and to accept.
|
|
|
3517 |
But I may have overstepped and raised the users’
|
|
|
3518 |
expectations too much.
|
|
|
3519 |
It’s hard to decide which way to resolve this problem.
|
|
|
3520 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3521 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.35in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3522 |
<span style="font-size: 10pt">Finally, there is a tradeoff in
|
|
|
3523 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3524 |
that was decided by the environment in which it runs:
|
|
|
3525 |
</span><span style="font-size: 10pt"><tt>sam</tt></span><span style="font-size: 10pt">
|
|
|
3526 |
is a multi-file editor, although in a different system there might instead be
|
|
|
3527 |
multiple single-file editors.
|
|
|
3528 |
The decision was made primarily because starting a new program in a Blit is
|
|
|
3529 |
time-consuming.
|
|
|
3530 |
If the choice could be made freely, however, I would
|
|
|
3531 |
still choose the multi-file architecture, because it allows
|
|
|
3532 |
groups of files to be handled as a unit;
|
|
|
3533 |
the usefulness of the multi-file commands is incontrovertible.
|
|
|
3534 |
It is delightful to have the source to an entire program
|
|
|
3535 |
available at your fingertips.
|
|
|
3536 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
3537 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3538 |
<span style="font-size: 10pt"><b>Acknowledgements
|
|
|
3539 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3540 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3541 |
<span style="font-size: 10pt">Tom Cargill suggested the idea behind the
|
|
|
3542 |
</span><span style="font-size: 10pt"><tt>Rasp</tt></span><span style="font-size: 10pt">
|
|
|
3543 |
data structure.
|
|
|
3544 |
Norman Wilson and Ken Thompson influenced the command language.
|
|
|
3545 |
This paper was improved by comments from
|
|
|
3546 |
Al Aho,
|
|
|
3547 |
Jon Bentley,
|
|
|
3548 |
Chris Fraser,
|
|
|
3549 |
Gerard Holzmann,
|
|
|
3550 |
Brian Kernighan,
|
|
|
3551 |
Ted Kowalski,
|
|
|
3552 |
Doug McIlroy
|
|
|
3553 |
and
|
|
|
3554 |
Dennis Ritchie.
|
|
|
3555 |
</span></p><p style="margin-top: 0; margin-bottom: 0.17in"></p>
|
|
|
3556 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3557 |
<span style="font-size: 10pt"><b>REFERENCES
|
|
|
3558 |
</b></span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3559 |
<p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3560 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3561 |
<span style="font-size: 10pt"> 1. R. Pike,
|
|
|
3562 |
‘The Blit: a multiplexed graphics terminal,’
|
|
|
3563 |
</span><span style="font-size: 10pt"><i>AT&T Bell Labs. Tech. J.,
|
|
|
3564 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>63</b></span><span style="font-size: 10pt">,
|
|
|
3565 |
(8),
|
|
|
3566 |
1607-1631 (1984).
|
|
|
3567 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3568 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3569 |
<span style="font-size: 10pt"> 2. L. Johnson,
|
|
|
3570 |
</span><span style="font-size: 10pt"><i>MacWrite,</i></span><span style="font-size: 10pt">
|
|
|
3571 |
Apple Computer Inc., Cupertino, Calif. 1983.
|
|
|
3572 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3573 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3574 |
<span style="font-size: 10pt"> 3. B. Lampson,
|
|
|
3575 |
‘Bravo Manual,’
|
|
|
3576 |
in
|
|
|
3577 |
</span><span style="font-size: 10pt"><i>Alto User’s Handbook,
|
|
|
3578 |
</i></span><span style="font-size: 10pt">pp. 31-62,
|
|
|
3579 |
Xerox Palo Alto Research Center,
|
|
|
3580 |
Palo Alto, Calif.
|
|
|
3581 |
1979.
|
|
|
3582 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3583 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3584 |
<span style="font-size: 10pt"> 4. W. Teitelman,
|
|
|
3585 |
‘A tour through Cedar,’
|
|
|
3586 |
</span><span style="font-size: 10pt"><i>IEEE Software,
|
|
|
3587 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>1</b></span><span style="font-size: 10pt">
|
|
|
3588 |
(2), 44-73 (1984).
|
|
|
3589 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3590 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3591 |
<span style="font-size: 10pt"> 5. J. Gutknecht,
|
|
|
3592 |
‘Concepts of the text editor Lara,’
|
|
|
3593 |
</span><span style="font-size: 10pt"><i>Comm. ACM,
|
|
|
3594 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>28</b></span><span style="font-size: 10pt">,
|
|
|
3595 |
(9),
|
|
|
3596 |
942-960 (1985).
|
|
|
3597 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3598 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3599 |
<span style="font-size: 10pt"> 6. Bell Telephone Laboratories,
|
|
|
3600 |
</span><span style="font-size: 10pt"><i>UNIX Programmer’s Manual,
|
|
|
3601 |
</i></span><span style="font-size: 10pt">Holt, Rinehart and Winston, New York 1983.
|
|
|
3602 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3603 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3604 |
<span style="font-size: 10pt"> 7. B. W. Kernighan and R. Pike,
|
|
|
3605 |
</span><span style="font-size: 10pt"><i>The Unix Programming Environment,
|
|
|
3606 |
</i></span><span style="font-size: 10pt">Prentice-Hall, Englewood Cliffs, New Jersey 1984.
|
|
|
3607 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3608 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3609 |
<span style="font-size: 10pt"> 8. </span><span style="font-size: 10pt"><i>Unix Time-Sharing System Programmer’s Manual, Research Version, Ninth Edition,
|
|
|
3610 |
Volume 1,
|
|
|
3611 |
</i></span><span style="font-size: 10pt">AT&T Bell Laboratories, Murray Hill, New Jersey 1986.
|
|
|
3612 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3613 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3614 |
<span style="font-size: 10pt"> 9. </span><span style="font-size: 10pt"><i>Unix Time-Sharing System Programmer’s Manual, 4.1 Berkeley Software Distribution,
|
|
|
3615 |
Volumes 1 and 2C,
|
|
|
3616 |
</i></span><span style="font-size: 10pt">University of California, Berkeley, Calif. 1981.
|
|
|
3617 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3618 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3619 |
<span style="font-size: 10pt">10. R. Pike,
|
|
|
3620 |
‘Structural Regular Expressions,’
|
|
|
3621 |
</span><span style="font-size: 10pt"><i>Proc. EUUG Spring Conf., Helsinki 1987,
|
|
|
3622 |
</i></span><span style="font-size: 10pt">Eur. Unix User’s Group, Buntingford, Herts, UK 1987.
|
|
|
3623 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3624 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3625 |
<span style="font-size: 10pt">11. A. Goldberg,
|
|
|
3626 |
</span><span style="font-size: 10pt"><i>Smalltalk-80 – The Interactive Programming Environment,
|
|
|
3627 |
</i></span><span style="font-size: 10pt">Addison-Wesley, Reading, Mass. 1984.
|
|
|
3628 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3629 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3630 |
<span style="font-size: 10pt">12. K. Thompson,
|
|
|
3631 |
‘Regular expression search algorithm,’
|
|
|
3632 |
</span><span style="font-size: 10pt"><i>Comm. ACM,
|
|
|
3633 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>11</b></span><span style="font-size: 10pt">,
|
|
|
3634 |
(6),
|
|
|
3635 |
419-422 (1968).
|
|
|
3636 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3637 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3638 |
<span style="font-size: 10pt">13. A. V. Aho, J. E. Hopcroft and J. D. Ullman,
|
|
|
3639 |
</span><span style="font-size: 10pt"><i>The Design and Analysis of Computer Algorithms,
|
|
|
3640 |
</i></span><span style="font-size: 10pt">Addison-Wesley, Reading, Mass. 1974.
|
|
|
3641 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3642 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3643 |
<span style="font-size: 10pt">14. B. W. Kernighan and D. M. Ritchie,
|
|
|
3644 |
</span><span style="font-size: 10pt"><i>The C Programming Language,
|
|
|
3645 |
</i></span><span style="font-size: 10pt">Prentice-Hall, Englewood Cliffs, New Jersey 1978.
|
|
|
3646 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3647 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3648 |
<span style="font-size: 10pt">15. W. M. Waite,
|
|
|
3649 |
‘The cost of lexical analysis,’
|
|
|
3650 |
</span><span style="font-size: 10pt"><i>Softw. Pract. Exp.,
|
|
|
3651 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>16</b></span><span style="font-size: 10pt">,
|
|
|
3652 |
(5),
|
|
|
3653 |
473-488 (1986).
|
|
|
3654 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3655 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3656 |
<span style="font-size: 10pt">16. C. W. Fraser,
|
|
|
3657 |
‘A generalized text editor,’
|
|
|
3658 |
</span><span style="font-size: 10pt"><i>Comm. ACM,
|
|
|
3659 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>23</b></span><span style="font-size: 10pt">,
|
|
|
3660 |
(3),
|
|
|
3661 |
154-158 (1980).
|
|
|
3662 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3663 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3664 |
<span style="font-size: 10pt">17. R. Pike,
|
|
|
3665 |
‘Graphics in overlapping bitmap layers,’
|
|
|
3666 |
</span><span style="font-size: 10pt"><i>ACM Trans. on Graph.,
|
|
|
3667 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>2</b></span><span style="font-size: 10pt">,
|
|
|
3668 |
(2)
|
|
|
3669 |
135-160 (1983).
|
|
|
3670 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3671 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3672 |
<span style="font-size: 10pt">18. L. J. Guibas and J. Stolfi,
|
|
|
3673 |
‘A language for bitmap manipulation,’
|
|
|
3674 |
</span><span style="font-size: 10pt"><i>ACM Trans. on Graph.,
|
|
|
3675 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>1</b></span><span style="font-size: 10pt">,
|
|
|
3676 |
(3),
|
|
|
3677 |
191-214 (1982).
|
|
|
3678 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3679 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3680 |
<span style="font-size: 10pt">19. R. Pike, B. Locanthi and J. Reiser,
|
|
|
3681 |
‘Hardware/software trade-offs for bitmap graphics on the Blit,’
|
|
|
3682 |
</span><span style="font-size: 10pt"><i>Softw. Pract. Exp.,
|
|
|
3683 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>15</b></span><span style="font-size: 10pt">,
|
|
|
3684 |
(2),
|
|
|
3685 |
131-151 (1985).
|
|
|
3686 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3687 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3688 |
<span style="font-size: 10pt">20. T. A. Cargill,
|
|
|
3689 |
‘The feel of Pi,’
|
|
|
3690 |
</span><span style="font-size: 10pt"><i>Winter USENIX Conference Proceedings,
|
|
|
3691 |
Denver 1986,
|
|
|
3692 |
</i></span><span style="font-size: 10pt">62-71,
|
|
|
3693 |
USENIX Assoc., El Cerrito, CA.
|
|
|
3694 |
</span></p><p style="margin-top: 0; margin-bottom: 0.05in"></p>
|
|
|
3695 |
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: justify;">
|
|
|
3696 |
<span style="font-size: 10pt">21. G. J. Holzmann,
|
|
|
3697 |
‘Tracing protocols,’
|
|
|
3698 |
</span><span style="font-size: 10pt"><i>AT&T Tech. J.,
|
|
|
3699 |
</i></span><span style="font-size: 10pt"></span><span style="font-size: 10pt"><b>64</b></span><span style="font-size: 10pt">,
|
|
|
3700 |
(10),
|
|
|
3701 |
2413-2434 (1985).
|
|
|
3702 |
</span></p><p style="margin-top: 0; margin-bottom: 0.50in"></p>
|
|
|
3703 |
</body>
|
|
|
3704 |
</html>
|
|
|
3705 |
|