-- util.jam
-- Copyright Ó 1985, 1991 by Xerox Corporation. All rights reserved.
-- last changed by Stone&Paxton, March 28, 1983 3:45 pm
-- last changed by Doug Wyatt, March 26, 1985 2:36:52 pm PST

($help) .dup .where {.pop .pop} {100 .dict .def} .ifelse .cvx .exec

(/def)
{3 .copy .exch .pop .def .pop $help 3 1 .roll .put} .cvx .def

(/xdef)
{3 .copy .exch .pop .cvx .def .pop $help 3 1 .roll .put} .cvx .def

(/def)
(accepts three entries on the stack: a key, string, and value.
 the string is stored under the key in the $help dictionary, and
 the value is stored as a noun under the key in the current dictionary.)
(/def).load /def

(/xdef)
(accepts three entries on the stack: a key, string, and value.
 the string is stored under the key in the $help dictionary, and
 the value is stored as a verb under the key in the current dictionary.)
(/xdef).load /xdef

(?)
(prints the explanation of the given key from the $help dictionary)
{$help .exch .get =}/xdef

(??)
(prints the names of all the utility commands found in the $help dictionary.)
{$help /kdir}/xdef

(/print)
(prints the top of the stack)
{.cvs .print}/xdef

(/lp)
(prints a left parenthesis)
{"(" .print}/xdef

(/rp)
(prints a right parenthesis)
{")" .print}/xdef

(/cr)
(prints a carriage return)
{(
).print}/xdef

(=)
(prints the top of the stack and a carriage return)
{/print /cr}/xdef

(/stk)
(prints (without destroying) the contents of the operand stack.)
{.cntstk .dup 1 .add .copy
{.dup .type /print ( ).print =}.cvx .rept .pop}/xdef

(/pstk)
(pretty prints (without destroying) the contents of the operand stack.)
{.cntstk .dup 1 .add .copy
(:tab) 0 .def {pprint} .cvx .rept .pop}/xdef

(/clr)
(clears the operand stack (same as .clrstk))
{.clrstk} /xdef

(/dir)
(prints the contents of the dictionary on top of the operand stack.)
{{.exch /print (  ).print .dup .type .print
( ).print =}.cvx .dictforall}/xdef

(/kdir)
(prints the keys found in the dictionary on the top of the operand stack.)
({.exch = .pop}.cvx .dictforall)/xdef

(/if)
(equivalent to ".cvx .if")
{.cvx .if}/xdef

(/ifelse)
(equivalent to ".ifelse .cvx .exec")
{.ifelse .cvx .exec}/xdef

([)
(marks the operand stack for use by "]")
{.mark}/xdef

(])
(makes the elements above "[" into an array)
{.cnttomrk .array .astore .exch .pop}/xdef

(/run){(Running ).print .dup .print .run (.)=}.cvx .def
(/loadbcd){(Loading ).print .dup .print .loadbcd (.)=}.cvx .def

(==)
(prints the top of the operand stack in a readable form)
{(:tab) 0 .def pprint}/xdef

(pprint)
(supports == and does all the printing)
{tabprint .dup .type .dup /print ( ).print .dup
 $ptypes .exch .known {$ptypes .exch .get .exec} {.pop /cr} /ifelse}/xdef

($ptypes) .dup .where {.pop .pop} {11 .dict .def} /ifelse

$ptypes .begin
(.number) {=}.cvx .def
(.atom) {=}.cvx .def
(.rope) {"(" .print .print ")" .print /cr}.cvx .def
(.cmd) {.commandname =}.cvx .def
(.dict) {"[" .print .dup .length /print "]\n" .print}.cvx .def
(.array) {"[" .print .dup .length /print "]\n" .print
 tabinc {pprint}.cvx .arrayforall tabdec}.cvx .def
.end

(tabinc){(:tab) :tab 1 .add .def}.cvx .def
(tabprint){:tab {( )/print}.cvx .rept}.cvx .def
(tabdec){(:tab) :tab 1 .sub .def}.cvx .def