-
Notifications
You must be signed in to change notification settings - Fork 83
/
tecman.20
executable file
·5310 lines (4572 loc) · 223 KB
/
tecman.20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
This file will be an interm on-line INFO file for TECO. -*-Text-*-
File: TECMAN Node: Top Up: (DIR)
TECO, the Text Editor and Corrector, is both a text editor, and a
language designed for the creation of higher level editing systems, such
as EMACS, INFO, and RMAIL.
Unfortunately, there is no on-line tutorial at this time. If you want to
go hunting, somewhere around the ninth floor there is a thick velobound
manual which someone produced by adapting DEC's TECO manual (fourteen
years out of date) to the then-current version. It's on blue paper, and
seems to have been printed on an impact printer of some type. I saw it
last in CADR-1's room (907). If anyone knows the whereabouts of a tape,
please let us know!
What on-line documentation there is now exists in two forms:
* Menu:
* Ascii: (.TECO.;TECORD >)*
A complete listing of TECO commands, in ASCII order.
Usually requires use of an editor to find the entry
you're looking for. Most useful when attempting to
understand another user's TECO code. ("What does this
mean?")
* Concept:: The same data, resorted roughly by kind of command
(editing, variables, mathematics, environmental, and so
on. Refer to this section when you are writing new code.
("How can I do this?")
Two abortive attempts have been made recently to produce a TECO tutorial manual.
These are:
* JKESS: (MC:.teco.;jkess info)Top
* KMP: (MC:.teco.;kmp info)Top
Also worth looking at:
* Brief: (MC:.teco.;teco primer)*
File: TECMAN Node: Concept Up: Top
At this time, these topics are not perfectly seperated. In many cases, a
command could have been listed under several topics, and the decision
was based on how I most often used it. If you don't find what you're
looking for, be creative in guessing where else I might have put it. If
all else fails, read .TECO.;TECORD > into EMACS, and try using search
commands to look for it.
* Menu: The current topics are:
* Functions:: All commands which are used to obtain a value without
modifying TECOs state. Specifically, values referring to
locations in the editing buffer (in terms of characters,
lines, words, LISP constructs and parentheses), the
characters in the buffer, string comparison and
examination, a random number generator, conversions
(ASCII/SAIL/sixbit character sets), arguments passed to
a TECO Macro, and so on.
* Background:: General information about TECOs behavior. Init files,
Journal files, data structure descriptions and internal
formats, character sets, how to control TECO from other
programs, neat programming hacks, debugging aids, and
proposed TECO program standards.
* Fancy:: High-powered commands: Sorting, command dispatching,
LISP parsing, variable table hacking, text processing
(justification etc.).
* Deletion:: How to delete characters from the buffer.
* Real-time:: "Real-time", or dynamic, command recognition. This is
the system upon which EMACS is built. Also known as
"^R-mode TECO".
* Files:: How to read and write files; reading and modifying
directories, Journal and Dump files, and I/O channel
manipulation.
* Named:: Analogous to EMACS' MM commands. These are commands
which, while indespensable when needed, are not used
often enough to warrent a one- or two-character name.
Mostly environmental control variables. They are
accessed via the FS command prefix. If you can't find it
anywhere else, it's probably here.
* Flow:: Program flow control: Branching, loops, conditionals,
error traps, lisp-like "throw" and "catch".
* Insertion:: Inserting characters into, and "writing over", the
editing buffer and other data structures.
* Math:: Mathematical and boolean operators. Note that booleans
operate bitwise on data.
* Motion:: How to get to the desired editing location, either
explicitly by searching the buffer (and clean-up
operations after searching), recovering automatically
stored records of past locations, screen-oriented
actions.
* Variables:: Q-registers (built-in and user-defined) are the most
commonly-used "variable" in TECO. They can hold text,
numeric values, or an entire editing buffer. Text can be
executed as a TECO command string (a TECO Macro, or
program). A push-down list (stack) exists. This section
also contains documentation of the special-purpose "..n"
Q-registers.
* Syntax:: Commands related to TECO syntax. How to execute a
command; how to abort one; exiting TECO; error recovery
and debugging commands; sleeping; comments and other
command format questions; case conversion; communicating
with other programs; error messages.
* TTY:: Commands for reading from and outputting to the user's
terminal, and controlling the format of these actions.
* Valret:: Invoking other programs from within TECO.
File: TECMAN Node: Functions Up: Concept
TECO COMMANDS: ARGUMENTS -- basicly, all commands which are FUNCTIONS --
that is, return a value without otherwise changing the system's state.
>>>>>>>>>>>>>>>>>>>> Buffer Position Values <<<<<<<<<<<<<<<<<<<<
. equals the number of chars to left of the pointer.
B normally 0. Actually, the number of the first character
within the virtual buffer boundaries - but that will be
the first char in the buffer (char number 0) unless you
have used FS BOUND or FS V B to change that.
Z val=number of chars in buffer (more generally, the
character number of the virtual end of the buffer,
if virtual buffer boundaries are in use).
H equivalent to B,Z; i.e., specifies whole buffer
(or all within the virtual boundaries if they're in use)
to commands taking two args for character positions such as
K, T, or V.
<n>^@ for nonnegative <n>, is the same as ".,.+<n>".
For negative <n>, is the same as ".+<n>,.".
"10^@XA" puts the 10 characters after the pointer
in a string in qreg A.
>>>>>>>>>>>>>>>>>>>> Buffer position in LINES <<<<<<<<<<<<<<<<<<<<
<n>F^@ returns, in numerical order, 2 args that delimit a range
of the buffer extending <n> lines from the pointer.
Thus, "<n>F^@T" is the same as "<n>T".
<n>@F^@
is like <n>F^@ but treats in CRLFs, not just CRs.
>>>>>>>>>>>>>>>>>>>> Buffer position in LISP <<<<<<<<<<<<<<<<<<<<
<arg>FL a list maniulating command, that returns 2 values specifying
a range of the buffer. If <arg> is >0, the range
returned is that containing the next <arg> lists
to the right of the pointer; if <arg> is <0,
the range is that containing <arg> lists
to the left of the pointer. This command should be
followed by a command such as K, T, X, FX ...
which can take 2 args; the specified number of lists
will be deleted, typed, put in q-reg, etc.
To move to the other side of the lists, do "<arg>FLL".
The syntax parsed by FL is controlled by the delimiter
dispatch table in Q..D; the character types known
are "A", " ", "|", "/", "(", ")" and "'", and any character
can be redefined to be of any of those types.
:FL is like FL, but stops before the ( that starts the list
instead of after. -:FL stops after the ), etc.
<arg> @FL
is like "<arg>FL", but refers to <arg> s-expressions
rather than <arg> lists. An s-expression is either
a list or a LISP atom, whichever is encountered first.
"@FW" is used to find LISP atoms when necessary.
@:FL stops before the next s-expression - if it is a list,
it stops before the (, and if it is quoted it stops before
the quote.
>>>>>>>>>>>>>>>>>>>> Buffer position in PARENS <<<<<<<<<<<<<<<<<<<<
FU a list manipulating command whose main use
is in <arg>FUL, which moves up <arg> levels of parentheses.
<arg>FU where <arg> is positive returns a pair of args for
the next command, specifying the range of the buffer from .
Moving rightward to the first place <arg> levels up.
If <arg> is negative, it moves left -<arg> levels up.
>>>>>>>>>>>>>>>>>>>> Buffer position in WORDS <<<<<<<<<<<<<<<<<<<<
FW similar to FL but hacks words instead.
A word is defined as a sequence of non-delimiters.
Initially, the non-delimiters are just the squoze
characters but the user can change that - see q-reg ..D.
This command returns a pair of args for the next one.
Also, FW sets FS INSLEN equal to the length of the
last word moved over.
Main uses: FWL moves right one word,
-FWL moves left one, FWK deletes one word to the right,
FWFXA deletes and puts in q-reg A,
FWFC converts one word to lower case.
:FW similar to FW but stops before crossing the word instead
of after. Thus, :1FWL moves up to before the next
non-delimiter. :2FWL is the same as 2FWL-FWL.
:FW sets FS INSLEN to the length of the last inter-word
gap crossed.
@FW like FW, but finds LISP atoms rather than words.
Understands slashes and vertical bars but not comments.
>>>>>>>>>>>>>>>>>>>> Numerical Functions <<<<<<<<<<<<<<<<<<<<
^Z normally causes an interrupt to DDT when typed.
However, one can be given to TECO by quoting it
with ^_ , in which case it is a normal command:
with no arg, its value is a pseudo-random number.
>>>>>>>>>>>>>>>>>>>> Examining buffer <<<<<<<<<<<<<<<<<<<<
<n>A value is the 7-bit ASCII value of char arg chars
to the right of the pointer. Note that
"0A" is the character immediately to the left of
the pointer and "-<n>A" is the character <n>+1
characters left of the pointer. If .+<n>-1 is not
within the bounds (real or virtual) of the buffer, a
"NIB" error occurs.
<m>,<n>A
is like <n>A except that when <n>A would cause a
"NIB" error, <m>,<n>A will return <m>. Thus,
13,1A will return 13 iff the pointer is either at the
end of the buffer or before a carriage return.
\ If no arg, converts digits in the buffer to a number. Value is
the number represented as decimal digits to right of pointer
in buffer (actually, the input radix comes from FS IBASE, as
with numbers in commands).
:\ allows an optional minus sign.
Moves pointer to right of number.
<n>:\ returns a string containing the printed representation of
<n>, in the radix in ..E. Sets FS INSLEN.
<m>,<n>:\
makes a <m> character string, with leading spaces.
>>>>>>>>>>>>>>>>>>>> Arguments to Macros <<<<<<<<<<<<<<<<<<<<
^X only defined inside macro. Its value is the
first arg of the M command which called the macro.
See the F^X command for a more sophisticated
way for macros to examine their arguments.
^Y like ^X, only second or only arg of the M command.
:F^K can be used by a macro to tell whether it was called from
the internals of TECO or from another macro. It returns -1
if the macro was called from the internals of TECO or was
called with @M. Otherwise, it returns a positive number.
F^X within a macro, this command returns as its values the
arguments that were given to the macro. As many values
are returned as args were given. To find out how many
there were, use F^Y.
F^Y returns a value saying how many args it was given. For
example, WF^Y returns 0; W1F^Y, 1; W1,F^Y, 2; W1,2F^Y, 3.
The : and @ flags are also indicated by bits in the value;
:F^Y returns 4 and @F^Y returns 8. 1,2:@F^Y returns 15.
The modifier flags, and the previous arguments, are flushed.
>>>>>>>>>>>>>>>>>>>> String-handling Functions <<<<<<<<<<<<<<<<<<<<
F^B:
<ch>F^B<string>
searches for the character <ch> in <string>. <ch> should
be the ASCII code for a character. If that character
does not occur in <string>, -1 will be returned. If the
char does occur, the value will be the position of its
first occurrence (eg., 0 if it is the first char).
<pos>,<ch>F^B<string>
is like <ch>F^B but searches starting at position <pos>
in the string. If no occurrence is found past there, the
value is -1.
F* reads and ignores a string argument. Useful in macros
because "F*^]^X" reads and ignores a string argument
passed to the macro.
F= does an ordered comparison of strings.
If "F=" has numeric args, they specify the range of buffer
to be used as the first comparison string. Otherwise,
the "=" should be followed by the name of a q-reg which
should hold the first comparison string.
The second comparison string should follow the command as
a string argument, as for the "I" command. (the @ modifier
works just as it does for the "I" command)
the two strings are compared, and if they are equal
0 is returned as the value of the "F=" command.
If the first string is greater, a positive value
is returned; if the second, a negative value.
If the value isn't 0, its absolute value is 1 +
the position in the string of the first difference
(1 if the first characters differ, etc.).
A string is considered to be
greater than any of its initial segments.
F~ compares strings, ignoring case difference. It is just
like F= except that both strings are converted to upper
case as they are compared.
>>>>>>>>>>>>>>>>>>>> Conversions <<<<<<<<<<<<<<<<<<<<
<n>F(<m>)
converts <n> feet <m> inches to inches.
^^<char>
(ctl caret) has the value of the 7-bit ASCII
code for <char>.
F6<string>
returns a word of SIXBIT containing the first six
characters of <string>.
<sixbit>F6
interpreting <sixbit> as a word of SIXBIT, converts
it to ASCII which is then inserted in the buffer
before the pointer.
<sixbit>: F6
returns a string containing the characters of <sixbit>.
@F6 is an obsolete equivalent command.
<ch>:FC returns the upper-case equivalent of the character whose
numeric code is <ch>, as a numeric code. Meta-bits in
<ch> are passed through unchanged.
:FC may also be given a string pointer as argument.
It returns a new string containing the upper-case of its
argument.
>>>>>>>>>>>>>>>>>>>> Q-Reg related <<<<<<<<<<<<<<<<<<<<
F^^<^R-char>
F^^ takes the name of a ^R-character definition, as a
q-reg, and returns the 9-bit character code for the
character. For example, F^^.^R. returns the code for
Control-., which is 256 octal.
<string>:F^^
:F^^ is used to test whether a string contains a valid short
q-register name. The string is passed as a string pointer in
a prefix argument. If the string contains a short q-register
name then the :FS QP HOME of that q-register is returned.
Otherwise, zero is returned.
>>>>>>>>>>>>>>>>>>>> "Searching" the buffer <<<<<<<<<<<<<<<<<<<<
@F^B<string>
searches the buffer from point forward for a character
NOT belonging to <string>, and then returns
.,<address of that character>. If such a character is not
found, .,Z is returned.
-@F^B<string>
searches the buffer backwards from point for a character
NOT belonging to <string>, and then returns
<address of that character>,<point>. If no such character
is found, B,. is returned.
<x>,<y>@F^B<string>
searches the buffer from <x> to <y> (which can be either
forward or backward) for a character NOT belonging to
<string>, and then returns .,<address of character> or
<address of character>,., whichever puts the smaller
value first.
@:F^B<string>
is like @F^B with no colon except that it searches for
a character which IS a member of <string>. It takes the
same sorts of arguments that non-colon @F^B takes, and
returns the same sorts of values.
>>>>>>>>>>>>>>>>>>>> Searching other structures <<<<<<<<<<<<<<<<<<<<
F^S:
<m>,<n>F^S<q>
searches the buffer or word aligned string in <q> for a word
containing <n>, starting at word <m>. If one is found, its
index is returned; otherwise, -1 is the value. The index of
one occurrence can be used as <m> in the next call to find the
next occurrence.
<m>,<n>:F^S
searches the ^R character definition table instead of a buffer.
In other respects it is like F^S.
>>>>>>>>>>>>>>>>>>>> Other functions <<<<<<<<<<<<<<<<<<<<
FK returns minus the value of FS INSLEN; that is,
minus the length of the last string inserted by "I", "G" or
"\", or found by a search or "FW". FK is negative except
after a successful backward search, or backward "FW".
Thus, "SFOOFKC" will move to the beginning of the FOO found.
"-SFOOFKC" will move to the end of the FOO found.
See also the ^B command in this context.
"SFOOFKDIBAR" will replace FOO with BAR. See "^F".
"IBLETCHFKC" inserts BLETCH and backs over it.
EG is a semi-obsolete command for getting random info.
It inserts in buffer on successive lines
the current date (as YYMMDD),
the current time (as HHMMSS),
TECO's current sname,
TECO's default filenames for E-commands,
the real names of the file open for input
the date in text form,
a 3-digit value as follows:
1st digit = day of week today (0 = Sunday)
2nd digit = day of week of 1st day of year
3rd digit should be understood as binary:
4-bit = normal year, and after 2/28
2-bit = leap year
1-bit = daylight savings time in effect.
(this line is blank on Twenex)
and the phase of the moon.
There are better ways to get most of these things:
FS FD CONV, FS D FILE, FS D SNAME, FS I FILE.
File: TECMAN Node: Background Up: Concept
TECO COMMANDS: Background information.
Lower case letters are interpreted like upper case letters when they
are commands. Inside insert and search strings they are treated as
themselves.
When TECO is started for the first time,
it initializes various data areas,
prints its version number,
and initializes several flags associated with the terminal (by
executing FS TTY INIT).
If TECO was started at 2 + the normal starting address, FS
LISPT is set nonzero. Otherwise, it is set to 0.
In either case, TECO looks for a "TECO INIT" file (see below),
executing it as a program if it is found.
When TECO is restarted,
it does not clobber the buffer, q-regs or open files.
It does, however, execute FS TTY INIT which resets some flags
whose preferred setting depend on the type of terminal.
Then, it quits to top level and executes whatever is in q-reg
..L (unless it is 0).
Init files:
Whenever TECO is started for the first time, it checks for a file
<hsname>;<xuname> TECO, for a file <hsname>;* TECO, and then for the
file .TECO.;* TECO. The first one found is executed as TECO commands.
The last of those files is the default init file. The other two would
be personal init files. The personal init file can do whatever you
want. The only thing the default init file does is interpret command
lines from DDT as follows:
":TECO FOO BAR <cr>" typed at DDT causes
"ET FOO BAR EI ER Y" to be done by TECO --
that is, TECO starts editing FOO BAR.
":TECO FOO <cr>" edits FOO > .
Because COM:.TECO. (INIT) sets FS FNAMSY temporarily.
":TECO <filename><TECO commands> <cr>"
typed at DDT executes " ET <file> <commands> ".
A user's own init file should interpreted the JCL by reading it in
with the "FJ" command. It may have any command format it wishes
except that it should always respond to "<foo>;" in the JCL by
flushing the JCL (do "@^K^W:JCL<cr>P^V") and loading and executing
<foo>'s init file. See the default init file for how to do those
things.
Dumped macro packages runnable from DDT often also have init files.
Such packages should use FS XUNAME and FS HSNAME to determine init
file names the same way TECO does.
Journal Files
TECO can write a journal file describing all the commands typed by the
user. If the system crashes, the user can replay the journal file
later so that his work is not lost.
The TECO program starts writing a journal file by doing FS JRN OPEN.
This opens the file for output, using the default filenames. TECO
automatically writes into the file representations of all command
characters read from the terminal. To close the journal file, use :FS
JRN OPEN. To see whether a journal file is being written, look at
the value of FS JRN OUT (it is -1 in that case). Note that no output
is ever written in a journal file while another journal file is being
replayed.
The TECO program requests the replaying of a journal file by doing FS
JRN EXECUTE. This opens the file using the default filenames. When
TECO is ready to read more commands, they will be read from the
journal file until the file is exhausted, or the user types a ^G on
the terminal, or the TECO program does :FS JRN EXECUTE to close the
file. FS JRN IN is -1 when a journal file is being replayed.
Each command character is represented by a pair of characters in the
journal file. This is so that the Control and Meta bits can be
represented in full generality. A character with neither the Control
nor the Meta bit is represented in the journal file by a space
followed by the character itself. A Control character (200+nnn) is
represented by an "^" followed by the non-control character. A Meta
character (400+nnn) is represented by "+" followed by the non-meta
character. A Control-Meta character is represented by "*" followed by
the basic character. Thus, Meta-F is represented by "+F".
There are a few exceptions to the rule above. A CR character (015) is
represented by the two characters CRLF. This makes the journal file
look much nicer. The Help character is represented by "??".
Other constructs which can appear in a journal file are ^G (007) to
represent a quit command; comments, which start with semicolon and end
with CRLF, and are ignored when replaying the file; and program
commands, which start with a colon and whose format is up to the TECO
program. When a ^G or a colon is seen in a journal file being
replayed, the FS JRN MACRO is called, and given the character (^G or
colon) as an argument. In the case of ^G, the macro should do 1F[JRN
INHIBIT and then call ^R so that the user can fix up for any timing
errors that occurred in quitting, and when the ^R returns it should do
-1FS QUIT to replay the quit. Colon represents the start of
program-specific information; the program which wrote the journal file
and the one which replays it must agree on what format the following
information takes. The information can be read using the FS JRN READ
command.
One specific colon-sequence is defined by TECO: colon followed by a ^G
indicates a quit which happened synchronously, while TECO was waiting
for input. Such a quit does not need a recursive ^R for the user to
fix things up because everything is guaranteed correct. In this case,
the FS JRN MACRO should just replay the quit with -1FS QUIT.
Normally, journal files are written and read automatically. However,
the TECO program may wish to add extra information to the journal
file. This could be comments designed to aid humans who look at the
journal file, or it could be information intended to be used in
replaying the file properly. In that case, it should take the form of
a colon followed by information to be read in by FS JRN MACRO later.
In either case, the information is written by means of the FS JRN
WRITE command, which accepts a character or a string.
TECO's Data Structures (Strings, Buffers and Qvectors)
TECO has two different data structures for storing sequences of
characters: strings, and buffers. They differ in what operations are
allowed on them, and how efficient they are.
Strings have less overhead than buffers, but as a penalty they are
not easily altered. Once a string has been created, its contents
usually do not change; instead one might eventually discard the string
and create a new one with updated contents. The sole exception is
F^E, which makes it possible to alter characters in a string (but not
to insert or delete). Commands which "put text in a q-register" all
do so by consing up a string and putting a pointer to it in the
q-register.
Buffers are designed to be convenient for insertion and deletion.
Each buffer has its own pointer, and its own virtual buffer
boundaries, which are always associated with it. The contents of a
buffer can be accessed just like the contents of a string (in which
case only the part between the virtual boundaries is visible), but it
can also be "selected" and then accessed or altered in many other
ways: insertion, deletion, searching, etc. Each buffer also has a
flag which is set nonzero whenever the buffer's contents are changed;
it can also be set by the user with FS MODIFIED. A buffer has about
42 characters of overhead, and the number of buffers is limited (about
40). Initially, there is only one buffer in a TECO (pointers to which
are initially found in q-registers ..O and ..Z), and new ones are only
made when explicitly asked for with F[ B BIND, FS B CONS or FS B
CREATE.
Strings and buffers are normally represented in TECO by pointers.
When a q-register "contains" a string, it actually contains a pointer
to the string (see the sections on internal format for details). If
q-register A contains a string, QA returns the pointer, which can be
stored into q-register B; then QB and QA both point to the same
string. The command :I*<string> returns a pointer to a newly consed
up string containing <string>. :G can be used to extract a substring
(which is copied, not shared). The commands :\, :F6 and X* are also
useful for creating strings.
A buffer is selected by putting a copy of a pointer to it into
q-register ..O. TECO has a garbage collector, so that if all pointers
to a buffer or string are eliminated, the storage it occupies will
eventually be reclaimed. Most of the space occupied by a buffer can
be reclaimed explicitly with the FS B KILL command; the buffer is
becomes "dead", and even though pointers to it may still exist, any
attempt to use them to select the buffer or examine its contents will
be an error.
Vectors of objects can also be represented in TECO, with either
buffers or qvectors. Buffers can be used to as vectors of numbers,
while qvectors are used as vectors of arbitrary objects (numbers, or
pointers to strings, buffers or qvectors). The difference is due to
the fact that the garbage collector knows that the objects in a
qvector might be pointers and therefore must be marked, while the
objects in a buffer cannot be pointers and are ignored. The words in
a buffer or q-vector can be accessed easily with subscripted
q-register names; if QA contains a q-vector, then Q:A(0) is its first
element. To access the elements in hairier ways, you can select the
buffer or q-vector and the insert or delete, etc. Q-vectors are
created by means of FS Q VECTOR.
The buffer block, and what buffers contain (and the gap):
The current buffer is described by the 7-word "buffer block" which
contains these variables:
BEG char addr of start of buffer,
BEGV char addr of lower buffer boundary,
PT char addr of pointer,
GPT char addr of start of gap,
ZV char addr of upper buffer boundary,
Z char addr of top of buffer,
EXTRAC # chars in gap.
(next come 2 words used by the communication
protocol. See below).
MODIFF nonzero if buffer has been modified.
RDONLY value of FS READ ONLY for this buffer.
Note that all character addresses normally used in TECO have BEG
subtracted from them; "B" returns BEGV-BEG; "Z", ZV-BEG; "FS Z",
Z-BEG; ".", PT-BEG; "FS GAP LOCATION", GPT-BEG. "FS GAP LENGTH"
gives EXTRAC. The actual value of BEG is available as "FS REAL
ADDRESS".
GPT and EXTRAC describe the "gap", a block of unused space in the
middle of the buffer. The real amount of space used by the buffer is
Z-BEG+EXTRAC. BEGV, PT, Z and ZV are "virtual" addresses in that they
take no account of the gap. To convert a virtual address to a real
one, add EXTRAC to it if it is greater than or equal to GPT. Real
address 0 refers to the first character in word 0; real address 5
refers to the first character in word 1, etc.
It is OK for the superior to alter those variables or the contents
of the buffer, if TECO is between commands or has returned because of
^K, FS EXIT or ^C; except that BEG should not be changed and the sum
of Z and EXTRAC (the real address of the end of the buffer) should not
be changed, unless appropriate relocation of other buffers and TECO
variables is undertaken. TECO programs need not worry about the gap,
except for efficiency reasons or when communicating with machine
language programs, and they need never convert character addresses to
real addresses; TECO does all that.
Strings - internal format:
A string containing <n> characters takes up <n>+4 consecutive
characters in TECO. It need not start on a word boundary. The first
four characters are the string header; the rest, the text of the
string. The header starts with a rubout. The second character is
<n>&177; the third, (<n>/200)&177; the fourth, <n>/40000 (numbers in
octal).
Buffers - internal format:
A buffer consists of a buffer-string, which points to a buffer
frame, which points to the buffer's text.
The buffer-string is similar to a string, and exists in a string
storage space, but begins with a "~" (ASCII 176) instead of a rubout.
It has only three more characers; the second is <addr>&177; the third,
(<addr>/200)&177; the fourth, <addr>/40000; <addr> being the address
of the buffer frame.
The buffer frame is a seven-word block whose purpose is to save the
buffer block for buffers which are not selected. While a buffer is
selected, the buffer frame contents may not be up to date.
The first word of the frame contains a few flag bits in the left
half. The sign bit will be set to indicate that the block is in use
as a buffer frame. The 200000 bit is the GC mark bit and should be
ignored. The 100000 bit, if set, indicates that the buffer is really
a qvector. The 40000 bit is the "buffer modified" flag. These bits
are only in the buffer frame, not the buffer block (BEG).
Buffer and string pointers - internal format:
When a q-reg is said to hold a buffer or a string, it really
contains a pointer to the buffer or string. The pointer is in fact a
number, distinguished from other numbers by its value only! A range
of the smallest negative numbers are considered to be pointers (this
is why QAUB copies a string pointer from QA to QB without any special
hair).
Numbers which are pointers are decoded by subtracting 400000000000
octal (the smallest negative integer) to get a character address.
This may either be the exact address of a character in pure space
(what :EJ loads into), or the relative address of a character in
impure string space (what "X" allocates within. The char address of
the start of impure string space is held in location QRBUF). In
either case, that character should be the rubout beginning a string or
the "~" starting a buffer-string. If the number, thus decoded, does
not point within either of those ranges, or doesn't point at a "~" or
rubout, then it is not a pointer - just a plain number.
For example, 400000000000.+(FS :EJPAGE*5*2000.) is a string pointer
to a string whose first character is at the very beginning of the last
:EJ'd file. If the file has the proper format (see "strings" above),
that number may be put in a q-reg and the string then executed with
"M" or gotten by "G", etc. The file might contain a buffer-string
except that causing it to point to a legitimate buffer frame would be
difficult. Making it point to a counterfeit buffer frame inside the
file would lose, since TECO tries to write in buffer frames.
Low Bits:
On ITS, the low bits of the words of a "text" file are generally
ignored, but on other systems such as BOTTOMS-10 any word whose low
bit is 1 is effectively not present in the file. Because of this,
TECO attempts not to turn on the low bits of files. However, for
efficiency's sake, low bits are not cleared in files when they are
read in; also, you can easily set low bit explicitly using FS WORD or
U:<buffer>(<idx>). If you wish specifically to clear the low bits of
all the words of the buffer, you can do it as follows: J 0I ZJ 0I JD
ZJ-D.
On the other hand, when you have numeric data in a buffer, stored
in words instead of as text, you must be careful to avoid operations
which can clear the low bits of the words. Anything which moves text
except on word boundaries can shuffle the positions of the characters
in the words, and the low bits will be misplaced if not also cleared.
You can avoid such problems if you never insert or delete characters
except in groups of 5 or multiples of 5, starting at positions which
are multiples of 5. In this context, note that 5,0I will NOT clear
the low bit; you must do 0,.-5FS WORD or 0U:..Q(<n>) (or something
else suitable) to do that.
How superiors can put text (and other things) into TECO:
A standard protocol for communication from a superior to TECO is
hereby defined, which allows the superior to request space in the
buffer for inserting text, or request that a file be loaded and a
certain function be found. Macro packages may supply functions to
handle the requests instead of TECO's default handler.
A superior can make a request whenever TECO has deliberately returned
control (by a ^K valret, FS EXIT or a ^C) by restarting TECO at a
special place: 7 plus the address of the "buffer block", which address
can be found in accumulator 2 at such times. Save the old PC before
setting it, since you must restore the PC after the request is
handled. The word after the starting location (8 plus the buffer
block address) is used for an argument.
There are two types of requests. If you wish to supply text for TECO
to edit, the argument should be the number of characters of text you
need space for (it may be 0). In that case, TECO will return (with an
FS EXIT) after making at least that much space in the buffer, after
which you should restore the PC at which TECO had stopped before you
made the request. You can then insert the text in the buffer and
restart TECO.
If you want TECO to read in a file, supply a negative argument and be
prepared to supply TECO with JCL, when it asks with the standard
.BREAK 12, describing what it should do. When TECO does a .BREAK 16,
(FS EXIT) you can assume it has done its work, and should restore the
old PC. The formats for the JCL string are <filename><cr>,
<filename>,<decimal number><cr>, and <filename>,<function name><cr>.
A decimal number should be the address within TECO of the place to
start editing. A function name can be anything that isn't a number,
and its interpretation is not specified.
TECO macro packages can supply a handler for requests from the
superior by putting it in FS SUPERIOR. It will receive the argument
describing the type of request as its numeric argument (^Y), and can
read the JCL with FJ and do an FS EXIT when finished. If FS
SUPERIOR is zero, TECO's default actions will be taken Note that
TECO's default handling of a request to load a file is to do nothing.
TECO's character sets:
(numbers in this section are in octal)
The most important TECO character sets are ASCII (7-bit) and the 9-bit
TV set. The contents of all files, strings, and buffers, and thus all
TECO commands, are in ASCII; 9-bit is used only for terminal input.
Here is how TECO converts between character sets:
14-bit to 9-bit conversion when characters are read in:
When a character is actually read from the terminal, it is in a 14-bit
character set which contains a basic 7-bit code, and the control, meta
and top bits (also shift and shift- lock, which are ignored since they
are already merged into the basic 7-bit character). TECO converts it
to 9-bit as follows: if top is 0, and the 7-bit character is less than
40 and not bs, tab, LF, CR or altmode, then add control+100; then
clear out top, shift and shift-lock. Thus, TV uparrow comes in as
top+013 and turns into 013; TV control-K comes in as control+113 and
stays control+113; TV "VT" comes in as 013 and turns into control+113;
TV control-VT comes in as control+013 and becomes control+113; non-TV
control-K comes in as 013 and becomes control+113; TV control-I comes
in as control+111 and stays control+111; TV "tab" comes in as 011 and
stays 011; TV control-tab comes in as control+011 and stays
control+011; non-TV "tab" or control-I comes in as 011 and stays 011.
The character 4110 (Top-H) is the HELP character; it is handled
specially. It is not changed, even when any other character would be
converted to 9-bit or 7-bit. It is always returned as 4110. However,
if FS HELP MAC is nonzero, then 4110 typed AT ANY TIME will cause FS
HELP MAC to be run. When FS HELP MAC is run, the 4110 is otherwise
ignored, so TECO will continue to wait for input (unless FS HELP MAC
sets FS REREAD to supply some). Only when FS HELP MAC is zero will
4110 ever be returned to the user. ^R ignores 4110 (except for
running FS HELP MAC).
9-bit to ASCII, when TECO wants to read an ASCII code:
input read in using "@FI", or read by the ^R-mode comand dispatch, is
used as 9-bit. However, when input is read by "FI", or by the "^T"
command reader, or by TECO top level, it must be converted to ASCII as
follows: meta is thrown away; if control is 0 then nothing changes;
otherwise, control is cleared and the following actions performed on
the 7-bit character that is left: rubout stays the same; characters
less than 40 stay the same; characters more than 137 have 140
subtracted; characters 100 to 137 have 100 subtracted; all others are
unchanged, except for 40 (Space) which becomes 0 (^@). Thus,
control+111 (TV control-I) becomes 011; control+011 (TV control-tab)
becomes 011; and 011 (TV tab, or non-TV control-I) stays 011.
Similarly, TV uparrow, TV "VT", TV control-K and non-TV control-K all
become 013.
ASCII to 9-bit in FS ^RCMACRO and FS ^R INIT:
The ^R command dispatch table is indexed by 9-bit characters. For
compatibility with the time that it was not, the commands FS ^R
CMACRO and FS ^R INIT, when not given the atsign modifier, accept an
ASCII argument, and try to have the effect of referring to the
definition of that ASCII character - in fact, they convert the ASCII
character to 9-bit and then index their tables. The conversion is as
follows: if the character is less than 40, and is not bs, tab, LF, CR
or altmode, then add control+100. Thus, 013 (^K) becomes control+113
(TV "VT" or control-K, not TV "uparrow"), which is just right. Tab,
etc. have a harder time doing the right thing, since both 011
control+111 are plausible ways that the user could type what
corresponds to ASCII 011. The solution chosen is to leave 011 ASCII
the same in 9-bit, since the ^R-mode definition of control-111 is to
use 011's definition.
The initial ^R-mode definitions of all 9-bit characters:
All characters whose bottom 7 bits form a lower case letter are
defined to indirect through the corresponding upper case character.
Their definitions are all 40,,RRINDR, where RRINDR is the
indirect-definition routine, and 40 specifies the character 40 less.
Control-BS and Control-H indirect through BS, and similarly for Tab
and LF. Control-CR and Control-Altmode (but not Control-M and
Control-[) indirect through CR and Altmode. An isomorphic
indirection-pattern exists for meta characters.
Control-, Meta- and Control-Meta-digits all accumulate into the
numeric argument.
Control-, Meta- and Control-Meta-Minus-sign all set the 4 bit in FS
^R ARGP, thus negating the next command's arg.
All other meta characters are self-inserting. A few (mentioned
above) are self inserting because they go indirect through other meta
characters.
All non-control non-meta characters, except for CR, altmode and
rubout, are self-inserting. CR inserts CRLF; altmode leaves ^R-mode;
rubout deletes backwards. Of the rest, ^H, ^I and ^J are defined to
insert themeselves straight away, while the rest are defined to be
"normal" and do whatever FS ^R NORMAL and FS ^R REPLACE say.
Control-rubout has its own special routine, which deletes treating
spaces as if they were tabs.
Control-digits update the numeric arg for the next command.
All other control characters not in the range control+101 through
control+135 are errors.
Control-M inserts just a CR. Control-[ is an error.
The remaining control characters from control-101 to control-135 do
what the ^R command table says, or else are errors.
Neat hacks that are frequently useful:
1) To take an absolue value, use ^@^@. -1^@^@ and 1^@^@ are both 1.
This assumes that there is no pre-comma argument.
2) When there is just a pre-comma argument, :^@ will make it a
post-comma argument instead. There will be zero as a pre-comma
argument, but another ^@ will flush that. Thus, :^@^@ gets a
pre-comma argument as a post-comma argument with no pre-comma. If
there is a post-comma argument already, start with *0 to clear it
first, giving *0:^@^@. Since many commands ignore pre-comma
arguments, simply :^@ may be enough.
3) ",0^@" negates its argument, like "*(-1)".
4) The easiest way to compute the maximum of two quantities is with
F^@, as in QA,QBF^@. This, however, returns the other one as a
pre-comma argument. For the minimum as a post-comma arg, add :^@.
TECO program writing standards:
1) Each line that doesn't begin inside a string argument should be
indented with at least one space, preferably with a number of
spaces indicating how deep in conditionals and iterations it is.
2) The semantic content of one line of TECO program should be no
greater than that of one line of any other language, if the program
is to be understandable. in other words, break lines frequently -
and put a comment on each line. There should be spaces between
logical groups of commands, every few characters, as in "3K J
IFOO", which also shows how long a line should be.
3) The standard way to write a comment is to make it look like a tag:
!<comment>!.
4) Follow value-returning commands with "W"'s or CRLFs when the value
is not used for anything.
5) An example of a well-commented TECO program is RMAIL. See
EMACS1;RMAILX > and RMAILZ >. Note that these are written in EMACS
compressor format.
TECO program debugging aids:
1) Trace mode causes all TECO commands to be typed out as they are
executed. See the "?" command. A good technique is " 1F[TRACE MA"
for running q-reg A in trace mode.
2) FS STEP MACRO causes TECO to pause at each line, displaying the
buffer and waiting for input before continuing execution. This
works best when lines are short, as they ought to be anyway.
3) Break-loops on errors are available, by setting FS *RSET to
nonzero, or by using Q..P.
4) It is easy to edit a "FTHere I am" or "Q0=" into the program and
re-execute it.
5) If the standard top level is in use, "?" typed in after an error
will cause a printout of a short section of command string up to
the point of the error. User break loops in Q..P can use FS
BACKTRACE to do similar or better things.
6) Setting FS .CLRMODE to 1 disables the ^L and F+ commands, which
normally clear the screen. This may be useful for debugging
programs that wipe out their trace output.
File: TECMAN Node: Fancy Up: Concept
TECO COMMANDS: Various operations upon the buffer -- such as sorting,
casification, LISP operations and other semi-AI-type actions.
>>>>>>>>>>>>>>>>>>>> Sorting buffer <<<<<<<<<<<<<<<<<<<<
^P alphabetic (ASCII) or numeric sort command.
The entire buffer, or the part within the virtual boundaries,
is sorted, after being divided into sort records
(i.e., things to be sorted) on the basis of the arguments
given to the command in the form of
three TECO command strings following
the ^P, separated by altmodes
(Notes: (1) two successive null args
will result in a premature end of
command input, so use spaces where
needed; (2) a dollar sign in any
arg will be replaced by an altmode;
(3) the three args will be left in q-regs ..0, ..1, ..2).
The three expressions are used to divide the buffer into sort
records, each of which has a sort key.
A sort key may be any substring of the record, or it may
be a number. The records and keys are found as follows:
1. The pointer is moved to the
beginning of the buffer, which is the
beginning of the first sort record.
2. The first command string is executed.
If the key is to be a substring of the record,
this command string should leave point at the
beginning of the key. If the key is to be a number,
it does not matter what this command string does.
3. The second command string is executed.
If this command string returns a value, that value is the key.
Otherwise, this command string should leave point at the end
of the key.
4. The last command string is executed.
This should move the pointer to the end of the sort record,
which is also the beginning of the next record.
5. If step 3 or 4 leaves the pointer
at the end of the buffer, the creation of sort
records is complete, and the sort
takes place. Otherwise, go back
to step 2.
Sort records and keys may be variable length.
No character (i.e., a shorter key) sorts before ^@,
and keys are considered left-justified for the comparison.
Numeric keys are always "less" than any string keys.
Failing search commands are not errors while scanning for sort
records, unless the FS S ERROR flag is nonzero. It is
recommended that this flag be set, since code is easier to
debug if all searches which are supposed to be allowed to fail
have an explicit colon.