mirror of
https://github.com/PDP-10/its.git
synced 2026-01-17 00:33:22 +00:00
1472 lines
34 KiB
Plaintext
Executable File
1472 lines
34 KiB
Plaintext
Executable File
;;;-*-Midas-*-
|
||
|
||
subttl FORMAT
|
||
|
||
.begin format
|
||
|
||
;;;The master copy of this library lives in AI:SYSENG;FORMAT >.
|
||
|
||
;;;Modification history:
|
||
;;; Alan 12/2/87 Added ~U.
|
||
;;; Alan 10/10/87 Added ~:H. $$ERRS defaults to 0 since nobody seems
|
||
;;; to want it usually. ~Q and ~F should now work
|
||
;;; inside justification.
|
||
;;; Alan 5/16/87 Fixed ~E to understand multi-line error messages.
|
||
;;; Alan 11/23/85 Added : flag to ~S (and ~F?).
|
||
;;; Alan 5/2/85 Added ~| and ~Q and $$TIME.
|
||
;;; Alan 1/26/85 New switch:
|
||
;;; $$IERR = 1, allow user supplied error macro
|
||
;;; CStacy ??? New switches:
|
||
;;; $$ITS = 0, not running under ITS
|
||
;;; $$ERRS = 0, ~E not enabled
|
||
;;; Alan 7/17/83 Installed FORMAT on SYSENG;
|
||
|
||
comment
|
||
|
||
File: FORMAT, Node: Top, Up: (LIB), Next: Requirements
|
||
|
||
FORMAT is a .INSRTable MIDAS library patterned after Lisp's FORMAT
|
||
function. The Lisp FORMAT function traces its ancestry back to the
|
||
FORTRAN FORMAT statement and to the ioa_ routine on Multics. This is
|
||
simply the latest entry in a long tradition.
|
||
|
||
* Menu:
|
||
|
||
* Introduction:: Introduction to FORMAT for people who have never
|
||
seen anything like it before.
|
||
|
||
* Requirements:: Basic requirements and calling convention.
|
||
|
||
* Operators:: Table of all operators.
|
||
|
||
* Switches:: Varying the behavior of FORMAT to suit your
|
||
application.
|
||
|
||
File: FORMAT, Node: Switches, Previous: Operators, Up: Top, Next: PCode
|
||
|
||
For the most part FORMAT can function quite well without having \any/
|
||
switches set, most all operators are always assembled. (The single
|
||
exception is the ~T operator currently.)
|
||
|
||
Some switches allow the user to choose between different techniques FORMAT
|
||
can use to accomplish the same ends. For example, the $$ITAB and $$UTAB
|
||
switches allow the user to choose how the ~T operator keeps track of
|
||
horizontal position.
|
||
|
||
In some cases FORMAT can do a better job with some hints and assistance
|
||
from the user. For example, the $$PCODE switch tells FORMAT that it is
|
||
outputting to a display mode TTY channel so that it can use -codes to
|
||
perform cursor positioning.
|
||
|
||
Anyone reading this documentation for the first time should probably glance
|
||
briefly at each node in the following menu, just to learn what the options
|
||
are.
|
||
|
||
* Menu:
|
||
|
||
* PCode:: The $$PCODE switch, for when FORMAT is outputting
|
||
to a display mode TTY.
|
||
|
||
* ITab:: The $$ITAB switch, for when you can track
|
||
horizontal position yourself.
|
||
|
||
* UTab:: The $$UTAB switch, for when you want FORMAT to
|
||
track horizontal position for you.
|
||
|
||
* PFN:: The $$PFN switch allows FORMAT to call the RFN"PFN
|
||
routine from the RFN library to print filenames.
|
||
*Note RFN:(LIB)RFN.
|
||
|
||
* Time:: The $$TIME switch allows FORMAT to call routines
|
||
from the DATIME library to print dates and times.
|
||
*Note DATIME:(LIB)DATIME.
|
||
|
||
* Engl:: The $$ENGL switch can be used to disable the
|
||
english number printer to conserve space.
|
||
|
||
* IErr:: The $$IERR switch controls the way FORMAT
|
||
signals errors.
|
||
|
||
* Errs:: The $$ERRS switch controls the ~E operator.
|
||
|
||
* ITS:: The $$ITS switch says FORMAT is running under the
|
||
ITS operating syste.
|
||
|
||
File: FORMAT, Node: Introduction, Previous: Top, Up: Top, Next: Requirements
|
||
|
||
If anyone needs this introduction, I refer them to the Lisp Machine
|
||
manual's documentation for the FORMAT function. Perhaps someday I will
|
||
write something here myself.
|
||
|
||
File: FORMAT, Node: Operators, Previous: Requirements, Up: Top, Next: Switches
|
||
|
||
FORMAT operators are introduced by the escape character tilde (~), as with
|
||
the Lisp FORMAT function. Each operator is identified by a single
|
||
character following the tilde, for example the two character sequence ~D is
|
||
the format operator for printing a number in decimal. Additionally,
|
||
various "infix" arguments are allowed between the tilde and the
|
||
identifying character. A sequence of digits is a numeric "parameter"; it
|
||
is interpreted in decimal. (Unlike the Lisp FORMAT, only a single
|
||
parameter is permitted.) Also the characters colon (:) and atsign (@) may
|
||
appear in the infix argument, they are simply "flags" that modify the
|
||
behavior of the operator in some binary way.
|
||
|
||
Instead of a sequence of digits the character "v" may appear as an infix
|
||
argument. In this case the next FORMAT argument is gobbled and it is used
|
||
as the parameter. This is mostly useful with the ~R, ~T and ~< operators.
|
||
|
||
Here is a table of all currently defined FORMAT operators.
|
||
|
||
~% Outputs a carrage return. ~n% outputs n carrage returns. No
|
||
argument is gobbled.
|
||
|
||
~& Advances to a fresh line. ~n& advances to a fresh line and outputs
|
||
n-1 carrage returns. No argument is gobbled. FORMAT's ability to
|
||
bring you to a fresh line without extraneous carrage returns
|
||
depends on the settings of the $$PCODE, $$ITAB and $$UTAB switches.
|
||
if none of those switches is set, then ~& behaves exactly like ~%.
|
||
|
||
~A One argument is gobbled. It should be a byte pointer to an ASCIZ
|
||
string which is to be output. -1 and 0 in the left half are both
|
||
equivalent to 440700.
|
||
|
||
~B One argument is gobbled. It is output as a number in binary.
|
||
|
||
~C One argument is gobbled. It is output as a single character.
|
||
Control characters are output as a two character sequence starting
|
||
with ^. ~:C just outputs the character, even if it is a control
|
||
character.
|
||
|
||
~D One argument is gobbled. It is output as a number in decimal.
|
||
|
||
~E The error message associated with the channel currently in .BCHN is
|
||
output (in all lower case). Normally this is the error message
|
||
associated with the most recent error (.CALL that failed to skip,
|
||
or whatever). ~:E gobbles one argument, which should be an ITS
|
||
error code, and prints the associated error message. The @ flag
|
||
causes the first character of the error message to be capitalized.
|
||
This operator is not assembled unless the $$ERRS flag is set.
|
||
See *Note Errs:Errs.
|
||
|
||
~F One argument is gobbled. It should be a pointer to a four-word
|
||
block containing an ITS filename. (In the usual order: device,
|
||
first filename, second filename, directory.) The filename is
|
||
printed in the standard way. If the $$PFN flag is set, then FORMAT
|
||
will call the RFN"PFN routine from the RFN library. See
|
||
*Note PFN:PFN.
|
||
|
||
~H One argument is gobbled. It is printed in octal halfword format
|
||
similar to H mode in DDT (In fact the algorithm is borrowed from
|
||
DDT). -105 is printed as "-1,,-105" etc. ~:H is the same except
|
||
the left half is omitted when it would be redundant. (That is,
|
||
777 is printed as "777" rather than "0,,777" and -1 is printed as
|
||
"-1" rather than "-1,,-1".)
|
||
|
||
~O One argument is gobbled. It is printed in octal.
|
||
|
||
~P The previously gobbled argument is re-examined. If it is 1,
|
||
nothing is output, otherwise "s" is output. No new arguments are
|
||
gobbled. ~:P is the same except instead of re-examining the
|
||
previous argument, a new argument is gobbled. (Note that the sense
|
||
of the colon flag is reversed from the Lisp FORMAT function's ~P
|
||
operator.) ~@P and ~:@P are similar except if the argument is 1
|
||
then "y" is output, otherwise "ies" is output.
|
||
|
||
~Q One argument is gobbled. It is interpreted as a date and time in
|
||
ITS disk format and output. ~:Q outputs just a time. ~@Q outputs
|
||
just a date. This operator is not assembled unless the $$TIME
|
||
switch is set. See *Note Time:Time.
|
||
|
||
~R ~nR gobbles one argument and outputs it in base n.
|
||
~R (no parameter) gobbles one argument and outputs it in english
|
||
("one", "two", "three", etc.). ~:R outputs an ordinal number
|
||
("first", "second", "third", etc.). The @ flag causes the first
|
||
character of the first word output to be capitalized. FORMAT's
|
||
english number printing facilities can be disabled by use of the
|
||
$$ENGL switch to save space, see *Note Engl:Engl.
|
||
|
||
~S One argument is gobbled. It is interpreted as a word of SIXBIT and
|
||
output. ~:S prints in lower case.
|
||
|
||
~T ~nT outputs enought tabs and spaces to advance the output to a
|
||
horizontal position of n. If the output is already beyond that
|
||
column, nothing is output. This operator is not assembled unless
|
||
one of the switches $$ITAB or $$UTAB is set. No arguments are
|
||
gobbled. (See *Note ITab:ITab, and its Next for details.)
|
||
|
||
~U One argument is gobbled. It is interpreted as a word of SQUOZE and
|
||
output.
|
||
|
||
~X ~X gobbles one argument. It is output in hexidecimal.
|
||
|
||
~| If $$PCODE is set, ~| clears the screen. If $$PCODE is not set, ~|
|
||
outputs a formfeed. In both cases ~n| then outputs n-1 carrage
|
||
returns.
|
||
|
||
~~ Outputs a tilde. No argument is gobbled.
|
||
|
||
~<cr> Occasionally it may be necessary to insert a carrage return in a
|
||
long FORMAT control string to improve readability. The ~<cr>
|
||
operator allow this to be done gracefully. ~<cr> simply discards
|
||
the carrage return and any leading whitespace on the next line and
|
||
then continues processing the control string. ~@<cr> outputs the
|
||
carrage return and discards the whitespace. ~:<cr> discards the
|
||
carrage return and outputs the whitespace. ~:@<cr> outputs both,
|
||
and is therefore a no-op. No argument is gobbled.
|
||
|
||
~< These three operators provide a justification feature.
|
||
~; ~n<ll...ll~;crr...rr~> processes the two strings "ll...ll" and
|
||
~> "rr...rr" and outputs them with as many copies of the character "c"
|
||
between them as is necessary to fill up exactly n characters. So
|
||
for example, to print a decimal number in a 6 column field padded
|
||
on the left with zeros, one could write: "~6<~;0~D~>". If the
|
||
output cannot possibly fit, no copies of the padding character will
|
||
be output and the resulting text will simply be too long.
|
||
|
||
By special dispensation, if the lefthand string is empty, and the
|
||
padding character is a space, then the "~; " may be omitted. Thus to
|
||
output a decimal number in 6 columns padded on the left with
|
||
spaces, one could simply write: "~6<~D~>".
|
||
|
||
A few operators are illegal within the strings "ll...ll" and
|
||
"rr...rr", mostly those having to do with knowing horizontal
|
||
position. They are: ~%, ~&, ~T and ~<. The last means that
|
||
recursive justifications are not currently supported.
|
||
|
||
Note that unlike ~T, the justification feature counts characters,
|
||
rather than computing horizontal position.
|
||
|
||
File: FORMAT, Node: Requirements, Previous: Top, Up: Top, Next: Operators
|
||
|
||
FORMAT requires no static storage, it keeps all of its state on the stack
|
||
(including its small output buffer). It is completely pure, and completely
|
||
reentrant.
|
||
|
||
FORMAT stack frames are relatively large, about 20. to 30. words. Keep
|
||
this in mind when you are allocating your PDL!
|
||
|
||
The following accumulators must be defined: A, B, C, D, E, and P. C must
|
||
be B+1. P must be the pdl-pointer.
|
||
|
||
OUTSTR must be defined. It should be a routine for printing an ASCII
|
||
string. This is what FORMAT calls to output characters.
|
||
|
||
FORMAT does not define any symbols outside of its own symbol block, named
|
||
FORMAT. (See *Note Blocks:(Midas)Blocks, for a review of Midas block
|
||
structure.) Thus, for example, FORMAT's entrypoint is usually written
|
||
FORMAT"FORMAT by the caller.
|
||
|
||
Calling convention:
|
||
|
||
When FORMAT"FORMAT is called it expects A to contain a byte pointer to an
|
||
ASCII string. B should contain the length of that string in characters. C
|
||
should contain minus the number of arguments being passed to FORMAT. Those
|
||
arguments should have been pushed on the PDL (in order) before FORMAT was
|
||
called. The return address will be found below those arguments. FORMAT
|
||
returns by popping the arguments off the stack and then doing a POPJ P,. A
|
||
typical call to FORMAT might look like:
|
||
|
||
push p,[foo69]
|
||
push p,errors
|
||
push p,trials
|
||
hrroi a,[ascii "~&~D error~P in ~D trial~P."]
|
||
movei b,.length "~&~D error~P in ~D trial~P."
|
||
movni c,2
|
||
jrst format"format
|
||
foo69:
|
||
|
||
Obviously a little macrology can sugar this up to be not quite so
|
||
cumbersome. See *Note Macro:Macro, for a possible candidate.
|
||
|
||
Notice, by the way, that a -1 or a 0 in the left half of the byte pointer
|
||
passed to FORMAT in A will be treated as if it were 440700.
|
||
|
||
FORMAT calls the routine OUTSTR to do output with a byte pointer in A,
|
||
character count in B. That routine mustn't clobber D or E, but C is
|
||
fair game. It is called by PUSHJ P,OUTSTR. A likely OUTSTR might be:
|
||
|
||
outstr: .call [setz ? sixbit /siot/
|
||
movei ttyo
|
||
move a
|
||
setz b]
|
||
.lose %lssys
|
||
popj p,
|
||
|
||
File: FORMAT, Node: PFN, Previous: UTab, Up: Switches, Next: Time
|
||
|
||
By default $$PFN==0.
|
||
|
||
If $$PFN==0 then ~F will simply format a filename like: "~S: ~S; ~S ~S"
|
||
|
||
If $$PFN==1 then the ~F operator will work by calling the routine PFN,
|
||
which you must supply somehow. It will be invoked as if it is the RFN"PFN
|
||
routine from the RFN library. (*Note RFN:(LIB)RFN.) Typically setting
|
||
$$PFN==1 will look something like:
|
||
|
||
rfn"$$pfn==:1
|
||
.insrt dsk:syseng;rfn >
|
||
|
||
format"$$pfn==:1
|
||
format"pfn==:rfn"pfn
|
||
.insrt dsk:syseng;format >
|
||
|
||
FORMAT assumes that no filename can require more than 54 characters to
|
||
print (including quotes, and including a potential ^@ after the last
|
||
character deposited).
|
||
|
||
Of course it needn't really be RFN"PFN that format calls in this case, the
|
||
routines RFN"PFNMCH and RFN"PFNBRF also have the same calling convention
|
||
and can be used instead. Indeed, any routine can be used as long as it has
|
||
the same calling convention and doesn't deposit more than 54 characters!
|
||
|
||
File: FORMAT, Node: Time, Previous: PFN, Up: Switches, Next: Engl
|
||
|
||
By default $$TIME==0.
|
||
|
||
If $$TIME==1 then the ~Q operator is enabled. It will format dates and
|
||
times by calling the routines FORMAT"DATIME, FORMAT"TIME, and FORMAT"DATE
|
||
in order to implement ~Q, ~:Q, and ~@Q respectively. These routines are
|
||
all invoked as if they were output routines from the DATIME library.
|
||
(*Note DATIME:(LIB)DATIME.) Typically setting $$TIME==1 will look
|
||
something like:
|
||
|
||
datime"$$out==:1
|
||
.insrt dsk:syseng;datime >
|
||
|
||
format"$$time==:1
|
||
format"datime==:datime"twdasc
|
||
format"time==:datime"timasc
|
||
format"date==:datime"datasc
|
||
.insrt dsk:syseng;format >
|
||
|
||
FORMAT assumes that no date or time requires more than 35 characters to
|
||
print. (This is easily true of all the routines in DATIME.)
|
||
|
||
File: FORMAT, Node: Engl, Previous: Time, Up: Switches, Next: IErr
|
||
|
||
By default $$ENGL==1.
|
||
|
||
If $$ENGL==1, then FORMAT's english number printing routines are assembled.
|
||
This enables ~R, ~:R, ~@R and ~:@R.
|
||
|
||
If you are tight for space, you can set $$ENGL==0 and save about 250 words.
|
||
|
||
File: FORMAT, Node: ITS, Previous: Errs, Up: Switches
|
||
|
||
By default $$ITS==1.
|
||
|
||
If $$ITS==0, then FORMAT will not assume that it is running under ITS
|
||
timesharing.
|
||
|
||
File: FORMAT, Node: Errs, Previous: IErr, Up: Switches, Next: ITS
|
||
|
||
By default $$ERRS==0.
|
||
|
||
If $$ERRS==1, then the ~E operator is enabled and ERRI must be defined. It
|
||
should be a channel on which FORMAT can open the ERR device if need be.
|
||
|
||
File: FORMAT, Node: IErr, Previous: Engl, Up: Switches, Next: Errs
|
||
|
||
By default $$IERR==0.
|
||
|
||
If $$IERR==1 then FORMAT will expect the user to define a macro named
|
||
FMTERR that FORMAT will use to signal errors. It should expect a single
|
||
macro argument of a string of text surrounded by doublequotes.
|
||
|
||
If $$IERR==0 then format uses the following macro:
|
||
|
||
define fmterr *text*
|
||
.value .+2
|
||
jrst .-1
|
||
asciz ":text
|
||
"
|
||
termin
|
||
|
||
File: FORMAT, Node: PCode, Previous: Switches, Up: Switches, Next: ITab
|
||
|
||
By default $$PCODE==0.
|
||
|
||
If $$PCODE==1 then FORMAT is allowed to output ^P codes. This is different
|
||
from allowing the caller to include ^P codes in his FORMAT control string.
|
||
The only restriction on the latter is that if $$UTAB==1 (*Note UTab:UTab.),
|
||
then FORMAT will be confused by ^P codes not produced by FORMAT itself.
|
||
|
||
File: FORMAT, Node: ITab, Previous: PCode, Up: Switches, Next: UTab
|
||
|
||
By default $$ITAB==0.
|
||
|
||
If $$ITAB==1 then the ~T operator is enabled. The user should supply a
|
||
routine named GETPOS to return the horizontal cursor position. The routine
|
||
will be called using PUSHJ P,GETPOS. It should return the current
|
||
horizontal cursor position in A. It should return -1 if the horizontal
|
||
position is unknown. It mustn't clobber D or E, but B and C are fair game.
|
||
A likely GETPOS might be:
|
||
|
||
getpos: .call [setz ? sixbit /rcpos/
|
||
movei ttyo
|
||
setzm a]
|
||
skipa a,[-1]
|
||
hrrz a,a
|
||
popj p,
|
||
|
||
File: FORMAT, Node: UTab, Previous: ITab, Up: Switches, Next: PFN
|
||
|
||
By default $$UTAB==0.
|
||
|
||
If $$UTAB==1 then the ~T operator is enabled. FORMAT will keep track
|
||
of horizontal position itself in this case. This requires that D should
|
||
contain the starting horizontal position whenever FORMAT"FORMAT is called.
|
||
When FORMAT returns, D will contain the updated horizontal position. A
|
||
GETPOS routine is NOT required.
|
||
|
||
The algorithm FORMAT uses to compute horizontal position is the same as
|
||
that employed by EMACS when it displays a file without SAIL characters
|
||
enabled. That is, most control characters are two characters wide,
|
||
including ^H (backspace) and isolated ^M's (carrage return) and ^J's (line
|
||
feed). ^M immediately followed by ^J resets horizontal position to 0.
|
||
^I (tab) characters are understood to advance the horizontal position to
|
||
the next multiple of 8 (and at least to advance it by 1).
|
||
|
||
File: FORMAT, Node: Macro
|
||
|
||
Here is a simple macrology for calling FORMAT:
|
||
|
||
The user writes:
|
||
|
||
format "~&~D error~P in ~D trial~P.",[errors,trials]
|
||
|
||
This macro expands into a single instruction, so that it can be skipped
|
||
over. All accumulators are saved and restored. The arguments written in
|
||
the IRP list after the control string can refer to any location and will
|
||
find the expected value there, EXCEPT for P.
|
||
|
||
define format &string&,args
|
||
pushj p,[
|
||
pushj p,fmtin
|
||
zzz==-1
|
||
irp arg,,[args]
|
||
push p,arg
|
||
zzz==.irpcnt
|
||
termin
|
||
hrroi a,[ascii string]
|
||
movei b,.length string
|
||
movni c,zzz+1
|
||
jrst format"format]
|
||
termin
|
||
|
||
fmtin: push p,a
|
||
push p,b
|
||
push p,c
|
||
push p,[fmtout]
|
||
jrst @-4(p)
|
||
|
||
fmtout: pop p,c
|
||
pop p,b
|
||
pop p,a
|
||
pop p,(p)
|
||
popj p,
|
||
|
||
;end comment
|
||
.auxil ;Don't cref me please.
|
||
|
||
.tyo6 .ifnm1
|
||
.tyo 40
|
||
.tyo6 .ifnm2
|
||
fmtvrs==:.ifvrs
|
||
printx / included in this assembly.
|
||
/
|
||
|
||
ifn b+1-c, .err FORMAT requires C=B+1
|
||
|
||
ifndef $$pcode, $$pcode==0 ;can use ^P codes
|
||
ifndef $$itab, $$itab==0 ;~T and ~& can call GETPOS to do their job.
|
||
ifndef $$utab, $$utab==0 ;format itself is tracking the hpos.
|
||
ifndef $$pfn, $$pfn==0 ;PFN routine prints filenames.
|
||
ifndef $$engl, $$engl==1 ;English number printing is enabled.
|
||
ifndef $$time, $$time==0 ;Date and time printing is enabled.
|
||
ifndef $$ierr, $$ierr==0 ;User has defined a fmterr macro for us.
|
||
ifndef $$its, $$its==1 ;Running under ITS.
|
||
ifndef $$errs, $$errs==0 ;Error code/message printing is enabled.
|
||
|
||
ifn $$utab, ifn $$itab, .err $$ITAB and $$UTAB simultaneously non-zero.
|
||
|
||
ife $$its,[
|
||
ifn $$errs, .err ~E feature only available under ITS
|
||
ife $$ierr, .value==jrst 4,
|
||
];ife $$its
|
||
|
||
ife $$ierr,[
|
||
define fmterr *text*
|
||
.value .+2
|
||
jrst .-1
|
||
asciz ":text
|
||
"
|
||
termin
|
||
] ;ife $$ierr
|
||
|
||
call==pushj p,
|
||
return==popj p,
|
||
jcall==jrst
|
||
|
||
;;;Flags are kept in left half of E.
|
||
%fmcol==1_17. ;Colon flag, sign bit of E
|
||
%fmats==1_16. ;Atsign flag
|
||
%fmnum==1_15. ;Numeric argument seen.
|
||
%fmv==1_14. ;~vX type numeric argument seen.
|
||
%fmjst==1_13. ;Set during a justification.
|
||
%fmbuf==1_12. ;Indicates that a justification is still
|
||
;possible on characters still in the
|
||
;buffer. If $$UTAB==1 then the characters
|
||
;in the buffer have not been counted into
|
||
;HPOS yet. Cleared whenever the buffer is
|
||
;dumped.
|
||
%fmcrl==1_11. ;If $$UTAB==1, this bit remembers that a ^M
|
||
;was the last character out in case the
|
||
;next one is ^J.
|
||
%fmeng==1_10. ;Internal to the english number printer.
|
||
|
||
ifn $$utab,[
|
||
define tyo x
|
||
ifn c-x, move c,x
|
||
format"call format"%tyo
|
||
termin
|
||
] ;end ifn $$utab
|
||
|
||
ife $$utab,[
|
||
define tyo x
|
||
idpb x,format"obp(e)
|
||
sosg format"bufct(e)
|
||
format"call format"dump
|
||
termin
|
||
] ;end ife $$utab
|
||
|
||
define nojust
|
||
tlne e,format"%fmjst
|
||
format"call format"bdjust
|
||
termin
|
||
|
||
define nextarg x,inst=move
|
||
move x,format"argptr(e)
|
||
aobjp x,format"nxarg
|
||
movem x,format"argptr(e)
|
||
inst x,(x)
|
||
termin
|
||
|
||
define getarg x,inst=move
|
||
move x,format"argptr(e)
|
||
inst x,(x)
|
||
termin
|
||
|
||
format: push p,d
|
||
save.d=400000 ;saved contents of D
|
||
hpos==save.d ;If $$UTAB==1, this is hpos.
|
||
movei d,-1(p)
|
||
add d,c
|
||
push p,d
|
||
save.p=400001 ;saved pdl height
|
||
hrli d,-1(c)
|
||
push p,d
|
||
argptr=400002 ;AOBJP Argument pointer.
|
||
push p,e
|
||
save.e=400003 ;saved contents of E
|
||
hrrzi e,-save.e(p) ;Flags all clear initially.
|
||
hlrz c,a
|
||
caie c,-1 ;0 or -1 in left half acts like 440700
|
||
skipn c
|
||
hrli a,440700
|
||
push p,a
|
||
bp=400004 ;Control string byte pointer.
|
||
push p,[0]
|
||
numarg=400005 ;numeric argument to operator.
|
||
movei a,buffer(e)
|
||
hrli a,440700
|
||
push p,a
|
||
obp=400006 ;Output byte pointer.
|
||
ibfsiz==10. ;50. character buffer initially.
|
||
push p,[ibfsiz*5]
|
||
bufct=400007 ;Output buffer count.
|
||
push p,[0]
|
||
just=400010 ;For justification
|
||
push p,[ibfsiz*5]
|
||
bufsiz=400011 ;Size of buffer is variable.
|
||
repeat ibfsiz, push p,[ascii "_____"]
|
||
buffer=400012 ;Buffer must be last.
|
||
move d,b ;D: length of string
|
||
loop: sojl d,done ;nothing left?
|
||
scan: ildb c,bp(e)
|
||
xloop: cain c,"~
|
||
jrst escape
|
||
tyo c
|
||
sojge d,scan
|
||
done: call dump
|
||
tlne e,%fmjst
|
||
call eof
|
||
hrrz c,p
|
||
sub c,save.p(e)
|
||
move d,save.d(e)
|
||
move e,save.e(e)
|
||
hrl c,c
|
||
sub p,c
|
||
return
|
||
|
||
escape: movei c,1
|
||
movem c,numarg(e) ;default arg is 1
|
||
tlz e,%fmats\%fmcol\%fmnum\%fmv\%fmeng ;clear flags
|
||
escp1: sojl d,eof
|
||
ildb c,bp(e)
|
||
jrst @esctbl(c)
|
||
|
||
esctbl:
|
||
repeat 200, nxop
|
||
|
||
define defop char,handlr
|
||
zzz==.
|
||
loc format"esctbl+char
|
||
handlr
|
||
ifge char-"A,[
|
||
ifle char-"Z,[
|
||
loc format"esctbl+char+"a-"A
|
||
handlr
|
||
]]
|
||
loc zzz
|
||
termin
|
||
|
||
defop ":,opcolon
|
||
opcolo: tloe e,%fmcol
|
||
call bdop
|
||
jrst escp1
|
||
|
||
defop "@,opatsign
|
||
opatsi: tloe e,%fmats
|
||
call bdop
|
||
jrst escp1
|
||
|
||
defop "V,op.V
|
||
op.V: tloe e,%fmnum\%fmv
|
||
call bdop
|
||
nextarg c
|
||
movem c,numarg(e)
|
||
jrst escp1
|
||
|
||
repeat 10., defop "0+.rpcnt,opdigit
|
||
opdigi: tlne e,%fmv
|
||
call bdop
|
||
move a,numarg(e)
|
||
tlon e,%fmnum
|
||
setzi a,
|
||
imuli a,10.
|
||
subi c,"0
|
||
add a,c
|
||
movem a,numarg(e)
|
||
jrst escp1
|
||
|
||
defop "~,optilde
|
||
optild: tyo c
|
||
cloop: jrst loop
|
||
|
||
defop "R,op.R
|
||
defop "X,op.X
|
||
op.R: tlnn e,%fmnum
|
||
jrst englsh
|
||
skipa a,numarg(e)
|
||
op.X: movei a,16.
|
||
jrst op.num
|
||
|
||
defop "B,op.B
|
||
op.B: movei a,2
|
||
jrst op.num
|
||
|
||
defop "D,op.D
|
||
defop "O,op.O
|
||
op.D: skipa a,[10.]
|
||
op.O: movei a,8
|
||
op.num: nextarg b
|
||
call ntype
|
||
jrst loop
|
||
|
||
defop "H,op.H
|
||
op.H: nextarg b
|
||
caml b,[-4000]
|
||
cail b,774000
|
||
skipa
|
||
jumpl e,op.H1
|
||
hlrz b,b
|
||
cail b,774000
|
||
hrre b,b
|
||
movei a,8
|
||
call ntype
|
||
movei c,",
|
||
tyo c
|
||
movei c,",
|
||
tyo c
|
||
getarg b,hrrz
|
||
cail b,774000
|
||
hrre b,b
|
||
op.H1: movei a,8
|
||
call ntype
|
||
jrst loop
|
||
|
||
ifn $$engl,[
|
||
|
||
englsh: nextarg b
|
||
push p,cloop
|
||
jumpe b,eng0
|
||
jumpg b,eng1
|
||
movei a,$minus
|
||
call prinz
|
||
movn b,b
|
||
jumpl b,ensetz
|
||
eng1: cail b,10000.
|
||
jrst eng1E9
|
||
move a,b
|
||
idivi b,100.
|
||
idivi b,10.
|
||
move b,a
|
||
jumpe c,eng1E3
|
||
tlo e,%fmeng
|
||
jcall engb
|
||
|
||
eng0: movei a,$0
|
||
tlne e,%fmcol
|
||
movei a,$0th
|
||
jcall prinz
|
||
|
||
;;;An inordinate number of instructions have been written in this world to
|
||
;;;compensate for the fact that in two's-compliment binary there is an
|
||
;;;extra negative number:
|
||
ensetz: idiv b,[1000000000.]
|
||
movn b,b
|
||
movn c,c
|
||
jrst eng1E8
|
||
|
||
eng1E9: idiv b,[1000000000.]
|
||
eng1E8: move a,[$billion,,eng1E6]
|
||
jrst engil
|
||
|
||
eng1E6: idiv b,[1000000.]
|
||
move a,[$million,,eng1E3]
|
||
jrst engil
|
||
|
||
eng1E3: idivi b,1000.
|
||
eng1E2: move a,[$thousand,,eng1E0]
|
||
jrst engil
|
||
|
||
eng1E0: tlo e,%fmeng
|
||
jcall engb
|
||
|
||
engil: exch b,c
|
||
jumpe c,(a)
|
||
push p,a
|
||
push p,b
|
||
call engc
|
||
pop p,b
|
||
hlr a,(p)
|
||
call prinz
|
||
jumpn b,sppopj
|
||
pop p,(p)
|
||
jumpge e,cpopj
|
||
thpopj: movei a,[asciz "th"]
|
||
jcall prinz
|
||
|
||
sppopj: movei c,40
|
||
tyo c
|
||
return
|
||
|
||
;;;Still within IFN $$ENGL:
|
||
|
||
;;;Subroutine. Outputs C(B) in english. 0 < C(B) < 10000., but not
|
||
;;;1000.|C(B). ENGC prints C(C), ENGB prints C(B). If %FMENG and %FMCOL are
|
||
;;;set, then we output an ordinal number.
|
||
engc: move b,c
|
||
engb: idivi b,100.
|
||
jumpe b,engx2
|
||
push p,c
|
||
tlze e,%fmeng
|
||
tlnn e,%fmcol
|
||
jrst engx1
|
||
call eng100
|
||
movei a,$hundred
|
||
call prinz
|
||
pop p,b
|
||
jumpe b,thpopj
|
||
movei a,$and
|
||
call prinz
|
||
tlo e,%fmeng
|
||
jcall eng100
|
||
|
||
engx1: call eng100
|
||
movei a,$hundred
|
||
call prinz
|
||
pop p,b
|
||
jumpn b,eng140
|
||
return
|
||
|
||
engx2: move b,c
|
||
jcall eng100
|
||
|
||
;;;Subroutine. Outputs C(B) in english. 0 < C(B) < 100..
|
||
;;;ENG140 prints a space first, ENG100 does not. If %FMENG is set, we
|
||
;;;output an ordinal number.
|
||
eng140: movei c,40
|
||
tyo c
|
||
eng100: caige b,20.
|
||
jrst eng102
|
||
idivi b,10.
|
||
move a,C$20-2(b)
|
||
move b,c
|
||
call prinz
|
||
jumpe b,eng103
|
||
movei a,[asciz "y-"]
|
||
call prinz
|
||
eng102: move a,C$1-1(b)
|
||
tlne e,%fmeng
|
||
hlr a,a
|
||
prinz: hrli a,440700
|
||
tlzn e,%fmats ;Atsign flag causes capitalization
|
||
jrst prinz0
|
||
ildb c,a
|
||
subi c,"a-"A
|
||
prinz1: tyo c
|
||
prinz0: ildb c,a
|
||
jumpn c,prinz1
|
||
return
|
||
|
||
eng103: tlne e,%fmeng
|
||
jrst eng104
|
||
movei c,"y
|
||
tyo c
|
||
return
|
||
|
||
eng104: movei a,[asciz "ieth"]
|
||
jcall prinz
|
||
|
||
;;;Still within IFN $$ENGL:
|
||
|
||
C$1: $1th,,$1 ? $2th,,$2 ? $3th,,$3 ? $4th,,$4 ? $5th,,$5 ? $6th,,$6
|
||
$7th,,$7 ? $8th,,$8 ? $9th,,$9 ? $10th,,$10 ? $11th,,$11
|
||
$12th,,$12 ? $13th,,$13 ? $14th,,$14 ? $15th,,$15 ? $16th,,$16
|
||
$17th,,$17 ? $18th,,$18 ? $19th,,$19
|
||
|
||
C$20: $20 ? $30 ? $40 ? $50 ? $60 ? $70 ? $80 ? $90
|
||
|
||
$minus: asciz "minus "
|
||
$and: asciz " and "
|
||
$0: asciz "zero"
|
||
$0th: asciz "zeroth"
|
||
|
||
$1: asciz "one"
|
||
$1th: asciz "first"
|
||
$2: asciz "two"
|
||
$2th: asciz "second"
|
||
$3: asciz "three"
|
||
$3th: asciz "third"
|
||
$4: asciz "four"
|
||
$4th: asciz "fourth"
|
||
$5: asciz "five"
|
||
$5th: asciz "fifth"
|
||
$6: asciz "six"
|
||
$6th: asciz "sixth"
|
||
$7: asciz "seven"
|
||
$7th: asciz "seventh"
|
||
$8: asciz "eight"
|
||
$8th: asciz "eighth"
|
||
$9: asciz "nine"
|
||
$9th: asciz "ninth"
|
||
$10: asciz "ten"
|
||
$10th: asciz "tenth"
|
||
$11: asciz "eleven"
|
||
$11th: asciz "eleventh"
|
||
$12: asciz "twelve"
|
||
$12th: asciz "twelfth"
|
||
$13: asciz "thirteen"
|
||
$13th: asciz "thirteenth"
|
||
$14: asciz "fourteen"
|
||
$14th: asciz "fourteenth"
|
||
$15: asciz "fifteen"
|
||
$15th: asciz "fifteenth"
|
||
$16: asciz "sixteen"
|
||
$16th: asciz "sixteenth"
|
||
$17: asciz "seventeen"
|
||
$17th: asciz "seventeenth"
|
||
$18: asciz "eighteen"
|
||
$18th: asciz "eighteenth"
|
||
$19: asciz "nineteen"
|
||
$19th: asciz "nineteenth"
|
||
|
||
$20: asciz "twent"
|
||
$30: asciz "thirt"
|
||
$40: asciz "fort"
|
||
$50: asciz "fift"
|
||
$60: asciz "sixt"
|
||
$70: asciz "sevent"
|
||
$80: asciz "eight"
|
||
$90: asciz "ninet"
|
||
|
||
$hundr: asciz " hundred"
|
||
$thous: asciz " thousand"
|
||
$milli: asciz " million"
|
||
$billi: asciz " billion"
|
||
|
||
] ;end ifn $$engl
|
||
|
||
defop "A,op.A
|
||
op.A: nextarg a
|
||
hlrz c,a
|
||
caie c,-1 ;0 or -1 in left half acts like 440700
|
||
skipn c
|
||
hrli a,440700
|
||
jrst op.A1
|
||
|
||
op.A2: tyo c
|
||
op.A1: ildb c,a
|
||
jumpn c,op.A2
|
||
jrst loop
|
||
|
||
defop "S,op.S
|
||
op.S: nextarg a
|
||
call 6type
|
||
jrst loop
|
||
|
||
defop "C,op.C
|
||
op.C: nextarg a
|
||
jumpl e,op.C1 ;If colon set, just tyo it.
|
||
cail a,40 ;Normal printing characters just tyo'd
|
||
cail a,177
|
||
jrst op.C2
|
||
op.C1: tyo a
|
||
jrst loop
|
||
|
||
op.C2: cain a,33 ;altmode just gets tyo'd
|
||
jrst op.C1
|
||
movei c,"^
|
||
tyo c
|
||
trc a,100
|
||
jrst op.C1
|
||
|
||
defop "P,op.P
|
||
op.P: jumpl e,op.P1 ;Colon flag reversed from Lisp version.
|
||
getarg c
|
||
tlne e,%fmats
|
||
jrst op.P2
|
||
op.P3: cain c,1
|
||
jrst loop
|
||
op.Ps: movei c,"s
|
||
tyo c
|
||
jrst loop
|
||
|
||
op.P1: nextarg c
|
||
tlnn e,%fmats
|
||
jrst op.P3
|
||
op.P2: cain c,1
|
||
jrst op.P4
|
||
movei c,"i
|
||
tyo c
|
||
movei c,"e
|
||
tyo c
|
||
jrst op.Ps
|
||
|
||
op.P4: movei c,"y
|
||
tyo c
|
||
jrst loop
|
||
|
||
; SQUOZE ASCII
|
||
; 0 "/" 57
|
||
; 1 - 12 "0" - "9" 60 - 71
|
||
; 13 - 44 "A" - "Z" 101 - 132
|
||
; 45 "." 56
|
||
; 46 "$" 44
|
||
; 47 "%" 45
|
||
|
||
defop "U,op.U
|
||
op.U: nextarg b
|
||
tlz b,740000
|
||
op.U1: idiv b,[50*50*50*50*50]
|
||
addi b,"A-13
|
||
caige b,"A
|
||
subi b,<"A-1>-"9
|
||
caile b,"Z
|
||
subi b,<"Z+2>-"$
|
||
cain b,"$-1
|
||
movei b,".
|
||
exch b,c
|
||
tyo c
|
||
imuli b,50
|
||
jumpn b,op.U1
|
||
jrst loop
|
||
|
||
ifn $$errs,[
|
||
defop "E,op.E
|
||
op.E: jumpl e,op.E4 ;If colon flag is set, arg is error code.
|
||
movei a,1
|
||
op.E1: .call op.Ecl
|
||
.lose %lssys
|
||
tlnn e,%fmats ;If atsign flag is set, Capitalize first word.
|
||
jrst op.E3
|
||
.iot erri,c
|
||
jrst op.E2
|
||
|
||
op.E5: movei c,",
|
||
tyo c
|
||
movei c,40
|
||
tyo c
|
||
op.E6: movei c,"a-"A(a)
|
||
cail c,"a
|
||
caile c,"z
|
||
subi c,"a-"A
|
||
op.E2: tyo c
|
||
op.E3: .iot erri,a
|
||
cail a,40
|
||
jrst op.E6
|
||
caie a,^M
|
||
jrst op.E9
|
||
.iot erri,a
|
||
caie a,^J
|
||
jrst op.E9
|
||
.iot erri,a
|
||
cail a,40
|
||
jrst op.E5
|
||
op.E9: .close erri,
|
||
jrst loop
|
||
|
||
op.E4: nextarg b
|
||
movei a,4
|
||
jrst op.E1
|
||
|
||
op.Ecl: setz
|
||
sixbit /open/
|
||
[.uai,,erri]
|
||
[sixbit /err/]
|
||
move a
|
||
setz b
|
||
];$$errs
|
||
|
||
ife $$pfn,[
|
||
defop "F,op.F
|
||
op.F: nextarg a
|
||
push p,2(a) ;fn2
|
||
push p,1(a) ;fn1
|
||
push p,3(a) ;dir
|
||
move a,0(a) ;dev
|
||
call 6type
|
||
movei c,":
|
||
tyo c
|
||
movei c,40
|
||
tyo c
|
||
pop p,a
|
||
call 6type
|
||
movei c,";
|
||
tyo c
|
||
movei c,40
|
||
tyo c
|
||
pop p,a
|
||
call 6type
|
||
movei c,40
|
||
tyo c
|
||
pop p,a
|
||
call 6type
|
||
jrst loop
|
||
] ;end ife $$pfn
|
||
|
||
ifn $$pfn,[
|
||
|
||
defop "F,op.F
|
||
op.F: movei b,54. ;maximum size of filename including
|
||
jsp a,grow ; the ^@ at the end.
|
||
push p,d
|
||
move d,obp(e)
|
||
nextarg b
|
||
call pfn
|
||
move a,d
|
||
pop p,d
|
||
call nstr
|
||
jrst loop
|
||
|
||
] ;end ifn $$pfn
|
||
|
||
ifn $$time,[
|
||
|
||
defop "Q,op.Q
|
||
op.Q: movei b,35.
|
||
jsp a,grow
|
||
push p,d
|
||
move d,obp(e)
|
||
nextarg a
|
||
tlnn e,%fmcol\%fmats
|
||
call datime
|
||
tlne e,%fmcol
|
||
call time
|
||
tlne e,%fmats
|
||
call date
|
||
move a,d
|
||
pop p,d
|
||
call nstr
|
||
jrst loop
|
||
|
||
] ;end ifn $$time
|
||
|
||
defop ^M,opcrlf
|
||
opcrlf: tlne e,%fmats
|
||
call crlf
|
||
sojl d,done
|
||
ildb c,bp(e)
|
||
caie c,^J ;flush linefeed if it is there
|
||
jrst nolf
|
||
jumpl e,loop ;If colon set, we are done.
|
||
skpws1: sojl d,done
|
||
ildb c,bp(e)
|
||
skipws: caie c,40
|
||
cain c,^I
|
||
jrst skpws1
|
||
jrst xloop
|
||
|
||
nolf: jumpge e,skipws ;If colon not set, skip white space.
|
||
jrst xloop
|
||
|
||
ife $$pcode,[
|
||
defop "|,opvbar
|
||
opvbar: movei c,^L
|
||
tyo c
|
||
sosg a,numarg(e)
|
||
jrst loop
|
||
jrst op.%1
|
||
] ;end ife $$pcode
|
||
|
||
;;;~& is the same as ~% if you can't orient yourself:
|
||
ife $$pcode\$$itab\$$utab, defop "&,op.%
|
||
|
||
defop "%,op.%
|
||
op.%: skipg a,numarg(e)
|
||
jrst loop
|
||
op.%1: call crlf
|
||
sojg a,op.%1
|
||
jrst loop
|
||
|
||
ifn $$pcode,[
|
||
defop "|,opvbar
|
||
defop "&,opamper
|
||
opvbar: skipa a,["C]
|
||
opampe: movei a,"A
|
||
opamp1: nojust
|
||
movei c,^P
|
||
tyo c
|
||
tyo a
|
||
ifn $$utab, setzm hpos(e)
|
||
sosg a,numarg(e)
|
||
jrst loop
|
||
jrst op.%1
|
||
] ;end ifn $$pcode
|
||
|
||
defop "<,oples
|
||
oples: call dump
|
||
tloe e,%fmjst\%fmbuf
|
||
call bdjust
|
||
tlnn e,%fmnum
|
||
call bdop
|
||
move b,numarg(e)
|
||
jsp a,grow ;Make sure buffer is big enough.
|
||
oples3: movei c,40
|
||
hrl c,numarg(e)
|
||
movem c,just(e)
|
||
jrst loop
|
||
|
||
defop 73,opsemi ;"; (Emacs and Midas both give you grief if
|
||
; you actually write a semicolon here...)
|
||
opsemi: tlnn e,%fmjst
|
||
call bdop
|
||
sojl d,eof
|
||
ildb a,bp(e)
|
||
tlnn e,%fmbuf ;buffer overflew, no justification.
|
||
jrst loop
|
||
move c,bufsiz(e)
|
||
sub c,bufct(e)
|
||
jumpe c,opsmi1
|
||
hlrz b,just(e)
|
||
sub b,c
|
||
jumple b,loop ;already no more room, no padding needed.
|
||
hrl a,b
|
||
movem a,just(e)
|
||
call dump
|
||
tlo e,%fmbuf
|
||
jrst loop
|
||
|
||
opsmi1: hrrm a,just(e)
|
||
jrst loop
|
||
|
||
defop ">,opgrt
|
||
opgrt: tlzn e,%fmjst
|
||
call bdop
|
||
tlnn e,%fmbuf ;buffer overflew, no justification.
|
||
jrst loop
|
||
move c,bufsiz(e)
|
||
sub c,bufct(e)
|
||
hlrz b,just(e)
|
||
sub b,c
|
||
jumple b,opgrt7 ;no padding needed.
|
||
move a,obp(e)
|
||
push p,a
|
||
push p,b
|
||
hrrz c,just(e)
|
||
opgrt9: idpb c,a
|
||
ifn $$utab, call pos
|
||
sojg b,opgrt9
|
||
pop p,b
|
||
pop p,a
|
||
call outstr
|
||
opgrt7: call dump
|
||
jrst loop
|
||
|
||
ifn $$itab,[
|
||
|
||
ife $$pcode,[
|
||
defop "&,opamper
|
||
opampe: nojust
|
||
call dump
|
||
call getpos
|
||
jumpn a,op.%
|
||
sose numarg(e)
|
||
jrst op.%
|
||
jrst loop
|
||
] ;end ife $$pcode
|
||
|
||
defop "T,op.T
|
||
op.T: nojust
|
||
tlnn e,%fmnum
|
||
call bdop
|
||
call dump
|
||
call getpos
|
||
jumpl a,loop
|
||
move b,numarg(e)
|
||
camg b,a
|
||
jrst loop
|
||
rot b,-3 ;Only works for 8 character wide tabs.
|
||
rot a,-3
|
||
sub b,a
|
||
hrrz a,b
|
||
lsh b,-33.
|
||
jumpe a,op.T2
|
||
movei b,^I
|
||
op.T1: tyo b
|
||
sojg a,op.T1
|
||
ldb b,[000300,,numarg(e)]
|
||
jumpe b,loop
|
||
op.T2: movei a,40
|
||
op.T3: tyo a
|
||
sojg b,op.T3
|
||
jrst loop
|
||
|
||
] ;end ifn $$itab
|
||
|
||
ifn $$utab,[
|
||
|
||
%tyo: idpb c,obp(e)
|
||
sosg bufct(e)
|
||
jrst tyodmp
|
||
%tyo1: tlne e,%fmbuf
|
||
return
|
||
pos: tlze e,%fmcrl
|
||
jrst poscrl
|
||
posfoo: cail c,40
|
||
cain c,177
|
||
jrst poscc
|
||
aos hpos(e)
|
||
return
|
||
|
||
tyodmp: push p,c
|
||
call dump
|
||
pop p,c
|
||
jrst %tyo1
|
||
|
||
poscrl: caie c,^J
|
||
jrst posfoo
|
||
setzm hpos(e)
|
||
return
|
||
|
||
poscc: cain c,^I
|
||
jrst postab
|
||
cain c,^M
|
||
tloa e,%fmcrl
|
||
caie c,33
|
||
aos hpos(e)
|
||
aos hpos(e)
|
||
return
|
||
|
||
postab: exch c,hpos(e)
|
||
addi c,10 ;Only works for 8 character wide tabs.
|
||
andcmi c,7
|
||
exch c,hpos(e)
|
||
return
|
||
|
||
;;; still in ifn $$utab
|
||
|
||
ife $$pcode,[
|
||
defop "&,opamper
|
||
opampe: nojust
|
||
skipn hpos(e)
|
||
sose numarg(e)
|
||
jrst op.%
|
||
jrst loop
|
||
] ;end ife $$pcode
|
||
|
||
defop "T,op.T
|
||
op.T: nojust
|
||
tlnn e,%fmnum
|
||
call bdop
|
||
move b,numarg(e)
|
||
move a,hpos(e)
|
||
camg b,a
|
||
jrst loop
|
||
rot b,-3
|
||
rot a,-3
|
||
sub b,a
|
||
hrrz a,b
|
||
lsh b,-33.
|
||
jumpe a,op.T2
|
||
op.T1: movei c,^I
|
||
tyo c
|
||
sojg a,op.T1
|
||
ldb b,[000300,,numarg(e)]
|
||
jumpe b,loop
|
||
op.T2: movei c,40
|
||
tyo c
|
||
sojg b,op.T2
|
||
jrst loop
|
||
|
||
] ;end ifn $$utab
|
||
|
||
;;;Make room in the buffer for B more characters. Called by JSP A,GROW:
|
||
grow: sub b,bufct(e)
|
||
jumple b,(a)
|
||
addi b,4
|
||
idivi b,5 ;B: how many words we need.
|
||
movei c,5
|
||
imul c,b ;C: how many characters that will add to
|
||
addm c,bufsiz(e) ; the buffer.
|
||
addm c,bufct(e)
|
||
push p,[ascii "_____"]
|
||
sojg b,.-1
|
||
jrst (a)
|
||
|
||
;;;Empty the buffer.
|
||
dump: push p,b
|
||
move b,bufsiz(e)
|
||
move c,b
|
||
exch c,bufct(e)
|
||
sub b,c
|
||
jumpe b,dump3
|
||
push p,a
|
||
movei a,buffer(e)
|
||
hrli a,440700
|
||
movem a,obp(e)
|
||
ifn $$utab,[
|
||
tlnn e,%fmbuf
|
||
jrst dump1
|
||
push p,a
|
||
push p,b
|
||
dump2: ildb c,a
|
||
call pos
|
||
sojg b,dump2
|
||
pop p,b
|
||
pop p,a
|
||
] ;end ifn $$utab
|
||
dump1: call outstr
|
||
pop p,a
|
||
dump3: tlz e,%fmbuf
|
||
pop p,b
|
||
return
|
||
|
||
;;;Outputs a crlf.
|
||
crlf: movei c,^M
|
||
tyo c
|
||
movei c,^J
|
||
tyo c
|
||
return
|
||
|
||
;;;Types number in B in base A:
|
||
ntype: jumpge b,ntype1
|
||
movei c,"-
|
||
tyo c
|
||
ntype1: idiv b,a
|
||
movm b,b
|
||
movm c,c
|
||
ntype2: addi c,"0
|
||
caile c,"9
|
||
addi c,<"A-10.-"0>
|
||
jumpe b,ntype3
|
||
hrlm c,(p)
|
||
idiv b,a
|
||
call ntype2
|
||
hlrz c,(p)
|
||
ntype3: tyo c
|
||
return
|
||
|
||
;;;Types the word in A in SIXBIT. In lowercase if colon flag is set.
|
||
6type: jumpe a,cpopj
|
||
6type1: ldb c,[360600,,a]
|
||
addi c,40
|
||
tlne e,%fmcol
|
||
jrst 6type2
|
||
6type3: tyo c
|
||
lsh a,6
|
||
jumpn a,6type1
|
||
cpopj: return
|
||
|
||
6type2: cail c,"A
|
||
caile c,"Z
|
||
jrst 6type3
|
||
addi c,"a-"A
|
||
jrst 6type3
|
||
|
||
ifn $$pfn\$$time,[
|
||
;;;Cleanup for the case where a string has been deposited in the buffer by
|
||
;;;someone other than ourselves. New byte pointer is found in A.
|
||
nstr: move c,a
|
||
exch a,obp(e)
|
||
skipge a
|
||
sub a,[430000,,1] ;In case A is 440700,,1 and B is 010700,,0
|
||
sub c,a
|
||
jumpe c,cpopj
|
||
ldb b,[360600,,c]
|
||
imuli c,5
|
||
imuli b,55.
|
||
lsh b,30.
|
||
ash b,-30.
|
||
subi b,(c)
|
||
addm b,bufct(e)
|
||
ifn $$utab,[ ;If we are tabbing, then we must update the HPOS
|
||
tlne e,%fmbuf
|
||
return
|
||
nstr1: ildb c,a
|
||
call pos
|
||
aojl b,nstr1
|
||
] ;end ifn $$utab
|
||
return
|
||
] ;end ifn $$pfn\$$time
|
||
|
||
;;;Under construction:
|
||
;host printing
|
||
;flonum printing
|
||
;defop "?,opques ;Funcall escape.
|
||
|
||
nxop: fmterr "Undefined format operator."
|
||
|
||
bdop: fmterr "Bad call to format operator."
|
||
ife $$engl, englsh==:bdop
|
||
|
||
bdjust: fmterr "Illegal format operation during justification."
|
||
|
||
eof: fmterr "Format string terminated unexpectedly."
|
||
|
||
nxarg: fmterr "Format ran out of arguments."
|
||
|
||
;define sizhac size
|
||
;printx / (size!. words)
|
||
;/
|
||
;termin
|
||
;
|
||
;oradix==10
|
||
;radix 10.
|
||
;sizhac \.-format
|
||
;radix oradix
|
||
|
||
.end format
|