From 1662094bc141ab0e4f817dd7b634cbb5fe800770 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Wed, 18 Apr 1979 21:00:16 -0800 Subject: [PATCH] BSD 2 development Work on file doc/px/fig1.1.n Work on file doc/px/pxin2.n Work on file doc/px/pxin3.n Work on file doc/px/fig2.2.n Work on file doc/px/pxin1.n Work on file doc/px/makefile Work on file doc/px/fig2.1.n Work on file doc/px/fig2.1.raw Work on file doc/px/pxin4.n Work on file doc/px/pxin0.n Work on file doc/px/fig1.3.n Work on file doc/px/fig1.2.n Work on file doc/pxp/pxpin3.n Work on file doc/pxp/pxpin0.n Work on file doc/pxp/pcrt0.s Work on file doc/pxp/pxpin1.n Work on file doc/pxp/makefile Work on file doc/pxp/pxpin2.n Work on file doc/px/tmac.p Work on file doc/pxp/tmac.p Work on file doc/pxp/stat.c Work on file doc/pascal/makefile Work on file doc/pascal/bigger.p Work on file doc/pascal/fixcomments Work on file doc/pascal/firstout Work on file doc/pascal/firstobjout Work on file doc/pascal/kat3.p Work on file doc/pascal/bigger7.p Work on file doc/pascal/clashout Work on file doc/pascal/bigger5.p Work on file doc/pascal/bigger4.p Work on file doc/pascal/bigger2.p Work on file doc/pascal/clash.p Work on file doc/pascal/bigger3.p Work on file doc/pascal/comments.p Work on file doc/pascal/firstobjout2 Work on file doc/pascal/bigout1 Work on file doc/pascal/contents.n Work on file doc/pascal/bigout2 Work on file doc/pascal/copydata.p Work on file doc/pascal/bigger6.p Work on file doc/pascal/csfix.c Work on file doc/pascal/digits.p Work on file doc/pascal/data Work on file doc/pascal/bigout3 Work on file doc/pascal/bigout4 Work on file doc/pascal/primeout1 Work on file doc/pascal/primeout2 Work on file doc/pascal/digitsout Work on file doc/pascal/synerr2out Work on file doc/pascal/expr.p Work on file doc/pascal/primes Work on file doc/pascal/first.p Work on file doc/pascal/exprout Work on file doc/pascal/sinout1 Work on file doc/pascal/mismout Work on file doc/pascal/typequout Work on file doc/pascal/sinout2 Work on file doc/pascal/primeout3 Work on file doc/pascal/kat.p Work on file doc/pascal/katout Work on file doc/pascal/kat2.p Work on file doc/pascal/kat2out Work on file doc/pascal/katin Work on file doc/pascal/copydataout Work on file doc/pascal/katscript Work on file doc/pascal/xxxxqqqout Work on file doc/pascal/mism.p Work on file doc/pascal/xxxxqqqout2 Work on file doc/pascal/primes-d Work on file doc/pascal/motd Work on file doc/pascal/comments1.p Work on file doc/pascal/synerrout Work on file doc/pascal/commentsout Work on file doc/pascal/primes.p Work on file doc/pascal/primes2.p Work on file doc/pascal/puman0.n Work on file doc/pascal/puman1.n Work on file doc/pascal/puman2.n Work on file doc/pascal/puman3.n Work on file doc/pascal/pumanA.n Work on file doc/pascal/sin1.p Work on file doc/pascal/puman4.n Work on file doc/pascal/puman5.n Work on file doc/pascal/sin2.p Work on file doc/pascal/synerr.p Work on file doc/pascal/synerr2.p Work on file doc/pascal/tmac.p Work on file doc/pascal/typequ.p Work on file doc/pascal/fixkatscript Synthesized-from: 2bsd --- doc/pascal/bigger.p | 24 + doc/pascal/bigger2.p | 24 + doc/pascal/bigger3.p | 24 + doc/pascal/bigger4.p | 26 + doc/pascal/bigger5.p | 26 + doc/pascal/bigger6.p | 26 + doc/pascal/bigger7.p | 26 + doc/pascal/bigout1 | 21 + doc/pascal/bigout2 | 7 + doc/pascal/bigout3 | 36 + doc/pascal/bigout4 | 3 + doc/pascal/clash.p | 9 + doc/pascal/clashout | 2 + doc/pascal/comments.p | 18 + doc/pascal/comments1.p | 18 + doc/pascal/commentsout | 21 + doc/pascal/contents.n | 105 +++ doc/pascal/copydata.p | 15 + doc/pascal/copydataout | 25 + doc/pascal/csfix.c | 172 +++++ doc/pascal/data | 3 + doc/pascal/digits.p | 9 + doc/pascal/digitsout | 8 + doc/pascal/expr.p | 21 + doc/pascal/exprout | 37 + doc/pascal/first.p | 4 + doc/pascal/firstobjout | 2 + doc/pascal/firstobjout2 | 1 + doc/pascal/firstout | 6 + doc/pascal/fixcomments | 6 + doc/pascal/fixkatscript | 6 + doc/pascal/kat.p | 13 + doc/pascal/kat2.p | 23 + doc/pascal/kat2out | 7 + doc/pascal/kat3.p | 23 + doc/pascal/katin | 2 + doc/pascal/katout | 26 + doc/pascal/katscript | 5 + doc/pascal/makefile | 85 +++ doc/pascal/mism.p | 5 + doc/pascal/mismout | 11 + doc/pascal/motd | 3 + doc/pascal/primeout1 | 43 ++ doc/pascal/primeout2 | 50 ++ doc/pascal/primeout3 | 10 + doc/pascal/primes | 6 + doc/pascal/primes-d | 6 + doc/pascal/primes.p | 30 + doc/pascal/primes2.p | 30 + doc/pascal/puman0.n | 127 ++++ doc/pascal/puman1.n | 465 +++++++++++++ doc/pascal/puman2.n | 849 +++++++++++++++++++++++ doc/pascal/puman3.n | 712 ++++++++++++++++++++ doc/pascal/puman4.n | 577 ++++++++++++++++ doc/pascal/puman5.n | 828 +++++++++++++++++++++++ doc/pascal/pumanA.n | 893 ++++++++++++++++++++++++ doc/pascal/sin1.p | 13 + doc/pascal/sin2.p | 13 + doc/pascal/sinout1 | 1 + doc/pascal/sinout2 | 1 + doc/pascal/synerr.p | 9 + doc/pascal/synerr2.p | 7 + doc/pascal/synerr2out | 23 + doc/pascal/synerrout | 20 + doc/pascal/tmac.p | 76 +++ doc/pascal/typequ.p | 10 + doc/pascal/typequout | 2 + doc/pascal/xxxxqqqout | 5 + doc/pascal/xxxxqqqout2 | 1 + doc/px/fig1.1.n | 45 ++ doc/px/fig1.2.n | 47 ++ doc/px/fig1.3.n | 27 + doc/px/fig2.1.n | 92 +++ doc/px/fig2.1.raw | 92 +++ doc/px/fig2.2.n | 27 + doc/px/makefile | 4 + doc/px/pxin0.n | 98 +++ doc/px/pxin1.n | 559 ++++++++++++++++ doc/px/pxin2.n | 905 +++++++++++++++++++++++++ doc/px/pxin3.n | 303 +++++++++ doc/px/pxin4.n | 72 ++ doc/px/tmac.p | 77 +++ doc/pxp/makefile | 2 + doc/pxp/pcrt0.s | 55 ++ doc/pxp/pxpin0.n | 114 ++++ doc/pxp/pxpin1.n | 677 +++++++++++++++++++ doc/pxp/pxpin2.n | 1415 +++++++++++++++++++++++++++++++++++++++ doc/pxp/pxpin3.n | 441 ++++++++++++ doc/pxp/stat.c | 109 +++ doc/pxp/tmac.p | 77 +++ 90 files changed, 10979 insertions(+) create mode 100644 doc/pascal/bigger.p create mode 100644 doc/pascal/bigger2.p create mode 100644 doc/pascal/bigger3.p create mode 100644 doc/pascal/bigger4.p create mode 100644 doc/pascal/bigger5.p create mode 100644 doc/pascal/bigger6.p create mode 100644 doc/pascal/bigger7.p create mode 100644 doc/pascal/bigout1 create mode 100644 doc/pascal/bigout2 create mode 100644 doc/pascal/bigout3 create mode 100644 doc/pascal/bigout4 create mode 100644 doc/pascal/clash.p create mode 100644 doc/pascal/clashout create mode 100644 doc/pascal/comments.p create mode 100644 doc/pascal/comments1.p create mode 100644 doc/pascal/commentsout create mode 100644 doc/pascal/contents.n create mode 100644 doc/pascal/copydata.p create mode 100644 doc/pascal/copydataout create mode 100644 doc/pascal/csfix.c create mode 100644 doc/pascal/data create mode 100644 doc/pascal/digits.p create mode 100644 doc/pascal/digitsout create mode 100644 doc/pascal/expr.p create mode 100644 doc/pascal/exprout create mode 100644 doc/pascal/first.p create mode 100644 doc/pascal/firstobjout create mode 100644 doc/pascal/firstobjout2 create mode 100644 doc/pascal/firstout create mode 100644 doc/pascal/fixcomments create mode 100644 doc/pascal/fixkatscript create mode 100644 doc/pascal/kat.p create mode 100644 doc/pascal/kat2.p create mode 100644 doc/pascal/kat2out create mode 100644 doc/pascal/kat3.p create mode 100644 doc/pascal/katin create mode 100644 doc/pascal/katout create mode 100644 doc/pascal/katscript create mode 100755 doc/pascal/makefile create mode 100644 doc/pascal/mism.p create mode 100644 doc/pascal/mismout create mode 100644 doc/pascal/motd create mode 100644 doc/pascal/primeout1 create mode 100644 doc/pascal/primeout2 create mode 100644 doc/pascal/primeout3 create mode 100644 doc/pascal/primes create mode 100644 doc/pascal/primes-d create mode 100644 doc/pascal/primes.p create mode 100644 doc/pascal/primes2.p create mode 100644 doc/pascal/puman0.n create mode 100644 doc/pascal/puman1.n create mode 100644 doc/pascal/puman2.n create mode 100644 doc/pascal/puman3.n create mode 100644 doc/pascal/puman4.n create mode 100644 doc/pascal/puman5.n create mode 100644 doc/pascal/pumanA.n create mode 100644 doc/pascal/sin1.p create mode 100644 doc/pascal/sin2.p create mode 100644 doc/pascal/sinout1 create mode 100644 doc/pascal/sinout2 create mode 100644 doc/pascal/synerr.p create mode 100644 doc/pascal/synerr2.p create mode 100644 doc/pascal/synerr2out create mode 100644 doc/pascal/synerrout create mode 100644 doc/pascal/tmac.p create mode 100644 doc/pascal/typequ.p create mode 100644 doc/pascal/typequout create mode 100644 doc/pascal/xxxxqqqout create mode 100644 doc/pascal/xxxxqqqout2 create mode 100644 doc/px/fig1.1.n create mode 100644 doc/px/fig1.2.n create mode 100644 doc/px/fig1.3.n create mode 100644 doc/px/fig2.1.n create mode 100644 doc/px/fig2.1.raw create mode 100644 doc/px/fig2.2.n create mode 100755 doc/px/makefile create mode 100644 doc/px/pxin0.n create mode 100644 doc/px/pxin1.n create mode 100644 doc/px/pxin2.n create mode 100644 doc/px/pxin3.n create mode 100644 doc/px/pxin4.n create mode 100644 doc/px/tmac.p create mode 100644 doc/pxp/makefile create mode 100644 doc/pxp/pcrt0.s create mode 100644 doc/pxp/pxpin0.n create mode 100644 doc/pxp/pxpin1.n create mode 100644 doc/pxp/pxpin2.n create mode 100644 doc/pxp/pxpin3.n create mode 100644 doc/pxp/stat.c create mode 100644 doc/pxp/tmac.p diff --git a/doc/pascal/bigger.p b/doc/pascal/bigger.p new file mode 100644 index 0000000000..d342b096ae --- /dev/null +++ b/doc/pascal/bigger.p @@ -0,0 +1,24 @@ +(* + * Graphic representation of a function + * f(x) = exp(-x) * sin(2 * pi * x) + *) +program graph1(output); +const + d = 0.0625; (* 1/16, 16 lines for interval [x, x+1] *) + s = 32; (* 32 character width for interval [x, x+1] + h = 34; (* Character position of x-axis *) + c = 6.28138; (* 2 * pi *) + lim = 32; +var + x, y: real; + i, n: integer; +begin + for i := 0 to lim begin + x := d / i; + y := exp(-x9 * sin(i * x); + n := Round(s * y) + h; + repeat + write(' '); + n := n - 1 + writeln('*') +end. diff --git a/doc/pascal/bigger2.p b/doc/pascal/bigger2.p new file mode 100644 index 0000000000..e0323497c7 --- /dev/null +++ b/doc/pascal/bigger2.p @@ -0,0 +1,24 @@ +(* + * Graphic representation of a function + * f(x) = exp(-x) * sin(2 * pi * x) + *) +program graph1(output); +const + d = 0.0625; (* 1/16, 16 lines for interval [x, x+1] *) + s = 32; (* 32 character width for interval [x, x+1] + h = 34; (* Character position of x-axis *) + c = 6.28138; (* 2 * pi *) + lim = 32; +var + x, y: real; + i, n: integer; +begin + for i := 0 to lim begin + x := d / i; + y := exp(-x9 * sin(i * x); + n := Round(s * y) + h; + repeat + write(' '); + n := n - 1 + writeln('*') +end. diff --git a/doc/pascal/bigger3.p b/doc/pascal/bigger3.p new file mode 100644 index 0000000000..c63be6853a --- /dev/null +++ b/doc/pascal/bigger3.p @@ -0,0 +1,24 @@ +\0\0\0\0\01\0\0(* +\0\0\0\0\02\0\0\0* Graphic representation of a function +\0\0\0\0\03\0\0\0* f(x) = exp(-x) * sin(2 * pi * x) +\0\0\0\0\04\0\0\0*) +\0\0\0\0\05\0\0program graph1(output); +\0\0\0\0\06\0\0const +\0\0\0\0\07\0\0\0\0\0\0\0\0\0\0d = 0.0625; (* 1/16, 16 lines for interval [x, x+1] *) +\0\0\0\0\08\0\0\0\0\0\0\0\0\0\0s = 32; (* 32 character width for interval [x, x+1] +\0\0\0\0\09\0\0\0\0\0\0\0\0\0\0h = 34; (* Character position of x-axis *) +\0\0\0\010\0\0\0\0\0\0\0\0\0\0c = 6.28138; (* 2 * pi *) +\0\0\0\011\0\0\0\0\0\0\0\0\0\0lim = 32; +\0\0\0\012\0\0var +\0\0\0\013\0\0\0\0\0\0\0\0\0\0x, y: real; +\0\0\0\014\0\0\0\0\0\0\0\0\0\0i, n: integer; +\0\0\0\015\0\0begin +\0\0\0\016\0\0\0\0\0\0\0\0\0\0for i := 0 to lim begin +\0\0\0\017\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0x := d / i; +\0\0\0\018\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0y := exp(-x9 * sin(i * x); +\0\0\0\019\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0n := Round(s * y) + h; +\0\0\0\020\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0repeat +\0\0\0\021\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0write(' '); +\0\0\0\022\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0n := n - 1 +\0\0\0\023\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0writeln('*') +\0\0\0\024\0\0end. diff --git a/doc/pascal/bigger4.p b/doc/pascal/bigger4.p new file mode 100644 index 0000000000..5a16ef40a3 --- /dev/null +++ b/doc/pascal/bigger4.p @@ -0,0 +1,26 @@ +(* + * Graphic representation of a function + * f(x) = exp(-x) * sin(2 * pi * x) + *) +program graph1(output); +const + d = 0.0625; (* 1/16, 16 lines for interval [x, x+1] *) + s = 32; (* 32 character width for interval [x, x+1] *) + h = 34; (* Character position of x-axis *) + c = 6.28138; (* 2 * pi *) + lim = 32; +var + x, y: real; + i, n: integer; +begin + for i := 0 to lim do begin + x := d / i; + y := exp(-x) * sin(c * x); + n := round(s * y) + h; + repeat + write(' '); + n := n - 1 + until n = 0; + writeln('*') + end +end. diff --git a/doc/pascal/bigger5.p b/doc/pascal/bigger5.p new file mode 100644 index 0000000000..5a16ef40a3 --- /dev/null +++ b/doc/pascal/bigger5.p @@ -0,0 +1,26 @@ +(* + * Graphic representation of a function + * f(x) = exp(-x) * sin(2 * pi * x) + *) +program graph1(output); +const + d = 0.0625; (* 1/16, 16 lines for interval [x, x+1] *) + s = 32; (* 32 character width for interval [x, x+1] *) + h = 34; (* Character position of x-axis *) + c = 6.28138; (* 2 * pi *) + lim = 32; +var + x, y: real; + i, n: integer; +begin + for i := 0 to lim do begin + x := d / i; + y := exp(-x) * sin(c * x); + n := round(s * y) + h; + repeat + write(' '); + n := n - 1 + until n = 0; + writeln('*') + end +end. diff --git a/doc/pascal/bigger6.p b/doc/pascal/bigger6.p new file mode 100644 index 0000000000..9ba7ceaeaf --- /dev/null +++ b/doc/pascal/bigger6.p @@ -0,0 +1,26 @@ +\0\0\0\0\01\0\0(* +\0\0\0\0\02\0\0\0* Graphic representation of a function +\0\0\0\0\03\0\0\0* f(x) = exp(-x) * sin(2 * pi * x) +\0\0\0\0\04\0\0\0*) +\0\0\0\0\05\0\0program graph1(output); +\0\0\0\0\06\0\0const +\0\0\0\0\07\0\0\0\0\0\0\0\0\0\0d = 0.0625; (* 1/16, 16 lines for interval [x, x+1] *) +\0\0\0\0\08\0\0\0\0\0\0\0\0\0\0s = 32; (* 32 character width for interval [x, x+1] *) +\0\0\0\0\09\0\0\0\0\0\0\0\0\0\0h = 34; (* Character position of x-axis *) +\0\0\0\010\0\0\0\0\0\0\0\0\0\0c = 6.28138; (* 2 * pi *) +\0\0\0\011\0\0\0\0\0\0\0\0\0\0lim = 32; +\0\0\0\012\0\0var +\0\0\0\013\0\0\0\0\0\0\0\0\0\0x, y: real; +\0\0\0\014\0\0\0\0\0\0\0\0\0\0i, n: integer; +\0\0\0\015\0\0begin +\0\0\0\016\0\0\0\0\0\0\0\0\0\0for i := 0 to lim do begin +\0\0\0\017\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0x := d / i; +\0\0\0\018\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0y := exp(-x) * sin(c * x); +\0\0\0\019\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0n := round(s * y) + h; +\0\0\0\020\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0repeat +\0\0\0\021\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0write(' '); +\0\0\0\022\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0n := n - 1 +\0\0\0\023\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0until n = 0; +\0\0\0\024\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0writeln('*') +\0\0\0\025\0\0\0\0\0\0\0\0\0\0end +\0\0\0\026\0\0end. diff --git a/doc/pascal/bigger7.p b/doc/pascal/bigger7.p new file mode 100644 index 0000000000..b4cd01d5d8 --- /dev/null +++ b/doc/pascal/bigger7.p @@ -0,0 +1,26 @@ +(* + * Graphic representation of a function + * f(x) = exp(-x) * sin(2 * pi * x) + *) +program graph1(output); +const + d = 0.0625; (* 1/16, 16 lines for interval [x, x+1] *) + s = 32; (* 32 character width for interval [x, x+1] *) + h = 34; (* Character position of x-axis *) + c = 6.28138; (* 2 * pi *) + lim = 32; +var + x, y: real; + i, n: integer; +begin + for i := 0 to lim do begin + x := d * i; + y := exp(-x) * sin(c * x); + n := round(s * y) + h; + repeat + write(' '); + n := n - 1 + until n = 0; + writeln('*') + end +end. diff --git a/doc/pascal/bigout1 b/doc/pascal/bigout1 new file mode 100644 index 0000000000..08deb3de9e --- /dev/null +++ b/doc/pascal/bigout1 @@ -0,0 +1,21 @@ + 9 h = 34; (* Character position of x-axis *) +w \l'\w` 9 h = 34; (`u-\w`w `u\&\(rh'\l'(\w`*`u-\w`^`u)/2 '\(ua\l'(\w`*`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' (* in a (* ... *) comment + 16 for i := 0 to lim begin +e \l'\w`w `u-\w`e `u '\l'\w` 16 for i := 0 to lim `u-\w`w `u\&\(rh'\l'(\w`b`u-\w`^`u)/2 '\(ua\l'(\w`b`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted keyword do + 18 y := exp(-x9 * sin(i * x); +E \l'\w`w `u-\w`E `u '\l'\w` 18 y := exp(-`u-\w`w `u\&\(rh'\l'(\w`x`u-\w`^`u)/2 '\(ua\l'(\w`x`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Undefined variable +e \l'\w`w `u-\w`e `u '\l'\w` 18 y := exp(-x9 * sin(i * x)`u-\w`w `u\&\(rh'\l'(\w`;`u-\w`^`u)/2 '\(ua\l'(\w`;`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted ')' + 19 n := Round(s * y) + h; +E \l'\w`w `u-\w`E `u '\l'\w` 19 n := `u-\w`w `u\&\(rh'\l'(\w`R`u-\w`^`u)/2 '\(ua\l'(\w`R`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Undefined function +E \l'\w`w `u-\w`E `u '\l'\w` 19 n := Round(s * y) + `u-\w`w `u\&\(rh'\l'(\w`h`u-\w`^`u)/2 '\(ua\l'(\w`h`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Undefined variable + 23 writeln('*') +e \l'\w`w `u-\w`e `u '\l'\w` 23 `u-\w`w `u\&\(rh'\l'(\w`w`u-\w`^`u)/2 '\(ua\l'(\w`w`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted ';' + 24 end. +E \l'\w`w `u-\w`E `u '\l'\w` 24 `u-\w`w `u\&\(rh'\l'(\w`e`u-\w`^`u)/2 '\(ua\l'(\w`e`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Expected keyword until +e \l'\w`w `u-\w`e `u '\l'\w` 24 end`u-\w`w `u\&\(rh'\l'(\w`.`u-\w`^`u)/2 '\(ua\l'(\w`.`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted keyword end matching begin on line 15 +In program graph1: + \l'(\w`E`u-\w`w`u)/2 'w\l'(\w`E`u-\w`w`u)/2 ' - constant c is never used + E - x9 undefined on line 18 + E - Round undefined on line 19 + E - h undefined on line 19 +Execution suppressed due to compilation errors diff --git a/doc/pascal/bigout2 b/doc/pascal/bigout2 new file mode 100644 index 0000000000..cd5412901a --- /dev/null +++ b/doc/pascal/bigout2 @@ -0,0 +1,7 @@ +Execution begins... +Floating divide by zero + + Error at "graph1"+2 near line 17 + +Execution terminated abnormally +2 statements executed in 0.04 seconds cpu time diff --git a/doc/pascal/bigout3 b/doc/pascal/bigout3 new file mode 100644 index 0000000000..b529b6a054 --- /dev/null +++ b/doc/pascal/bigout3 @@ -0,0 +1,36 @@ +Execution begins... + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * +Execution terminated +2550 statements executed in 0.21 seconds cpu time diff --git a/doc/pascal/bigout4 b/doc/pascal/bigout4 new file mode 100644 index 0000000000..598d8ef869 --- /dev/null +++ b/doc/pascal/bigout4 @@ -0,0 +1,3 @@ +Execution begins... +Execution terminated +2550 statements executed in 0.31 seconds cpu time diff --git a/doc/pascal/clash.p b/doc/pascal/clash.p new file mode 100644 index 0000000000..4a07405d46 --- /dev/null +++ b/doc/pascal/clash.p @@ -0,0 +1,9 @@ +program clash(output); +var + i: integer; + c: char; +begin + i := 1; + c := i; + write(c, i) +end. diff --git a/doc/pascal/clashout b/doc/pascal/clashout new file mode 100644 index 0000000000..a4d46d2989 --- /dev/null +++ b/doc/pascal/clashout @@ -0,0 +1,2 @@ +E 7 - Type clash: integer is incompatible with char + ... Type of expression clashed with type of variable in assignment diff --git a/doc/pascal/comments.p b/doc/pascal/comments.p new file mode 100644 index 0000000000..b07ddfc6bd --- /dev/null +++ b/doc/pascal/comments.p @@ -0,0 +1,18 @@ +{ This is a left marginal comment. } +program hello(output); +var i : integer; {This is a trailing comment} +j : integer; {This is a right marginal comment} +k : array [ 1..10] of array [1..10] of integer; {Marginal, but past the margin} +{ + An aligned, multi-line comment + which explains what this program is + all about +} +begin +i := 1; {Trailing i comment} +{A left marginal comment} + {An aligned comment} +j := 1; {Right marginal comment} +k[1] := 1; +writeln(i, j, k[1]) +end. diff --git a/doc/pascal/comments1.p b/doc/pascal/comments1.p new file mode 100644 index 0000000000..8e7de6c427 --- /dev/null +++ b/doc/pascal/comments1.p @@ -0,0 +1,18 @@ +{ This is a left marginal comment. } +program hello(output); +var i : integer; {This is a trailing comment} +j : integer; {This is a right marginal comment} +k : array [ 1..10] of array [1..10] of integer; {Marginal, but past the margin} +{ + An aligned, multi-line comment + which explains what this program is + all about +} +begin +i := 1; {Trailing i comment} +{A left marginal comment} + {An aligned comment} +j := 1; {Right marginal comment} +k[1] := 1; +writeln(i, j, k[1]) +end. diff --git a/doc/pascal/commentsout b/doc/pascal/commentsout new file mode 100644 index 0000000000..afc089e8c8 --- /dev/null +++ b/doc/pascal/commentsout @@ -0,0 +1,21 @@ +.ta 3.25i +{ This is a left marginal comment. } + +program hello(output); +var + i: integer; {This is a trailing comment} + j: integer; {This is a right marginal comment} + k: array [1..10] of array [1..10] of integer; {Marginal, but past the margin} +{ + An aligned, multi-line comment + which explains what this program is + all about +} +begin + i := 1; {Trailing i comment} +{A left marginal comment} + {An aligned comment} + j := 1; {Right marginal comment} + k[1] := 1; + writeln(i, j, k[1]) +end. diff --git a/doc/pascal/contents.n b/doc/pascal/contents.n new file mode 100644 index 0000000000..1d6e065fa8 --- /dev/null +++ b/doc/pascal/contents.n @@ -0,0 +1,105 @@ +.if !\n(xx .so /usr/lib/tmac.s +.nr LL 6.5i +.TL +UNIX Pascal User's Manual +.br +Version 1.0 \- November, 1977 +.LP +.ds CF "- \\n(PN - +.ds CH +.af PN i +.ce +.I +.LG +.LG +Table of Contents +.NL +.R +.sp .5i +.KS +.ta 5.75i +.tc . +.nf +.KE +.KS +Introduction \0\01 +.KE +.sp 2 +.KS +.B +1. Sources of Information \0\02 +.R +.sp + .1 Where to get documentation \0\02 + .2 Computer Center short courses \0\02 + .3 Documentation describing UNIX \0\02 + .4 Text editing documents \0\03 + .5 Pascal documents \- the language \0\04 + .6 Pascal documents \- the UNIX implementation \0\04 + .7 References \0\05 +.KE +.sp 2 +.KS +.B +2. Basic UNIX Pascal \0\07 +.R +.sp + .1 A first program \0\07 + .2 A larger program \010 + .3 Correcting the first errors \011 + .4 Executing the second example \014 + .5 Formatting the program listing \016 + .6 Execution profiling \016 +.KE +.sp 2 +.KS +.B +3. Error diagnostics \020 +.R +.sp + .1 Translator syntax errors \020 + .2 Translator semantic errors \023 + .3 Translator panics, i/o errors \027 + .4 Run-time errors \027 +.KE +.sp 2 +.KS +.B +4. Input/output \029 +.R +.sp + .1 Introduction \029 + .2 Eof and eoln \030 + .3 More about eoln \031 + .4 Output buffering \032 + .5 Files, reset and rewrite \032 + .6 Argc and argv \033 +.KE +.sp 2 +.KS +.B +5. Details on components of the system \036 +.R +.sp + .1 Options \036 + .2 Pi (and pix) \037 + .3 Px \039 + .4 Pxp \039 + .5 Formatting programs using pxp \040 + .6 Pcc and carriage control \042 + .7 Pxref \042 + .8 Pascals \042 + .9 Multi-file programs \042 +.KE +.sp 2 +.KS +.B +A. Appendix to Wirth's Pascal Report \044 +.R +.sp + .1 Extensions to the language Pascal \045 + .2 Resolution of the undefined specifications \045 + .3 Restrictions and limitations \048 + .4 Added types, operators, procedures and functions \048 + .5 Remarks on standard and portable Pascal \050 +.KE diff --git a/doc/pascal/copydata.p b/doc/pascal/copydata.p new file mode 100644 index 0000000000..ecf237c052 --- /dev/null +++ b/doc/pascal/copydata.p @@ -0,0 +1,15 @@ +program copydata(data, output); +var + ch: char; + data: text; +begin + reset(data); + while not eof(data) do begin + while not eoln(data) do begin + read(data, ch); + write(ch) + end; + readln(data); + writeln + end +end { copydata }. diff --git a/doc/pascal/copydataout b/doc/pascal/copydataout new file mode 100644 index 0000000000..2d060e6efb --- /dev/null +++ b/doc/pascal/copydataout @@ -0,0 +1,25 @@ +Berkeley Pascal PI -- Version 1.1 (January 4, 1979) + +Sat Mar 31 11:50 1979 copydata.p + +\0\0\0\0\01\0\0program copydata(data, output); +\0\0\0\0\02\0\0var +\0\0\0\0\03\0\0\0\0\0\0ch: char; +\0\0\0\0\04\0\0\0\0\0\0data: text; +\0\0\0\0\05\0\0begin +\0\0\0\0\06\0\0\0\0\0\0reset(data); +\0\0\0\0\07\0\0\0\0\0\0while not eof(data) do begin +\0\0\0\0\08\0\0\0\0\0\0\0\0\0\0while not eoln(data) do begin +\0\0\0\0\09\0\0\0\0\0\0\0\0\0\0\0\0\0\0read(data, ch); +\0\0\0\010\0\0\0\0\0\0\0\0\0\0\0\0\0\0write(ch) +\0\0\0\011\0\0\0\0\0\0\0\0\0\0end; +\0\0\0\012\0\0\0\0\0\0\0\0\0\0readln(data); +\0\0\0\013\0\0\0\0\0\0\0\0\0\0writeln +\0\0\0\014\0\0\0\0\0\0end +\0\0\0\015\0\0end { copydata }. +Execution begins... +line one. +line two. +line three is the end. +Execution terminated +134\0statements executed in 0.01 seconds cpu time diff --git a/doc/pascal/csfix.c b/doc/pascal/csfix.c new file mode 100644 index 0000000000..e78e472f7c --- /dev/null +++ b/doc/pascal/csfix.c @@ -0,0 +1,172 @@ +#include +/* + * csfix - fix constant spacing for error message flags in troff + * + * Bill Joy UCB September 11, 1977 + * + * This would be better written in snobol! + * + * Normally fixes error flags in a pi listing + * Optional - causes fixing of '---' and initial blank widthin a pxp profile. + */ + +char flag, dflag; + +main(argc, argv) + int argc; + char *argv[]; +{ + + argc--, argv++; + if (argc > 0 && argv[0][0] == '-' && argv[0][1] == 'd') + dflag++, argc--, argv++; + if (argc > 0 && argv[0][0] == '-') + flag++, argc--, argv++; + if (argc != 0) { + write(2, "Usage: csfix\n", 13); + exit(1); + } + while (getline()) { + if (errline()) { + flag ? fixpxp() : reformat(); + continue; + } + if (flag) { + fixdigits(); + continue; + } + if (spwarn()) + continue; + if (nontriv()) + save(); + if (dflag) + fixdigits(); + else + putline(); + } + exit(0); +} + +char line[160], flagee[160]; + +getline() +{ + register char *cp, c; + + for (cp = line, c = getchar(); c != '\n' && c != EOF; c = getchar()) + *cp++ = c; + if (c == EOF) + return (0); + *cp = 0; + return (1); +} + +errline() +{ + register int i; + register char *cp; + + for (cp = line; cp[0] && cp[1] && cp[2]; cp++) + if (cp[0] == '-' && cp[1] == '-' && cp[2] == '-') + return (1); + return (0); +} + +reformat() +{ + register char *cp, c, *tail; + + printf("%2.2s", line); + if (line[0] != 'w') + printf("\\l'\\w`w `u-\\w`%2.2s`u '", line); + for (cp = line; *cp != 0 && *cp != '^'; cp++) + continue; + tail = cp + 1; + if (cp[-1] == '\b' && cp[-2] == '|') + cp =- 2; + c = flagee[cp - line]; + flagee[cp - line] = 0; + printf("\\l'\\w`%s`u-\\w`w `u\\&\\(rh'", flagee); + flagee[cp - line] = c; + printf("\\l'(\\w`%c`u-\\w`^`u)/2 '", c); + printf("\\(ua"); + printf("\\l'(\\w`%c`u-\\w`^`u)/2 '", c); + printf("\\l'\\w`---`u\\&\\(rh'%s\n", tail+3); +} + +nontriv() +{ + + switch (line[0]) { + case 'E': + case 'e': + case 'w': + case 's': + case 0: + return (0); + } + return (1); +} + +save() +{ + + strcpy(flagee, line); +} + +putline() +{ + + printf("%s\n", flag ? digitty(0) : line); +} + +spwarn() +{ + + if (line[0] != ' ' || line[1] != ' ' || line[2] != 'w') + return (0); + printf(" \\l'(\\w`E`u-\\w`w`u)/2 'w\\l'(\\w`E`u-\\w`w`u)/2 '"); + printf(&line[3]); + printf("\n"); + return (1); +} + +fixpxp() +{ + register char *cp; + + for (cp = line; *cp != '-'; cp++) + continue; + *cp = 0; + printf("%s\\l'\\w`\\0\\0\\0\\0`u-\\w`.`u\\&\\(rh'%s\n", digitty(1), cp + 3); +} + +digitty(yup) + char yup; +{ + register char *cp, *dp, *lp; + + for (lp = line; *lp && *lp != '|'; lp++) + continue; + if (yup == 0 && !*lp) + return (line); + for (cp = line, dp = flagee; cp < lp; cp++) + if (*cp == ' ') + *dp++ = '\\', *dp++ = '0'; + else + *dp++ = *cp; + strcpy(dp, cp); + return (flagee); +} + +fixdigits() +{ + register char *cp, c; + + for (cp = line; *cp == ' ' || *cp >= '0' && *cp <= '9'; cp++) + continue; + c = *cp, *cp = 0; + digitty(1); + *cp = c; + printf("%s%s\n", flagee, cp); +} diff --git a/doc/pascal/data b/doc/pascal/data new file mode 100644 index 0000000000..3f9cfb50ca --- /dev/null +++ b/doc/pascal/data @@ -0,0 +1,3 @@ +line one. +line two. +line three is the end. diff --git a/doc/pascal/digits.p b/doc/pascal/digits.p new file mode 100644 index 0000000000..1e59d8dafb --- /dev/null +++ b/doc/pascal/digits.p @@ -0,0 +1,9 @@ +program digits(output); +var r: real; +begin +r := 0.; +r := .0; +r := 1.e10; +r := .05e-10; +writeln(r) +end. diff --git a/doc/pascal/digitsout b/doc/pascal/digitsout new file mode 100644 index 0000000000..e2e6ea5866 --- /dev/null +++ b/doc/pascal/digitsout @@ -0,0 +1,8 @@ + 4 r := 0.; +e \l'\w`w `u-\w`e `u '\l'\w` 4 r := 0.`u-\w`w `u\&\(rh'\l'(\w`;`u-\w`^`u)/2 '\(ua\l'(\w`;`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Digits required after decimal point + 5 r := .0; +e \l'\w`w `u-\w`e `u '\l'\w` 5 r := `u-\w`w `u\&\(rh'\l'(\w`.`u-\w`^`u)/2 '\(ua\l'(\w`.`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Digits required before decimal point + 6 r := 1.e10; +e \l'\w`w `u-\w`e `u '\l'\w` 6 r := 1.`u-\w`w `u\&\(rh'\l'(\w`e`u-\w`^`u)/2 '\(ua\l'(\w`e`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Digits required after decimal point + 7 r := .05e-10; +e \l'\w`w `u-\w`e `u '\l'\w` 7 r := `u-\w`w `u\&\(rh'\l'(\w`.`u-\w`^`u)/2 '\(ua\l'(\w`.`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Digits required before decimal point diff --git a/doc/pascal/expr.p b/doc/pascal/expr.p new file mode 100644 index 0000000000..60109af8c7 --- /dev/null +++ b/doc/pascal/expr.p @@ -0,0 +1,21 @@ +program x(output); +var + a: set of char; + b: Boolean; + c: (red, green, blue); + p: ^ integer; + A: alfa; + B: packed array [1..5] of char; +begin + b := true; + c := red; + new(p); + a := []; + A := 'Hello, yellow'; + b := a and b; + a := a * 3; + if input < 2 then writeln('boo'); + if p <= 2 then writeln('sure nuff'); + if A = B then writeln('same'); + if c = true then writeln('hue''s and color''s') +end. diff --git a/doc/pascal/exprout b/doc/pascal/exprout new file mode 100644 index 0000000000..bb1c4fdbf6 --- /dev/null +++ b/doc/pascal/exprout @@ -0,0 +1,37 @@ +Berkeley Pascal PI -- Version 1.1 (January 4, 1979) + +Sat Mar 31 11:50 1979 expr.p + + 1 program x(output); + 2 var + 3 a: set of char; + 4 b: Boolean; + 5 c: (red, green, blue); + 6 p: ^ integer; + 7 A: alfa; + 8 B: packed array [1..5] of char; + 9 begin + 10 b := true; + 11 c := red; + 12 new(p); + 13 a := []; + 14 A := 'Hello, yellow'; + 15 b := a and b; + 16 a := a * 3; + 17 if input < 2 then writeln('boo'); + 18 if p <= 2 then writeln('sure nuff'); + 19 if A = B then writeln('same'); + 20 if c = true then writeln('hue''s and color''s') + 21 end. +E 14 - Constant string too long +E 15 - Left operand of and must be Boolean, not set +E 16 - Cannot mix sets with integers and reals as operands of * +E 17 - files may not participate in comparisons +E 18 - pointers and integers cannot be compared - operator was <= +E 19 - Strings not same length in = comparison +E 20 - scalars and Booleans cannot be compared - operator was = +e 20 - Input is used but not defined in the program statement +In program x: + w - constant green is never used + w - constant blue is never used + w - variable B is used but never set diff --git a/doc/pascal/first.p b/doc/pascal/first.p new file mode 100644 index 0000000000..19196944e8 --- /dev/null +++ b/doc/pascal/first.p @@ -0,0 +1,4 @@ +program first(output) +begin + writeln('Hello, world!') +end. diff --git a/doc/pascal/firstobjout b/doc/pascal/firstobjout new file mode 100644 index 0000000000..0129da12e0 --- /dev/null +++ b/doc/pascal/firstobjout @@ -0,0 +1,2 @@ +Hello, world! +1 statement executed in 0.02 seconds cpu time diff --git a/doc/pascal/firstobjout2 b/doc/pascal/firstobjout2 new file mode 100644 index 0000000000..af5626b4a1 --- /dev/null +++ b/doc/pascal/firstobjout2 @@ -0,0 +1 @@ +Hello, world! diff --git a/doc/pascal/firstout b/doc/pascal/firstout new file mode 100644 index 0000000000..1c61517a55 --- /dev/null +++ b/doc/pascal/firstout @@ -0,0 +1,6 @@ + 2 begin +e \l'\w`w `u-\w`e `u '\l'\w` 2 `u-\w`w `u\&\(rh'\l'(\w`b`u-\w`^`u)/2 '\(ua\l'(\w`b`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted ';' +Execution begins... +Hello, world! +Execution terminated +1 statement executed in 0.04 seconds cpu time diff --git a/doc/pascal/fixcomments b/doc/pascal/fixcomments new file mode 100644 index 0000000000..5201c8f7eb --- /dev/null +++ b/doc/pascal/fixcomments @@ -0,0 +1,6 @@ +1i +.ta 3.25i +. +g/ *{/s// {/ +w +q diff --git a/doc/pascal/fixkatscript b/doc/pascal/fixkatscript new file mode 100644 index 0000000000..73948198de --- /dev/null +++ b/doc/pascal/fixkatscript @@ -0,0 +1,6 @@ +1t1 +1s/.*/\\*b&\\fR/ +3t3 +3s/.*/\\*b&\\fR/ +w +q diff --git a/doc/pascal/kat.p b/doc/pascal/kat.p new file mode 100644 index 0000000000..6d804533e0 --- /dev/null +++ b/doc/pascal/kat.p @@ -0,0 +1,13 @@ +program kat(input, output); +var + ch: char; +begin + while not eof do begin + while not eoln do begin + read(ch); + write(ch) + end; + readln; + writeln + end +end { kat }. diff --git a/doc/pascal/kat2.p b/doc/pascal/kat2.p new file mode 100644 index 0000000000..0dbc01a125 --- /dev/null +++ b/doc/pascal/kat2.p @@ -0,0 +1,23 @@ +program kat(input, output); +var + ch: char; + i: integer; + name: packed array [1..100] of char; +begin + i := 1; + repeat + if i < argc then begin + argv(i, name); + reset(input, name); + i := i + 1 + end; + while not eof do begin + while not eoln do begin + read(ch); + write(ch) + end; + readln; + writeln + end + until i >= argc +end { kat }. diff --git a/doc/pascal/kat2out b/doc/pascal/kat2out new file mode 100644 index 0000000000..100f05c88e --- /dev/null +++ b/doc/pascal/kat2out @@ -0,0 +1,7 @@ +\0\0\0\0\02\0\0\0\0\03\0\0\0\0\05\0\0\0\0\07\0\0\0\011\0\0\0\013\0\0\0\017\0\0\0\019\0\0\0\023\0\0\0\029 +\0\0\0\031\0\0\0\037\0\0\0\041\0\0\0\043\0\0\0\047\0\0\0\053\0\0\0\059\0\0\0\061\0\0\0\067\0\0\0\071 +\0\0\0\073\0\0\0\079\0\0\0\083\0\0\0\089\0\0\0\097\0\0\0101\0\0\0103\0\0\0107\0\0\0109\0\0\0113 +\0\0\0127\0\0\0131\0\0\0137\0\0\0139\0\0\0149\0\0\0151\0\0\0157\0\0\0163\0\0\0167\0\0\0173 +\0\0\0179\0\0\0181\0\0\0191\0\0\0193\0\0\0197\0\0\0199\0\0\0211\0\0\0223\0\0\0227\0\0\0229 + +930\0statements executed in 0.24 seconds cpu time diff --git a/doc/pascal/kat3.p b/doc/pascal/kat3.p new file mode 100644 index 0000000000..411205caf7 --- /dev/null +++ b/doc/pascal/kat3.p @@ -0,0 +1,23 @@ +program kat(input, output); +var + ch: char; + i: integer; + name: packed array [1..100] of char; +begin + i := 1; + repeat + if i < argc then begin + argv(i, name); + reset(input, name); + i := i + 1 + end; + while not eof do begin + while not eoln do begin + read(ch); + write(ch) + end; + readln; + writeln + end + until i >= argc +end { kat }. diff --git a/doc/pascal/katin b/doc/pascal/katin new file mode 100644 index 0000000000..220793bf91 --- /dev/null +++ b/doc/pascal/katin @@ -0,0 +1,2 @@ +This is a line of text. +The next line contains only an end-of-file (an invisible control-d!) diff --git a/doc/pascal/katout b/doc/pascal/katout new file mode 100644 index 0000000000..2c5e46b986 --- /dev/null +++ b/doc/pascal/katout @@ -0,0 +1,26 @@ +Berkeley Pascal PI -- Version 1.1 (January 4, 1979) + +Sat Mar 31 11:50 1979 kat.p + +\0\0\0\0\01\0\0program kat(input, output); +\0\0\0\0\02\0\0var +\0\0\0\0\03\0\0\0\0\0\0ch: char; +\0\0\0\0\04\0\0begin +\0\0\0\0\05\0\0\0\0\0\0while not eof do begin +\0\0\0\0\06\0\0\0\0\0\0\0\0\0\0while not eoln do begin +\0\0\0\0\07\0\0\0\0\0\0\0\0\0\0\0\0\0\0read(ch); +\0\0\0\0\08\0\0\0\0\0\0\0\0\0\0\0\0\0\0write(ch) +\0\0\0\0\09\0\0\0\0\0\0\0\0\0\0end; +\0\0\0\010\0\0\0\0\0\0\0\0\0\0readln; +\0\0\0\011\0\0\0\0\0\0\0\0\0\0writeln +\0\0\0\012\0\0\0\0\0\0end +\0\0\0\013\0\0end { kat }. +Execution begins... +\0\0\0\0\02\0\0\0\0\03\0\0\0\0\05\0\0\0\0\07\0\0\0\011\0\0\0\013\0\0\0\017\0\0\0\019\0\0\0\023\0\0\0\029 +\0\0\0\031\0\0\0\037\0\0\0\041\0\0\0\043\0\0\0\047\0\0\0\053\0\0\0\059\0\0\0\061\0\0\0\067\0\0\0\071 +\0\0\0\073\0\0\0\079\0\0\0\083\0\0\0\089\0\0\0\097\0\0\0101\0\0\0103\0\0\0107\0\0\0109\0\0\0113 +\0\0\0127\0\0\0131\0\0\0137\0\0\0139\0\0\0149\0\0\0151\0\0\0157\0\0\0163\0\0\0167\0\0\0173 +\0\0\0179\0\0\0181\0\0\0191\0\0\0193\0\0\0197\0\0\0199\0\0\0211\0\0\0223\0\0\0227\0\0\0229 + +Execution terminated +925\0statements executed in 0.21 seconds cpu time diff --git a/doc/pascal/katscript b/doc/pascal/katscript new file mode 100644 index 0000000000..6abbc99906 --- /dev/null +++ b/doc/pascal/katscript @@ -0,0 +1,5 @@ +\*bThis is a line of text.\fR +This is a line of text. +\*bThe next line contains only an end-of-file (an invisible control-d!)\fR +The next line contains only an end-of-file (an invisible control-d!) +287 statements executed in 0.02 seconds cpu time diff --git a/doc/pascal/makefile b/doc/pascal/makefile new file mode 100755 index 0000000000..2977c4c093 --- /dev/null +++ b/doc/pascal/makefile @@ -0,0 +1,85 @@ +# This makefile assumes that csh is running the figures +FIGURES=\ + firstout firstobjout firstobjout2\ + bigger2.p bigger3.p bigout1 bigger6.p bigout2 bigout3 bigout4\ + primeout1 primeout2\ + digitsout synerrout synerr2out\ + mismout clashout sinout1 sinout2\ + exprout typequout primeout3\ + katout copydataout kat2out katscript xxxxqqqout xxxxqqqout2\ + primes primes-d\ + comments1.p commentsout +puman: ${FIGURES} + soelim puman0.n | tbl | /usr/new/vtroff -o-1 +csfix: + cc -O csfix.c -o csfix -lS +firstout: first.p csfix + pix first.p |& expand | csfix >firstout +firstobjout: first.p + pi first.p >& firstobjout ; px >& firstobjout +firstobjout2: first.p + pi -p first.p >& firstobjout2 ; px >& firstobjout2 +bigger2.p: bigger.p + -expand bigger.p >bigger2.p +bigger3.p: bigger2.p csfix + number bigger2.p | expand | csfix -d >bigger3.p +bigout1: bigger.p csfix + pix bigger.p |& expand | csfix >bigout1 +bigger6.p: bigger5.p csfix + number bigger5.p | expand | csfix -d >bigger6.p +bigout2: bigger4.p + pix bigger4.p |& expand >bigout2 +bigout3: bigger7.p + pix bigger7.p |& expand >bigout3 +bigout4: bigger7.p + (pix bigger7.p >/dev/null) |& expand > bigout4 +primeout1: primes.p csfix + pix -l -z primes.p |& expand | csfix - >primeout1 +primeout2: primes.p csfix + pxp -z primes.p |& expand | csfix - >primeout2 +digitsout: digits.p csfix + pi digits.p |& expand | csfix >digitsout +synerrout: synerr.p csfix + pi -l synerr.p |& expand | csfix >synerrout +synerr2out: synerr2.p csfix + pix -l synerr2.p |& expand | csfix >synerr2out +mismout: mism.p csfix + pi -l mism.p |& expand | csfix >mismout +clashout: clash.p + pi clash.p |& expand >clashout +sinout1: sin1.p + pi sin1.p |& expand >sinout1 +sinout2: sin2.p + pi sin2.p |& expand >sinout2 +exprout: expr.p + pi -l expr.p | expand >exprout +typequout: typequ.p + -pi typequ.p >typequout +primeout3: primes2.p csfix + pix primes2.p |& expand | csfix -d >primeout3 +katout: kat.p csfix primes + pix -l kat.p katout +copydataout: copydata.p csfix + pix -l copydata.p |& expand | csfix -d >copydataout +kat2out: kat2.p + -pi kat2.p ; px obj primes |& csfix -d >kat2out +xxxxqqqout: kat2.p + -pi kat2.p + -px obj xxxxqqq >& xxxxqqqout +xxxxqqqout2: kat2.p + pi -p kat2.p + -px obj xxxxqqq >& xxxxqqqout2 +primes: primes.p + pix -p primes.p > primes +primes-d: primes + csfix -d primes-d +katscript: katin + px obj katin >& katscript + -ed - katscript < fixkatscript +comments1.p: comments.p + -expand comments.p >comments1.p +commentsout: comments.p + pxp comments.p |& expand >commentsout + -ed - commentsout < fixcomments +clean: + -rm csfix pmon.out obj ${FIGURES} diff --git a/doc/pascal/mism.p b/doc/pascal/mism.p new file mode 100644 index 0000000000..a690b1e7d3 --- /dev/null +++ b/doc/pascal/mism.p @@ -0,0 +1,5 @@ +program mismatch(output) +begin + writeln('***'); + { The next line is the last line in the file } + writeln diff --git a/doc/pascal/mismout b/doc/pascal/mismout new file mode 100644 index 0000000000..586b84caf5 --- /dev/null +++ b/doc/pascal/mismout @@ -0,0 +1,11 @@ +Berkeley Pascal PI -- Version 1.1 (January 4, 1979) + +Sat Mar 31 11:50 1979 mism.p + + 1 program mismatch(output) + 2 begin +e \l'\w`w `u-\w`e `u '\l'\w` 2 `u-\w`w `u\&\(rh'\l'(\w`b`u-\w`^`u)/2 '\(ua\l'(\w`b`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted ';' + 3 writeln('***'); + 4 { The next line is the last line in the file } + 5 writeln +E \l'\w`w `u-\w`E `u '\l'\w` 5 writeln`u-\w`w `u\&\(rh'\l'(\w``u-\w`^`u)/2 '\(ua\l'(\w``u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Unexpected end-of-file - QUIT diff --git a/doc/pascal/motd b/doc/pascal/motd new file mode 100644 index 0000000000..fbb69ce0b1 --- /dev/null +++ b/doc/pascal/motd @@ -0,0 +1,3 @@ +Cory Hall 11/70 + +Type 'msgs' for latest system messages (Megabyte of memory installed) diff --git a/doc/pascal/primeout1 b/doc/pascal/primeout1 new file mode 100644 index 0000000000..988d01cae1 --- /dev/null +++ b/doc/pascal/primeout1 @@ -0,0 +1,43 @@ +Berkeley Pascal PI -- Version 1.1 (January 4, 1979) + +Sat Mar 31 11:50 1979 primes.p + +\0\0\0\0\01\0\0program primes(output); +\0\0\0\0\02\0\0const n = 50; n1 = 7; (*n1 = sqrt(n)*) +\0\0\0\0\03\0\0var i,k,x,inc,lim,square,l: integer; +\0\0\0\0\04\0\0\0\0\0\0prim: boolean; +\0\0\0\0\05\0\0\0\0\0\0p,v: array[1..n1] of integer; +\0\0\0\0\06\0\0begin +\0\0\0\0\07\0\0\0\0\0write(2:6, 3:6); l := 2; +\0\0\0\0\08\0\0\0\0\0x := 1; inc := 4; lim := 1; square := 9; +\0\0\0\0\09\0\0\0\0\0for i := 3 to n do +\0\0\0\010\0\0\0\0\0begin (*find next prime*) +\0\0\0\011\0\0\0\0\0\0\0\0repeat x := x + inc; inc := 6-inc; +\0\0\0\012\0\0\0\0\0\0\0\0\0\0\0if square <= x then +\0\0\0\013\0\0\0\0\0\0\0\0\0\0\0\0\0\0begin lim := lim+1; +\0\0\0\014\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0v[lim] := square; square := sqr(p[lim+1]) +\0\0\0\015\0\0\0\0\0\0\0\0\0\0\0\0\0\0end ; +\0\0\0\016\0\0\0\0\0\0\0\0\0\0\0k := 2; prim := true; +\0\0\0\017\0\0\0\0\0\0\0\0\0\0\0while prim and (k v[k] +\0\0\0\021\0\0\0\0\0\0\0\0\0\0\0end +\0\0\0\022\0\0\0\0\0\0\0\0until prim; +\0\0\0\023\0\0\0\0\0\0\0\0if i <= n1 then p[i] := x; +\0\0\0\024\0\0\0\0\0\0\0\0write(x:6); l := l+1; +\0\0\0\025\0\0\0\0\0\0\0\0if l = 10 then +\0\0\0\026\0\0\0\0\0\0\0\0\0\0\0begin writeln; l := 0 +\0\0\0\027\0\0\0\0\0\0\0\0\0\0\0end +\0\0\0\028\0\0\0\0\0end ; +\0\0\0\029\0\0\0\0\0writeln; +\0\0\0\030\0\0end . +Execution begins... +\0\0\0\0\02\0\0\0\0\03\0\0\0\0\05\0\0\0\0\07\0\0\0\011\0\0\0\013\0\0\0\017\0\0\0\019\0\0\0\023\0\0\0\029 +\0\0\0\031\0\0\0\037\0\0\0\041\0\0\0\043\0\0\0\047\0\0\0\053\0\0\0\059\0\0\0\061\0\0\0\067\0\0\0\071 +\0\0\0\073\0\0\0\079\0\0\0\083\0\0\0\089\0\0\0\097\0\0\0101\0\0\0103\0\0\0107\0\0\0109\0\0\0113 +\0\0\0127\0\0\0131\0\0\0137\0\0\0139\0\0\0149\0\0\0151\0\0\0157\0\0\0163\0\0\0167\0\0\0173 +\0\0\0179\0\0\0181\0\0\0191\0\0\0193\0\0\0197\0\0\0199\0\0\0211\0\0\0223\0\0\0227\0\0\0229 + +Execution terminated +1404\0statements executed in 0.16 seconds cpu time diff --git a/doc/pascal/primeout2 b/doc/pascal/primeout2 new file mode 100644 index 0000000000..0c0ee0ef48 --- /dev/null +++ b/doc/pascal/primeout2 @@ -0,0 +1,50 @@ +Berkeley Pascal PXP -- Version 1.1 (November 6, 1978) + +Sat Mar 31 11:50 1979 primes.p + +Profiled Sat Mar 31 13:02 1979 + +\0\0\0\0\01\0\0\0\0\0\0\0\01.\l'\w`\0\0\0\0`u-\w`.`u\&\(rh'|program primes(output); +\0\0\0\0\02\0\0\0\0\0\0\0\0\0\0\0\0\0|const +\0\0\0\0\02\0\0\0\0\0\0\0\0\0\0\0\0\0| n = 50; +\0\0\0\0\02\0\0\0\0\0\0\0\0\0\0\0\0\0| n1 = 7; (*n1 = sqrt(n)*) +\0\0\0\0\03\0\0\0\0\0\0\0\0\0\0\0\0\0|var +\0\0\0\0\03\0\0\0\0\0\0\0\0\0\0\0\0\0| i, k, x, inc, lim, square, l: integer; +\0\0\0\0\04\0\0\0\0\0\0\0\0\0\0\0\0\0| prim: boolean; +\0\0\0\0\05\0\0\0\0\0\0\0\0\0\0\0\0\0| p, v: array [1..n1] of integer; +\0\0\0\0\06\0\0\0\0\0\0\0\0\0\0\0\0\0|begin +\0\0\0\0\07\0\0\0\0\0\0\0\0\0\0\0\0\0| write(2: 6, 3: 6); +\0\0\0\0\07\0\0\0\0\0\0\0\0\0\0\0\0\0| l := 2; +\0\0\0\0\08\0\0\0\0\0\0\0\0\0\0\0\0\0| x := 1; +\0\0\0\0\08\0\0\0\0\0\0\0\0\0\0\0\0\0| inc := 4; +\0\0\0\0\08\0\0\0\0\0\0\0\0\0\0\0\0\0| lim := 1; +\0\0\0\0\08\0\0\0\0\0\0\0\0\0\0\0\0\0| square := 9; +\0\0\0\0\09\0\0\0\0\0\0\0\0\0\0\0\0\0| for i := 3 to n do begin (*find next prime*) +\0\0\0\0\09\0\0\0\0\0\0\0\0\0\0\048.\l'\w`\0\0\0\0`u-\w`.`u\&\(rh'| repeat +\0\0\0\011\0\0\0\0\0\0\0\0\0\0\0\0\0\0\076.\l'\w`\0\0\0\0`u-\w`.`u\&\(rh'| x := x + inc; +\0\0\0\011\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| inc := 6 - inc; +\0\0\0\012\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| if square <= x then begin +\0\0\0\013\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\05.\l'\w`\0\0\0\0`u-\w`.`u\&\(rh'| lim := lim + 1; +\0\0\0\014\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| v[lim] := square; +\0\0\0\014\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| square := sqr(p[lim + 1]) +\0\0\0\014\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| end; +\0\0\0\016\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| k := 2; +\0\0\0\016\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| prim := true; +\0\0\0\017\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| while prim and (k < lim) do begin +\0\0\0\018\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0157.\l'\w`\0\0\0\0`u-\w`.`u\&\(rh'| k := k + 1; +\0\0\0\019\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| if v[k] < x then +\0\0\0\019\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\042.\l'\w`\0\0\0\0`u-\w`.`u\&\(rh'| v[k] := v[k] + 2 * p[k]; +\0\0\0\020\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| prim := x <> v[k] +\0\0\0\020\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| end +\0\0\0\020\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0|until prim; +\0\0\0\023\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| if i <= n1 then +\0\0\0\023\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\05.\l'\w`\0\0\0\0`u-\w`.`u\&\(rh'| p[i] := x; +\0\0\0\024\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| write(x: 6); +\0\0\0\024\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| l := l + 1; +\0\0\0\025\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| if l = 10 then begin +\0\0\0\026\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\05.\l'\w`\0\0\0\0`u-\w`.`u\&\(rh'| writeln; +\0\0\0\026\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| l := 0 +\0\0\0\026\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| end +\0\0\0\026\0\0\0\0\0\0\0\0\0\0\0\0\0| end; +\0\0\0\029\0\0\0\0\0\0\0\0\0\0\0\0\0| writeln +\0\0\0\029\0\0\0\0\0\0\0\0\0\0\0\0\0|end. diff --git a/doc/pascal/primeout3 b/doc/pascal/primeout3 new file mode 100644 index 0000000000..217f2d36f6 --- /dev/null +++ b/doc/pascal/primeout3 @@ -0,0 +1,10 @@ +Execution begins... +\0\0\0\0\02\0\0\0\0\03\0\0\0\0\05\0\0\0\0\07\0\0\0\011\0\0\0\013\0\0\0\017\0\0\0\019\0\0\0\023\0\0\0\029 +\0\0\0\031\0\0\0\037\0\0\0\041\0\0\0\043\0\0\0\047\0\0\0\053\0\0\0\059\0\0\0\061\0\0\0\067\0\0\0\071 +\0\0\0\073\0\0\0\079\0\0\0\083\0\0\0\089\0\0\0\097\0\0\0101\0\0\0103\0\0\0107\0\0\0109\0\0\0113 +\0\0\0127\0\0\0131\0\0\0137\0\0\0139\0\0\0149\0\0\0151\0\0\0157\0\0\0163\0\0\0167Subscript out of range + +\0\0\0\0\0\0\0\0Error at "primes"+8 near line 14 + +Execution terminated abnormally +941\0statements executed in 0.12 seconds cpu time diff --git a/doc/pascal/primes b/doc/pascal/primes new file mode 100644 index 0000000000..aa282aa6b8 --- /dev/null +++ b/doc/pascal/primes @@ -0,0 +1,6 @@ + 2 3 5 7 11 13 17 19 23 29 + 31 37 41 43 47 53 59 61 67 71 + 73 79 83 89 97 101 103 107 109 113 + 127 131 137 139 149 151 157 163 167 173 + 179 181 191 193 197 199 211 223 227 229 + diff --git a/doc/pascal/primes-d b/doc/pascal/primes-d new file mode 100644 index 0000000000..8d7eb8cc51 --- /dev/null +++ b/doc/pascal/primes-d @@ -0,0 +1,6 @@ +\0\0\0\0\02\0\0\0\0\03\0\0\0\0\05\0\0\0\0\07\0\0\0\011\0\0\0\013\0\0\0\017\0\0\0\019\0\0\0\023\0\0\0\029 +\0\0\0\031\0\0\0\037\0\0\0\041\0\0\0\043\0\0\0\047\0\0\0\053\0\0\0\059\0\0\0\061\0\0\0\067\0\0\0\071 +\0\0\0\073\0\0\0\079\0\0\0\083\0\0\0\089\0\0\0\097\0\0\0101\0\0\0103\0\0\0107\0\0\0109\0\0\0113 +\0\0\0127\0\0\0131\0\0\0137\0\0\0139\0\0\0149\0\0\0151\0\0\0157\0\0\0163\0\0\0167\0\0\0173 +\0\0\0179\0\0\0181\0\0\0191\0\0\0193\0\0\0197\0\0\0199\0\0\0211\0\0\0223\0\0\0227\0\0\0229 + diff --git a/doc/pascal/primes.p b/doc/pascal/primes.p new file mode 100644 index 0000000000..d840390159 --- /dev/null +++ b/doc/pascal/primes.p @@ -0,0 +1,30 @@ +program primes(output); +const n = 50; n1 = 7; (*n1 = sqrt(n)*) +var i,k,x,inc,lim,square,l: integer; + prim: boolean; + p,v: array[1..n1] of integer; +begin + write(2:6, 3:6); l := 2; + x := 1; inc := 4; lim := 1; square := 9; + for i := 3 to n do + begin (*find next prime*) + repeat x := x + inc; inc := 6-inc; + if square <= x then + begin lim := lim+1; + v[lim] := square; square := sqr(p[lim+1]) + end ; + k := 2; prim := true; + while prim and (k v[k] + end + until prim; + if i <= n1 then p[i] := x; + write(x:6); l := l+1; + if l = 10 then + begin writeln; l := 0 + end + end ; + writeln; +end . diff --git a/doc/pascal/primes2.p b/doc/pascal/primes2.p new file mode 100644 index 0000000000..7693de81c4 --- /dev/null +++ b/doc/pascal/primes2.p @@ -0,0 +1,30 @@ +program primes(output); +const n = 50; n1 = 6; (*n1 = sqrt(n)*) +var i,k,x,inc,lim,square,l: integer; + prim: boolean; + p,v: array[1..n1] of integer; +begin + write(2:6, 3:6); l := 2; + x := 1; inc := 4; lim := 1; square := 9; + for i := 3 to n do + begin (*find next prime*) + repeat x := x + inc; inc := 6-inc; + if square <= x then + begin lim := lim+1; + v[lim] := square; square := sqr(p[lim+1]) + end ; + k := 2; prim := true; + while prim and (k v[k] + end + until prim; + if i <= n1 then p[i] := x; + write(x:6); l := l+1; + if l = 10 then + begin writeln; l := 0 + end + end ; + writeln; +end . diff --git a/doc/pascal/puman0.n b/doc/pascal/puman0.n new file mode 100644 index 0000000000..6178dd8af1 --- /dev/null +++ b/doc/pascal/puman0.n @@ -0,0 +1,127 @@ +.so tmac.p +.RP +.TL +Berkeley Pascal User's Manual +.br +Version 1.1 \- April, 1979 +.AU +William N. Joy* +.AU +Susan L. Graham* +.AU +Charles B. Haley** +.AI +Computer Science Division +.if n Department of Electrical Engineering +.if n and Computer Science +.if t Department of Electrical Engineering and Computer Science +University of California, Berkeley +Berkeley, California 94720 +...AI +...MH +.AB +.FS +\s-2(C)\s0 1977, 1979 William N. Joy, Susan L. Graham, Charles B. Haley +.FE +.FS +* Author's current address: Bell Laboratories, Murray Hill NJ 07974 +.FE +.PP +Berkeley +Pascal +is designed for interactive instructional use +and runs on the \s-2PDP\s0 11 family of computers. +It produces interpretive code, +providing fast translation at the expense of slower execution speed. +An execution profiler and +Wirth's cross reference program are also +available with the system. +..An interpretive implementation for the \s-2VAX\s0 11/780 is nearly complete, +..and a compiled version of the system, utilizing the code generator of +..the portable C compiler, is under construction, and should be completed by +..September, 1979. +.PP +The system supports full Pascal, with the exception of +.B procedure +and +.B function +names as parameters. +The language accepted is very close to +`standard' Pascal, +with only a small number of extensions. +.PP +The +.UM +gives a list of sources relating to the +.UX +system, the Pascal language, and the +.UP +system. +Basic usage examples are provided for the Pascal +interpreter components +.PI , +.X , +.IX , +and +.XP . +Errors commonly encountered in these programs are discussed. +Details are given of special considerations due to the +interactive implementation. +A number of examples are provided including many dealing with +input/output. An appendix supplements Wirth's +.I "Pascal Report" +to form the full definition of the Berkeley implementation of the language. +.AE +.ND +.SH +'if n 'ND +Introduction +.PP +.FS +* The financial support of the first and second authors' work by +the National Science Foundation under grants +MCS74-07644-A03 and MCS78-07291, +and the first author's work by an +.SM IBM +Graduate Fellowship +are gratefully acknowledged. +.FE +.FS +** Author's present address: Bell Laboratories, Murray Hill, NJ 07974. +.FE +The +.UP +.UM +consists of five major sections and an appendix. +In section 1 we give sources of information about +.UX , +about the programming +language Pascal, and about the +Berkeley +implementation of the language. +Section 2 introduces the +Berkeley +implementation and provides a number of basic examples. +Section 3 discusses the error diagnostics produced by the translator +.PI +and the runtime interpreter +.X . +Section 4 describes input/output with special attention given to features +of the interactive implementation and to features unique to +.UX . +Section 5 gives details on the components of the system +and explanation of all relevant options. +The +.UM +concludes with an appendix to Wirth's +.I "Pascal Report" +with which it forms a precise definition of the implementation. +.SH +History of the implementation +.PP +The first +Berkeley +system was written by Ken Thompson in early 1976. +The main features of the present system result from the work +of Charles Haley and William Joy during the latter half of 1976. +Earlier versions of this system have been in use since January, 1977. diff --git a/doc/pascal/puman1.n b/doc/pascal/puman1.n new file mode 100644 index 0000000000..0268e5ef1d --- /dev/null +++ b/doc/pascal/puman1.n @@ -0,0 +1,465 @@ +.if \n(xx .bp +.if !\n(xx \{\ +.so tmac.p \} +.if n 'ND +'nr H1 0 +.NH +Sources of information +.PP +This section lists the resources available on the UC Berkeley +campus for information about +general features of +.UX , +text editing, +the Pascal language, +and the +.UP +implementation, +concluding with a list of references. +The available documents include both so-called standard documents \- +those distributed with all +.UX +system \- +and documents (such as this one) written at Berkeley. +.NH 2 +Where to get documentation +.PP +On the UC Berkeley campus, documentation is available at the Computer +Center Library, room 218B Evans Hall. +The library is open from 8:00 A.M. to 5:00 P.M. Monday through Friday. +Current documentation for most of the +.UX +system is also available ``on line'' at your terminal. +Details on getting such documentation interactively are given +in section 1.3. +.NH 2 +Computer Center short courses +.PP +For those not enrolled in Computer Science Division courses, and +who have no prior experience using +.UX , +the short-courses offered by the staff of the Computer Center +are highly recommended. +These courses are offered free of charge, and are usually held +at the beginning of each quarter. +The two most valuable short courses for the +Berkeley +Pascal user are the ones dealing with basic use of +.UX , +and with +text editing. +If you are unable to attend the short courses, documents +for these courses are available at the Computer Center Library, +and are recommended. +The documents are in a tutorial format, so it is possible to use them on your +own. +.NH 2 +Documentation describing UNIX +.PP +The following documents are those recommended as tutorial and +reference material about the +.UX +system. +We give the documents with the introductory and tutorial materials +first, the reference materials last. +.SH +UNIX For Beginners \- Second Edition +.PP +This document is the basic tutorial for +.UX +available with the standard system. +.SH +Communicating with UNIX +.PP +This is also a basic tutorial on the system and assumes +no previous familiarity +with computers; it was written at Berkeley and is used in the short courses. +.SH +An introduction to the C shell +.PP +This document introduces +.I csh, +the shell in common use at Berkeley, and provides a good deal of general +description about the way in which the system functions. +It provides a useful glossary of terms used in discussing the system. +.SH +UNIX Programmer's Manual +.PP +This manual is the major source of details on the components of the +.UX +system. +It consists of an Introduction, +a permuted index, +and eight command sections. +Section 1 consists of descriptions of most of the ``commands'' +of +.UX . +Most of the other sections have limited relevance to the user +of +Berkeley +Pascal, being of interest mainly to system programmers. +The manual is available from the Computer Center Library. +.PP +U\s-2NIX\s0 +documentation often refers the reader to sections of the manual. +Such a reference consists of a command name and a section number or name. +An example of such a reference would be: +.I ed +(1).\(dg +.FS +\(dg Older systems may refer to the manual sections using roman numerals, +e.g. \fIpi\fR (6). +.FE +Here +.I ed +is a command name \- the standard +.UX +text editor, and `(1)' indicates that its documentation is in section 1 of the +manual. +.PP +The pieces of the +Berkeley +Pascal system are +.I pi +(6), +.X +(6), +the combined Pascal translator and interpretive executor +.IX +(6), +the Pascal execution profiler +.XP +(6), +the Pascal cross-reference generator +.I pxref +(6), +and the filter which interprets carriage control +.I pcc +(6). +.PP +It is possible to obtain a copy of a manual section +by using the +.I man +(1) command. +To get the Pascal documentation just described one could issue the +command: +.LS +% \*bman new pi\fP +.LE +to the shell. +The user input here is shown in +.B "bold face" ; +the `% ', +which was printed by the shell as a prompt, +is not. +Similarly the command: +.LS +% \*bman man\fP +.LE +asks the +.I man +command to describe itself. +.NH 2 +Text editing documents +.PP +The following documents introduce the various +.UX +text editors. +Most Berkeley users will use a version of the text editor +.I ex; +either +.I edit, +which is a version of +.I ex +for new and casual users, +.I ex +itself, +or +.I vi +(visual) which focuses on the display editing portion of +.I ex.* +.FS +* Several other editors are available also. The standard +.UX +editor +.I ed, +the \s-2RAND\s0 editor +.I re, +and an (undocumented) version of +.I teco. +.FE +.SH +A Tutorial Introduction to the UNIX Text Editor +.PP +This document, written by Brian Kernighan of Bell Laboratories, +is a tutorial for the standard +.UX +text editor +.I ed. +It introduces you to the basics of text editing, +and provides enough information to meet day-to-day editing needs, +for +.I ed +users. +.SH +Edit: A tutorial +.PP +This introduces the use of +.I edit, +an editor similar to +.I ed +which provides a more hospitable environment for beginning users. +The short courses on editing taught by the Computer Center use this +document. +.SH +Ex/edit Command Summary +.PP +This summarizes the features of the editors +.I ex +and +.I edit +in a concise form. If you have used a line oriented editor before +this summary alone may be enough to get you started. +.SH +Ex Reference Manual \- Version 2.0 +.PP +A complete reference on the features of +.I ex +and +.I edit. +.SH +An Introduction to Display Editing with Vi +.PP +.I Vi +is a display oriented text editor. It can be used on most any \s-2CRT\s0 +terminal, +and uses the screen as a window into the file you are editing. Changes +you make to the file are reflected in what you see. This manual serves +both as an introduction to editing with +.I vi +and a reference manual. +.SH +Vi Quick Reference +.PP +This reference card is a handy quick guide to +.I vi; +you should get one when you get the introduction to +.I vi. +.NH 2 +Pascal documents \- The language +.PP +This section describes the documents on the Pascal language +which are likely to be most useful to the +Berkeley +Pascal user. +Complete references for these documents are given in section 1.7. +.SH +Pascal User Manual +.PP +By Kathleen Jensen and Niklaus Wirth, the +.I "User Manual" +provides a tutorial introduction to the features +of the language Pascal, +and serves as an excellent quick-reference to the language. +The reader with no familiarity with Algol-like languages +may prefer one of the Pascal text books listed below, +as they provide more examples and explanation. +Particularly important here are pages 116-118 which define the syntax +of the language. +Sections 13 and 14 and Appendix F pertain only to the +6000-3.4 implementation of Pascal. +.SH +Pascal Report +.PP +By Niklaus Wirth, this document is bound with the +.I "User Manual." +It is the guiding reference for implementors and the fundamental +definition of the language. +Some programmers find this report too concise to be of practical use, +preferring the +.I "User Manual" +as a reference. +.SH +Books on Pascal +.PP +Several good books which teach Pascal or use it as a medium are +available. +The books by Wirth +.I "Systematic Programming" +and +.I "Algorithms + Data Structures = Programs" +use Pascal as a vehicle for teaching programming and data structure +concepts respectively. +They are both recommended. +Other books on Pascal are listed in the references below. +.NH 2 +Pascal documents \- The Berkeley Implementation +.PP +This section describes the documentation which is available +describing the +Berkeley +implementation of Pascal. +.SH +User's Manual +.PP +The document you are reading is the +.I "User's Manual" +for +.UP . +We often refer the reader to the +Jensen-Wirth +.I "User Manual" +mentioned above, +a different document with a similar name. +.SH +Manual sections +.PP +The sections relating to Pascal in the +.I "UNIX Programmer's Manual" +are +.IX +(6), +.PI +(6), +.I pcc +(6), +.X +(6), +.I pxp +(6), +and +.I pxref +(6). +These sections give a description of each program, +summarize the available options, +indicate files used by the program, +give basic information on the diagnostics produced +and include a list of known bugs. +.SH +Implementation notes +.PP +For those interested in the internal organization of the +Berkeley +Pascal system there are a series of +.I "Implementation Notes" +describing these details. +The +.I "Berkeley Pascal PXP Implementation Notes" +describe the Pascal interpreter +.X \|; +and the +.I "Berkeley Pascal PX Implementation Notes" +describe the structure of the +execution profiler +.I pxp . +.br +.ne 8 +.NH 2 +References +.de re +.sp +.IP +'nf +.. +.SH +UNIX Documents +.re +.I "Communicating With UNIX" +Computer Center +University of California, Berkeley +January, 1978. +.re +.I "Edit: a tutorial" +Ricki Blau and James Joyce +Computing Services Division, Computing Affairs +University of California, Berkeley +January, 1978. +.re +.I "Ex/edit Command Summary" +Computer Center +University of California, Berkeley +August, 1978. +.re +.I "Ex Reference Manual \- Version 2.0" +.I "An Introduction to Display Editing with Vi" +.I "Vi Quick Reference" +William Joy +Computer Science Division +Department of Electrical Engineering and Computer Science +University of California, Berkeley +April, 1979. +.re +.I "An Introduction to the C shell" +William Joy +Computer Science Division +Department of Electrical Engineering and Computer Science +University of California, Berkeley +January, 1979. +.re +Brian W. Kernighan +.I "UNIX for Beginners \- Second Edition" +Bell Laboratories +Murray Hill, New Jersey. +.re +Brian W. Kernighan +.I "A Tutorial Introduction to the UNIX Text Editor" +Bell Laboratories +Murray Hill, New Jersey. +.re +Dennis M. Ritchie and Ken Thompson +.I "The UNIX Time Sharing System" +Communications of the ACM +July 1974 +365-378. +.re +B. W. Kernighan and M. D. McIlroy +.I "UNIX Programmer's Manual \- Seventh Edition" +Bell Laboratories +Murray Hill, New Jersey +December, 1978. +.ne 12 +.SH +Pascal Language Documents +.re +Conway, Gries and Zimmerman +.I "A Primer on PASCAL" +Winthrop, Cambridge Mass. +1976, 433 pp. +.re +Kathleen Jensen and Niklaus Wirth +.I "Pascal \- User Manual and Report" +Springer-Verlag, New York. +1975, 167 pp. +.re +C. A. G. Webster +.I "Introduction to Pascal" +Heyden and Son, New York +1976, 129pp. +.re +Niklaus Wirth +.I "Algorithms + Data structures = Programs" +Prentice-Hall, New York. +1976, 366 pp. +.re +Niklaus Wirth +.I "Systematic Programming" +Prentice-Hall, New York. +1973, 169 pp. +.SH +Berkeley Pascal documents +.PP +The following documents are available from the Computer Center Library +at the University of California, Berkeley. +.nf +.re +William N. Joy, Susan L. Graham, and Charles B. Haley +.I "Berkeley Pascal User's Manual \- Version 1.1" +April, 1979. +.re +William N. Joy +.I "Berkeley Pascal PX Implementation Notes" +Version 1.1, April 1979. +.re +William N. Joy +.I "Berkeley Pascal PXP Implemetation Notex" +Version 1.1, April 1979. diff --git a/doc/pascal/puman2.n b/doc/pascal/puman2.n new file mode 100644 index 0000000000..6d45af5222 --- /dev/null +++ b/doc/pascal/puman2.n @@ -0,0 +1,849 @@ +.if \n(xx .bp +.if !\n(xx \{\ +.so tmac.p \} +'if n 'ND +.nr H1 1 +.NH +Basic UNIX Pascal +.PP +The following sections +explain the basics of using +.UP . +In examples here we use the text editor +.I ex +(6). +Users of the text editor +.I ed +should have little trouble following these examples, +as +.I ex +is similar to +.I ed . +We use +.I ex +because it +allows us to make clearer examples.\(dg +.FS +\(dg Users with \s-2CRT\s0 terminals should find the editor +.I vi +more pleasant to use; +we do not show its use here because its display oriented nature +makes it difficult to illustrate. +.FE +The new +.UX +user will find it helpful to read one of the text editor documents +described in section 1.4 before continuing with this section. +.NH 2 +A first program +.PP +To prepare a program for +.UP +we first need to have an account on +.UX +and to `login' +to the system on this account. +These procedures are described in the documents +.I "Communicating with UNIX" +and +.I "UNIX for Beginners". +.PP +Once we are logged in we need to choose a name for our program; +let us call it `first' as this is the first example. +We must also choose a name for the file in which the program will be stored. +The +.UP +system requires that programs reside in files which have names ending with +the sequence `.p' so we will call our file `first.p'. +.PP +A sample editing session to create this file would begin: +.LS +% \*bex first.p\fR +"first.p" No such file or directory +: +.LE +We didn't expect the file to exist, so the error diagnostic doesn't +bother us. +The editor now knows the name of the file we are creating. +The `:' prompt indicates that it is ready for command input. +We can add the text for our program using the `append' +command as follows. +.LS +:\*bappend\fR +.B +program first(output) +begin + writeln('Hello, world!') +end. +\&. +.R +: +.LE +The line containing the single `\*b.\fR' character here indicated +the end of the appended text. +The `:' prompt indicates that +.I ex +is ready for another command. +As the editor operates in a temporary work space we must now store the contents +of this work space in the file `first.p' +so we can use the Pascal +translator and executor +.IX +on it. +.LS +:\*bwrite\fR +"first.p" 4 lines, 59 characters +:\*bquit\fR +% +.LE +We wrote out the file from the edit buffer here with the +`write' +command, and +.I ex +indicated the number of lines and characters written. +We then quit the editor, and now have a prompt from the shell.\(dd +.FS +\(dd Our examples here assume you are using +.I csh. +.FE +.KS +.PP +We are ready to try +to translate and execute our program. +.DS +.tr '\(aa^\(ua +% \*bpix first.p\fR +.so firstout +.tr ''^^ +% +.DE +.KE +.PP +The translator first printed a syntax error diagnostic. +The number 2 here indicates that the rest of the line is an image +of the second line of our program. +The translator is saying that it expected to find a `;' before the +keyword +.B begin +on this line. +If we look at the Pascal syntax charts in the Jensen-Wirth +.I "User Manual" , +or at some of the sample programs therein, we will see that +we have omitted the terminating `;' of the +.B program +statement on the first +line of our program. +.PP +One other thing to notice about the error diagnostic is the letter `e' +at the beginning. +It stands for `error', +indicating that our input was not legal Pascal. +The fact that it is an `e' rather than an `E' +indicates that the translator managed to recover from this error well +enough that generation of code and execution could take place. +Execution is possible whenever no fatal `E' errors +occur during translation. +The other classes of diagnostics are `w' warnings, +which do not necessarily indicate errors in the program, +but point out inconsistencies which are likely to be due to program bugs, +and `s' standard-Pascal violations.\*(dg +.FS +\*(dgThe standard Pascal warnings occur only when the associated +.B s +translator option is enabled. +The +.B s +option is discussed in sections 5.1 and A.6 below. +Warning diagnostics are discussed at the end of section 3.2, +the associated +.B w +option is described in section 5.2. +.FE +.PP +After completing the translation of the program to interpretive code, +the Pascal system indicates that execution of the translated program began. +The output from the execution of the program then appeared. +At program termination, the Pascal runtime system indicated the +number of statements executed, and the amount of cpu time +used, with the resolution of the latter being 1/60'th of a second. +.PP +Let us now fix the error in the program and translate it to a permanent +object code file +.I obj +using +.PI . +The program +.PI +translates Pascal programs but stores the object code instead of executing it\*(dd. +.FS +\*(ddThis script indicates some other useful approaches to debugging +Pascal programs. +As in +.I ed +we can shorten commands in +.I ex +to an initial prefix of the command name as we did +with the +.I substitute +command here. +We have also used the `!' shell escape command here to execute other +commands with a shell without leaving the editor. +.FE +.LS +% \*bex first.p\fR +"first.p" 4 lines, 59 characters +:\*b1 print\fR +program first(output) +:\*bs/$/;\fR +program first(output); +:\*bwrite\fR +"first.p" 4 lines, 60 characters +:\*b!pi %\fR +!pi first.p +! +:\*bquit\fR +% +.LE +The first command issued from +.I ex +with the `!' +involved the use of the `%' character which stands in this command for +the file we are editing. +.I Ex +made this substitution, and then echoed back the expanded line +before executing the command. +When the command finished, the editor echoed the character `!' +so that we would know it was done. +.PP +If we now use the +.UX +.I ls +list files command we can see what files we have: +.LS +% \*bls\fR +first.p +obj +% +.LE +The file `obj' here contains the Pascal interpreter code. +We can execute this by typing: +.LS +% \*bpx obj\fR +.so firstobjout +% +.LE +Alternatively, the command: +.LS +% \*bobj\fR +.LE +will have the same effect. +Some examples of different ways to execute the program follow. +.LS +% \*bpx\fR +.so firstobjout +% \*bpi -p first.p\fR +% \*bpx obj\fR +.so firstobjout2 +% \*bpix -p first.p\fR +.so firstobjout2 +% +.LE +.PP +Note that +.I px +will assume that `obj' is the file we wish to execute +if we don't tell it otherwise. +The last two translations use the +.B \-p +no-post-mortem option to eliminate +execution statistics and +`Execution begins' +and +`Execution terminated' +messages. +See section 5.2 for more details. +If we now look at the files in our directory we will see: +.LS +% \*bls\fR +first.p +obj +% +.LE +We can give our object program a name other than `obj' by using the move +command +.I mv +(1). +Thus to name our program `hello': +.LS +% \*bmv obj hello\fR +% \*bhello\fR +Hello, world! +% \*bls\fR +first.p +hello +% +.LE +.KS +Finally we can get rid of the Pascal object code by using the +.I rm +(1) remove file command, e.g.: +.LS +% \*brm hello\fR +% \*bls\fR +first.p +% +.LE +.KE +.PP +For small programs which are being developed +.IX +tends to be more convenient to use than +.PI +and +.X . +Except for absence of the +.I obj +file after a +.IX +run, +a +.IX +command is equivalent to a +.PI +command followed by a +.X +command. +For larger programs, +where a number of runs testing different parts of the program are +to be made, +.PI +is useful as this +.I obj +file can be executed any desired number of times. +.NH 2 +A larger program +.PP +Suppose that we have used the editor to put a larger program +in the file `bigger.p'. +We can list this program with line numbers by using the program +.I num +i.e.: +.LS +% \*bnum bigger.p\fR +.so bigger3.p +% +.LE +This program is similar to program 4.9 on page 30 of the +Jensen-Wirth +.I "User Manual" . +A number of problems have been introduced into this example for +pedagogical reasons. +.br +.ne 8 +.PP +If we attempt to translate and execute the program using +.IX +we get the following response: +.LS +% \*bpix bigger.p\fR +.so bigout1 +% +.LE +.PP +Since there were fatal `E' errors in our program, +no code was generated and execution was necessarily suppressed. +One thing which would be useful at this point is a listing of the +program with the error messages. +We can get this by using the command: +.LS +% \*bpi -l bigger.p\fR +.LE +There is no point in using +.IX +here, since we know there are fatal errors in the program. +This command will produce the output at our terminal. +If we are at a terminal which does not produce a hard copy +we may wish to print this +listing off-line on a line printer\*(dg. +.FS +\*(dgAt Berkeley, the line printer for the Cory Hall system is in Room 199B. +The line printers for the Computer Center +systems are in the basement of Evans Hall. +.FE +We can do this with the command: +.LS +% \*bpi -l bigger.p | lpr\fR +.LE +.PP +In the next few sections we will illustrate various aspects of the +Berkeley +Pascal system by correcting this program. +.NH 2 +Correcting the first errors +.PP +Most of the errors which occurred in this program were +.I syntactic +errors, those in the format and structure of the program rather than +its content. +Syntax errors are flagged by printing the offending line, and then a line +which flags the location at which an error was detected. +The flag line also gives an explanation +stating either a possible cause of the error, +a simple action which can be taken to recover from the error so +as to be able to continue the analysis, +a symbol which was expected at the point of error, +or an indication that the input was `malformed'. +In the last case, the recovery may skip ahead in the input +to a point where analysis of the program can continue. +.PP +In this example, +the first error diagnostic indicates that the translator detected +a comment within a comment. +While this is not considered an error in `standard' +Pascal, it usually corresponds to an error in the program which +is being translated. +In this case, we have accidentally omitted the trailing `*)' of the comment +on line 8. +We can begin an editor session to correct this problem by doing: +.LS +% \*bex bigger.p\fR +"bigger.p" 24 lines, 512 characters +:\*b8s/$/ *)\fR + s = 32; (* 32 character width for interval [x, x+1] *) +: +.LE +.PP +The second diagnostic, given after line 16, +indicates that the keyword +.B do +was expected before the keyword +.B begin +in the +.B for +statement. +If we examine the +.I statement +syntax chart on page 118 of the +Jensen-Wirth +.I "User Manual" +we will discover that +.B do +is a necessary part of the +.B for +statement. +Similarly, we could have referred to section C.3 of the +Jensen-Wirth +.I "User Manual" +to learn about the +.B for +statement and gotten the same information there. +It is often useful to refer to these syntax charts and to the +relevant sections of this book. +.PP +We can correct this problem by first scanning for the keyword +.B for +in the file and then substituting the keyword +.B do +to appear in front of the keyword +.B begin +there. +Thus: +.LS +:\*b/for\fR + for i := 0 to lim begin +:\*bs/begin/do &\fR + for i := 0 to lim do begin +: +.LE +The next error in the program is easy to pinpoint. +On line 18, we didn't hit the shift key and got a `9' +instead of a `)'. +The translator diagnosed that `x9' +was an undefined variable and, later, +that a `)' was missing in the statement. +It should be stressed that +.PI +is not suggesting that you should insert a `)' before the `;'. +It is only indicating that making this change will help it to be able to +continue analyzing the program so as to be able to diagnose further +errors. +You must then determine the true cause of the error and make the +appropriate correction to the source text. +.PP +This error also illustrates the fact that one error in the input may lead +to multiple error diagnostics. +.I Pi +attempts +to give only one diagnostic for each error, +but single errors in the input sometimes appear to be more than +one error. +It is also the case that +.PI +may not detect an error when it occurs, but may detect it later in +the input. +This would have happened +in this example if we had typed `x' instead of `x9'. +.PP +The translator next detected, on line 19, that the function +.I Round +and the variable +.I h +were undefined. +It does not know about +.I Round +because +.UP +normally distinguishes between upper- and lower-case. +On +.UX +lower-case is preferred\*(dg, +.FS +\*(dgOne good reason for using lower-case is that it is easier to type. +.FE +and all keywords and built-in +.B procedure +and +.B function +names are composed of lower-case letters, +just as they are in the Jensen-Wirth +.I "Pascal Report" . +Thus we need to use the function +.I round +here. +As far as +.I h +is concerned, +we can see why it is undefined if we look back to line 9 +and note that its definition was lost in the non-terminated +comment. +This diagnostic need not, therefore, concern us. +.PP +The next error which occurred in the program caused the translator +to insert a `;' before the statement calling +.I writeln +on line 23. +If we examine the program around the point of error we will see +that the actual error is that the keyword +.B until +and an associated expression have been omitted here. +Note that the diagnostic from the translator does not indicate the actual +error, and is somewhat misleading. +The translator made the correction which seemed to be most plausible. +As the omission of a `;' character is a common mistake, +the translator chose to indicate this as a possible fix here. +It later detected that the keyword +.B until +was missing, but not until it saw the keyword +.B end +on line 24. +The combination of these diagnostics indicate to us the true problem. +.PP +The final syntactic error message indicates that the translator needed an +.B end +keyword to match the +.B begin +at line 15. +Since the +.B end +at line 24 is supposed to match this +.B begin , +we can infer that another +.B begin +must have been mismatched, and have matched this +.B end . +Thus we see that we need an +.B end +to match the +.B begin +at line 16, +and to appear before the final +.B end . +We can make these corrections: +.LS +:\*b/x9/s//x)\fR + y := exp(-x) * sin(i * x); +:\*b+s/Round/round\fR + n := round(s * y) + h; +:\*b/write\fR + write(' '); +:\*b/\fR + writeln('*') +:\*binsert\fR + \*buntil n = 0;\fR +\&\*b.\fR +:\*b$\fR +end. +:\*binsert\fR + \*bend\fR +\&\*b.\fR +: +.LE +.PP +At the end of each +.B procedure +or +.B function +and the end of the +.B program +the translator summarizes references to undefined variables +and improper usages of variables. +It also gives +warnings about potential errors. +In our program, the summary errors do not indicate any further problems +but the warning that +.I c +is unused is somewhat suspicious. +Examining the program we see that the constant was intended +to be used in the expression which is an argument to +.I sin , +so we can correct this expression, and translate the program. +We have now made a correction for each diagnosed error +in our program. +.LS +:\*b?i ?s//c /\fR + y := exp(-x) * sin(c * x); +:\*bwrite\fR +"bigger.p" 26 lines, 538 characters +:\*b!pi %\fR +!pi bigger.p +! +:\*bquit\fR +% +.LE +It should be noted that the translator suppresses warning +diagnostics for a particular +.B procedure , +.B function +or the main +.B program +when it finds severe syntax errors in that part of the source +text. +This is to prevent possibly confusing and +incorrect warning diagnostics from being produced. +Thus these warning diagnostics may not appear in a program with +bad syntax errors until these errors are corrected. +.KS +.PP +We are now ready to execute our program for the first +time. +We will do so in the next section after giving a listing +of the corrected program for reference purposes. +.ne 15 +.LS +% \*bnumber bigger.p\fR +.so bigger6.p +% +.LE +.NH 2 +Executing the second example +.PP +We are now ready to execute the second example. +The following output was produced by our first run. +.LS +% \*bpx\fR +.so bigout2 +% +.LE +Here the interpreter is presenting us with a runtime error diagnostic. +It detected a `division by zero' at line 17. +Examining line 17, we see that we have written +the statement `x := d / i' instead of `x := d * i'. +We can correct this and rerun the program: +.ne 10 +.LS +% \*bex bigger.p\fR +"bigger.p" 26 lines, 538 characters +:\*b17\fR + x := d / i +:\*bs'/'*\fR + x := d * i +:\*bwrite\fR +"bigger.p" 26 lines, 538 characters +:\*b!pix %\fR +!pix bigger.p +.so bigout3 +! +:\*bq\fR +% +.LE +.KS +.PP +This appears to be the output we wanted. +We could now save the output in a file if we wished by using the shell +to redirect the output: +.LS +% \*bpx > graph\fR +.LE +.KE +We can use +.I cat +(1) to see the contents of the file graph. +We can also make a listing of the graph on the line printer without +putting it into a file, e.g. +.LS +% \*bpx | lpr\fR +.so bigout4 +% +.LE +Note here that the statistics lines came out on our terminal. +The statistics line comes out on the diagnostic output (unit 2.) +There are two ways to get rid of the statistics line. +We can redirect the statistics message to the printer using the +syntax `|\|&' to the shell rather than `|', i.e.: +.LS +% \*bpx |\|& lpr\fR +% +.LE +or we can translate the program with the +.B p +option disabled on the command line as we did above. +This will disable all post-mortem dumping including the statistics line, +thus: +.LS +% \*bpi -p bigger.p\fR +% \*bpx | lpr\fR +% +.LE +This option also disables the statement limit which normally guards +against infinite looping. +You should not use it until your program is debugged. +Also if +.B p +is specified and an error occurs, you will +not get run time diagnostic information to help you +determine what the problem is. +.NH 2 +Formatting the program listing +.PP +It is possible to use special lines within the source text of a program +to format the program listing. +An empty line (one with no characters on it) corresponds to a +`space' macro in an assembler, leaving a completely blank line +without a line number. +A line containing only a control-l (form-feed) character +will cause a page eject in the listing with the corresponding line number +suppressed. +This corresponds to an `eject' pseudo-instruction. +See also section 5.2 for details on the +.B n +and +.B i +options of +.PI . +.NH 2 +Execution profiling +.PP +An execution profile consists of a structured listing of (all or part of) +a program with information about the number of times each statement in +the program was executed for a particular run of the program. +These profiles can be used for several purposes. +In a program which was abnormally terminated due to excessive looping +or recursion or by a program fault, the counts can facilitate location +of the error. +Zero counts mark portions of the program which were not executed; +during the early debugging stages they should prompt new test data or +a re-examination of the program logic. +The profile is perhaps most valuable, however, in drawing +attention to the (typically small) +portions of the program that dominate execution time. +This information can be used for source level optimization. +.SH +An example +.PP +A prime number is a number which is divisible only by itself and the +number one. +The program +.I primes , +written by Niklaus Wirth, +determines the first few prime numbers. +In translating the program we have specified the +.B z +option to +.IX . +This option causes the translator to generate counters and count instructions +sufficient in number to determine the number of times each statement in the +program was executed.\*(dg +.FS +\*(dgThe counts +are completely accurate only in the absence of runtime errors and nonlocal +.B goto +statements. +This is not generally a problem, however, as in structured programs +nonlocal +.B goto +statements occur infrequently, +and counts are incorrect after abnormal termination only when the +.I "upward look" +described below to get a count passes a suspended call point. +.FE +When execution of the program completes, either normally or abnormally, +this count data is written to the file +.I pmon.out +in the current directory.\*(dd +.FS +\*(dd\c +.I Pmon.out +has a name similar to +.I mon.out +the monitor file produced by the profiling facility of the C compiler +.I cc +(1). +See +.I prof +(1) for a discussion of the C compiler profiling facilities. +.FE +It is then possible to prepare an execution profile by giving +.XP +the name of the file associated with this data, as was done in the following +example. +.LS +% \*bpix -l -z primes.p\fR +.so primeout1 +% +.LE +.SH +Discussion +.PP +The header lines of the outputs of +.IX +and +.XP +in this example indicate the version of the translator and execution +profiler in use at the time this example was prepared. +The time given with the file name (also on the header line) +indicates the time of last modification of the program source file. +This time serves to +.I "version stamp" +the input program. +.I Pxp +also indicates the time at which the profile data was gathered. +.LS +% \*bpxp -z primes.p\fR +.so primeout2 +% +.LE +.KE +.PP +To determine the number of times a statement was executed, +one looks to the left of the statement and finds the corresponding +vertical bar `|'. +If this vertical bar is labelled with a count then that count gives the +number of times the statement was executed. +If the bar is not labelled, we look up in the listing to find the first +`|' which directly above the original one which has a count and that +is the answer. +Thus, in our example, +.I k +was incremented 157 times on line 18, +while the +.I write +procedure call on line 24 was executed 48 times as given by the count +on the +.B repeat . +.PP +More information on +.I pxp +can be found in its manual section +.XP +(6) +and in sections 5.4, 5.5 and 5.10. diff --git a/doc/pascal/puman3.n b/doc/pascal/puman3.n new file mode 100644 index 0000000000..e371296ca0 --- /dev/null +++ b/doc/pascal/puman3.n @@ -0,0 +1,712 @@ +.if \n(xx .bp +.if !\n(xx \{\ +.so tmac.p \} +.if n 'ND +.nr H1 2 +.NH +Error diagnostics +.PP +This section of the +.UM +discusses the error diagnostics of the programs +.PI +and +.X . +.I Pix +is a simple but useful program which invokes +.PI +and +.X +to do all the real processing. +See its manual section +.IX +(6) +and section 5.2 below for more details. +.NH 2 +Translator syntax errors +.PP +A few comments on the general nature of the syntax errors usually +made by Pascal programmers +and the recovery mechanisms of the current translator may help in using +the system. +.SH +Illegal characters +.PP +Characters such as `$', `!', and `@' are not part of the language Pascal. +If they are found in the source program, +and are not part of a constant string, a constant character, or a comment, +they are considered to be +`illegal characters'. +This can happen if you leave off an opening string quote `\(aa'. +Note that the character `"', although used in English to quote strings, +is not used to quote strings in Pascal. +Most non-printing characters in your input are also illegal except +in character constants and character strings. +Except for the tab and form feed characters, +which are used to ease formatting of the program, +non-printing characters in the input file print as the character `?' +so that they will show in your listing. +.SH +String errors +.PP +There is no character string of length 0 in Pascal. +Consequently the input `\(aa\(aa' is not acceptable. +Similarly, encountering an end-of-line after an opening string quote `\(aa' +without encountering the matching closing quote yields the diagnostic +``Unmatched \(aa for string''. +It is permissible to use the character `#' +instead of `\'' +to delimit character and constant strings for portability reasons. +For this reason, a spuriously placed `#' sometimes causes the diagnostic +about unbalanced quotes. +Similarly, a `#' in column one is used when preparing programs which are to +be kept in multiple files. +See section 5.9 for details. +.SH +Comments in a comment, non-terminated comments +.PP +As we saw above, these errors are usually caused by leaving off a comment +delimiter. +You can convert parts of your program to comments +without generating this diagnostic +since there are two different kinds of comments \- those delimited by +`{' and `}', and those delimited by `(*' and `*)'. +Thus consider: +.LS +{ This is a comment enclosing a piece of program +a := functioncall; (* comment within comment *) +procedurecall; +lhs := rhs; (* another comment *) +} +.LE +.PP +By using one kind of comment exclusively in your program you can use +the other delimiters when you need to +``comment out'' +parts of your program\*(dg. +.FS +\*(dgIf you wish to transport your program, +especially to the 6000-3.4 implementation, +you should use the character sequence `(*' to delimit comments. +For transportation over the +.I rcslink +to Pascal 6000-3.4, the character `#' should be used to delimit characters +and constant strings. +.FE +In this way you will also allow the translator to help by detecting +statements accidentally placed within comments. +.PP +If a comment does not terminate before the end of the input file, +the translator will point to the beginning of the comment, +indicating that the comment is not terminated. +In this case processing will terminate immediately. +See the discussion of ``QUIT'' below. +.SH +Digits in numbers +.PP +This part of the language is a minor nuisance. +Pascal requires digits in real numbers both before and after the decimal +point. +Thus the following statements, which look quite reasonable to +.SM +FORTRAN +.NL +users, generate diagnostics in Pascal: +.LS +.so digitsout +.LE +These same constructs are also illegal as input to the Pascal interpreter +.I px . +.SH +Replacements, insertions, and deletions +.PP +When a syntax error is encountered in the input text, +the parser invokes an error recovery procedure. +This procedure examines the input text immediately after the point +of error and considers a set of simple corrections to see whether they +will allow the analysis to continue. +These corrections involve replacing an input token with a different +token, +inserting a token, +or replacing an input token with a different token. +Most of these changes will not cause fatal syntax errors. +The exception is the insertion of or replacement with a symbol +such as an identifier or a number; +in this case the recovery makes no attempt to determine +.I which +identifier or +.I what +number should be inserted, +hence these are considered fatal syntax errors. +.PP +Consider the following example. +.LS +% \*bpix -l synerr.p\fR +.tr -- +.so synerrout +% +.LE +The only surprise here may be that Pascal does not have an exponentiation +operator, hence the complaint about `**'. +This error illustrates that, if you assume that the language has a feature +which it does not, the translator diagnostic may not indicate this, +as the translator is unlikely to recognize the construct you supply. +.SH +Undefined or improper identifiers +.PP +If an identifier is encountered in the input but is undefined, +the error recovery will replace it with an identifier of the +appropriate class. +Further references to this identifier will be summarized at the +end of the containing +.B procedure +or +.B function +or at the end of the +.B program +if the reference occurred in the main program. +Similarly, +if an identifier is used in an inappropriate way, +e.g. if a +.B type +identifier is used in an assignment statement, +or if a simple variable +is used where a +.B record +variable is required, +a diagnostic will be produced and an identifier of the appropriate +type inserted. +Further incorrect references to this identifier will be flagged only +if they involve incorrect use in a different way, +with all incorrect uses being summarized in the same way as undefined +variable uses are. +.SH +Expected symbols, malformed constructs +.PP +If none of the above mentioned corrections appear reasonable, the +error recovery will examine the input +to the left of the point of error to see if there is only one symbol +which can follow this input. +If this is the case, the recovery will print a diagnostic which +indicates that the given symbol was `Expected'. +.PP +In cases where none of these corrections resolve the problems +in the input, +the recovery may issue a diagnostic that indicates that the +input is ``malformed''. +If necessary, the translator may then skip forward in the input to +a place where analysis can continue. +This process may cause some errors in the text to be missed. +.PP +Consider the following example: +.LS +% \*bpix -l synerr2.p\fR +.so synerr2out +% +.LE +Here we misspelled +.I input +and gave a +.SM FORTRAN +style variable declaration +which the translator diagnosed as a `Malformed declaration'. +When, on line 6, we used `(' and `)' for subscripting +(as in +.SM FORTRAN ) +rather than the `[' and `]' which are used in Pascal, +the translator noted that +.I a +was not defined as a +.B procedure . +This occurred because +.B procedure +and +.B function +argument lists are delimited by parentheses in Pascal. +As it is not permissible to assign to procedure calls the translator +diagnosed a malformed statement at the point of assignment. +.SH +Expected and unexpected end-of-file, ``QUIT'' +.PP +If the translator finds a complete program, but there is more non-comment text +in the input file, then it will indicate that an end-of-file was expected. +This situation may occur after a bracketing error, or if too many +.B end s +are present in the input. +The message may appear +after the recovery says that it +``Expected \`.\'\|'' +since `.' is the symbol that terminates a program. +.PP +If severe errors in the input prohibit further processing +the translator may produce a diagnostic followed by ``QUIT''. +One example of this was given above \- +a non-terminated comment; +another example is a line which is longer than 160 +characters. +Consider also the following example. +.LS +% \*bpix -l mism.p\fR +.so mismout +% +.LE +.NH 2 +Translator semantic errors +.PP +The extremely large number of semantic diagnostic messages which the translator +produces make it unreasonable to discuss each message or group of messages +in detail. +The messages are, however, very informative. +We will here explain the typical formats and the terminology used in the error +messages so that you will be able to make sense out of them. +In any case in which a diagnostic is not completely comprehensible you can +refer to the +.I "User Manual" +by Jensen and Wirth for examples. +.SH +Format of the error diagnostics +.PP +As we saw in the example program above, the error diagnostics from +the Pascal translator include the number of a line in the text of the program +as well as the text of the error message. +While this number is most often the line where the error occurred, it +is occasionally the number of a line containing a bracketing keyword +like +.B end +or +.B until . +In this case, the diagnostic may refer to the previous statement. +This occurs because of the method the translator uses for sampling line +numbers. +The absence of a trailing `;' in the previous statement causes the line +number corresponding to the +.B end +or +.B until . +to become associated with the statement. +As Pascal is a free-format language, the line number associations +can only be approximate and may seem arbitrary to some users. +This is the only notable exception, however, to reasonable associations. +.SH +Incompatible types +.PP +Since Pascal is a strongly typed language, many semantic errors manifest +themselves as type errors. +These are called `type clashes' by the translator. +The types allowed for various operators in the language are summarized on page +108 of the +Jensen-Wirth +.I "User Manual" . +It is important to know that the Pascal translator, in its diagnostics, +distinguishes between the following type `classes': +.br +.ne 8 +.TS +center; +lew(10) le le le le. +array Boolean char file integer +pointer real record scalar string +.TE +These words are plugged into a great number of error messages. +Thus, if you tried to assign an +.I integer +value to a +.I char +variable you would receive a diagnostic like the following: +.LS +.so clashout +.LE +In this case, one error produced a two line error message. +If the same error occurs more than once, the same explanatory +diagnostic will be given each time. +.SH +Scalar +.PP +The only class whose meaning is not self-explanatory is +`scalar'. +Scalar has a precise meaning in the +Jensen-Wirth +.I "User Manual" +where, in fact, it refers to +.I char , +.I integer , +.I real , +and +.I Boolean +types as well as the enumerated types. +For the purposes of the Pascal translator, +scalar +in an error message refers to a user-defined, enumerated +type, such as +.I ops +in the example above or +.I color +in +.LS +\*btype\fP color = (red, green, blue) +.LE +For integers, the more explicit denotation +.I integer +is used. +Although it would be correct, in the context of the +.I "User Manual" +to refer to an integer variable as a +.I scalar +variable +.PI +prefers the more specific identification. +.SH +Function and procedure type errors +.PP +For built-in procedures and functions, two kinds of errors occur. +If the routines are called with the wrong number of arguments a message similar to: +.LS +.so sinout1 +.LE +is given. +If the type of the argument is wrong, a message like +.LS +.so sinout2 +.LE +is produced. +A few functions and procedures implemented in Pascal 6000-3.4 are +diagnosed as unimplemented in +Berkeley +Pascal, notably those related to +.B segmented +files. +.SH +Can't read and write scalars, etc. +.PP +The messages which state that scalar (user-defined) types +cannot be written to and from files are often mysterious. +It is in fact the case that if you define +.LS +\*btype\fP color = (red, green, blue) +.LE +the translator does not associate these constants with the strings +`red', `green', and `blue' in any way. +If you wish such an association to be made, you will have to write a routine +to make it. +Note, in particular, that you can only read characters, integers and real +numbers from text files. +You cannot read strings or Booleans. +It is possible to make a +.LS +\*bfile of\fP color +.LE +but the representation is binary rather than string. +.SH +Expression diagnostics +.PP +The diagnostics for semantically ill-formed expressions are very explicit. +Consider this sample translation: +.LS +% \*bpi -l expr.p\fP +.so exprout +% +.LE +This example is admittedly far-fetched, but illustrates that the error +messages are sufficiently clear to allow easy determination of the +problem in the expressions. +.SH +Type equivalence +.PP +Several diagnostics produced by the Pascal translator complain about +`non-equivalent types'. +In general, +Berkeley +Pascal considers variables to have the same type only if they were +declared with the same constructed type or with the same type identifier. +Thus, the variables +.I x +and +.I y +declared as +.LS +\*bvar\fP + x: ^ integer; + y: ^ integer; +.LE +do not have the same type. +The assignment +.LS +x := y +.LE +thus produces the diagnostics: +.LS +.so typequout +.LE +Thus it is always necessary to declare a type such as +.LS +\*btype\fP intptr = ^ integer; +.LE +and use it to declare +.LS +\*bvar\fP x: intptr; y: intptr; +.LE +Note that if we had initially declared +.LS +\*bvar\fP x, y: ^ integer; +.LE +then the assignment statement would have worked. +The statement +.LS +x^ := y^ +.LE +is allowed in either case. +Since the parameter to a +.B procedure +or +.B function +must be declared with a +type identifier rather than a constructed type, +it is always necessary, in practice, +to declare any type which will be used in this way. +.SH +Unreachable statements +.PP +Berkeley +Pascal flags unreachable statements. +Such statements usually correspond to errors in the program logic. +Note that a statement is considered to be reachable +if there is a potential path of control, +even if it can never be taken. +Thus, no diagnostic is produced for the statement: +.LS +\*bif\fP false \*bthen\fP + writeln('impossible!') +.LE +.SH +Goto's into structured statements +.PP +The translator detects and complains about +.B goto +statements which transfer control into structured statements (\c +.B for , +.B while , +etc.) +It does not allow such jumps, nor does it allow branching from the +.B then +part of an +.B if +statement into the +.B else +part. +Such checks are made only within the body of a single procedure or +function. +.SH +Unused variables, never set variables +.PP +Although +Berkeley +Pascal always clears variables to 0 at +.B procedure +and +.B function +entry, it is +.B not +good programming practice to rely on this initialization. +To discourage this practice, and to help detect errors in program logic, +.PI +flags as a `w' warning error: +.IP +.RS +.HP 1) +Use of a variable which is never assigned a value. +.IP 2) +A variable which is declared but never used, distinguishing +between those variables for which values are computed but which are never +used, and those completely unused. +.RE +.LP +In fact, these diagnostics are applied to all declared items. +Thus a +.B constant +or a +.B procedure +which is declared but never used is flagged. +The +.B w +option of +.PI +may be used to suppress these warnings; +see sections 5.1 and 5.2. +.NH 2 +Translator panics, i/o errors +.SH +Panics +.PP +One class of error which rarely occurs, but which causes termination +of all processing when it does is a panic. +A panic indicates a translator-detected internal inconsistency. +A typical panic message is: +.LS +snark (rvalue) line=110 yyline=109 +Snark in pi +.LE +If you receive such a message, the translation will be quickly and perhaps +ungracefully terminated. +You should contact a teaching assistant or a member of the system staff, +after saving a copy of your program for later inspection. +If you were making changes to an existing program when the problem +occurred, you may +be able to work around the problem by ascertaining which change caused the +.I snark +and making a different change or correcting an error in the program. +You should report the problem in any case. +Pascal system bugs cannot be fixed unless they are reported. +.SH +Out of memory +.PP +The only other error which will abort translation when no errors are +detected is running out of memory. +All tables in the translator, with the exception of the parse stack, +are dynamically allocated, and can grow to take up the full available +process space of 64000 bytes. +Generally, the size of the largest translatable program is directly related to +.B procedure +and +.B function +size. +A number of non-trivial Pascal programs, including +some with more than 2000 lines and 2500 statements +have been translated and interpreted using +Berkeley +Pascal. +Notable among these are the Pascal-S +interpreter, +a large set of programs for automated generation of +code generators, +and a general context-free parsing program which has been used to +parse sentences with a grammar for a superset of English. +.PP +If you receive an out of space message from the translator +during translation of a large +.B procedure +or +.B function +or one containing a large number of string constants +you may yet be able +to translate your program if you break this one +.B procedure +or +.B function +into several routines. +.SH +I/O errors +.PP +Other errors which you may encounter when running +.PI +relate to input-output. +If +.PI +cannot open the file you specify, +or if the file is empty, +you will be so informed. +If your disk space quota\*(dg is exceeded while +.PI +is creating the file +.I obj , +or if the system runs out of disk space you will be notified; +in this case you should remove unneeded files. +.FS +\*(dgDisk quotas are also a modification at Berkeley +and may not exist at your installation. +.FE +.NH 2 +Run-time errors +.PP +We saw, in our second example, a run-time error. +We here give the general description of run-time errors. +The more unusual interpreter error messages are explained +briefly in the manual section for +.I px +(6). +.SH +Start-up errors +.PP +These errors occur when the object file to be executed is not available +or appropriate. +Typical errors here are caused by the specified object file not existing, +not being a Pascal object, or being inaccessible to the user. +.SH +Program execution errors +.PP +These errors occur when the program interacts with the Pascal runtime +environment in an inappropriate way. +Typical errors are values or subscripts out of range, +bad arguments to built-in functions, +exceeding the statement limit because of an infinite loop, +or running out of memory\*(dd. +.FS +\*(ddThe checks for running out of memory are not foolproof and there +is a chance that the interpreter will fault, producing a core image +when it runs out of memory. +This situation occurs very rarely. +.FE +The interpreter will produce a backtrace after the error occurs, +showing all the active routine calls, +unless the +.B p +option was disabled when the program was translated. +Unfortunately, no variable values are given and no way of extracting them +is available. +.PP +As an example of such an error, assume that we have accidentally +declared the constant +.I n1 +to be 6, instead of 7 +on line 2 of the program primes as given in section 2.6 above. +If we run this program we get the following response. +.LS +% \*bpix primes.p\fP +.so primeout3 +% +.LE +.PP +Here the interpreter indicates that the program terminated +abnormally due to a subscript out of range near line 14, +which is eight lines into the body of the program primes. +.SH +Interrupts +.PP +If the program is interrupted while executing +and the +.B p +option was not specified, +then a backtrace will be printed.\*(dg +.FS +\*(dgOccasionally, the Pascal system will be in an inconsistent +state when this occurs, +e.g. when an interrupt terminates a +.B procedure +or +.B function +entry or exit. +In this case, the backtrace will only contain the current line. +A reverse call order list of procedures will not be given. +.FE +The file +.I pmon.out +of profile information will be written if the program was translated +with the +.B z +option enabled to +.PI +or +.IX . +.SH +I/O interaction errors +.PP +The final class of interpreter errors results from inappropriate +interactions with files, including the user's terminal. +Included here are bad formats for integer and real numbers (such as +no digits after the decimal point) when reading. +.SH +Panics +.PP +A small number of panics are possible with +.I px . +These should be reported to a teaching assistant or to the system +staff if they occur. diff --git a/doc/pascal/puman4.n b/doc/pascal/puman4.n new file mode 100644 index 0000000000..097187475b --- /dev/null +++ b/doc/pascal/puman4.n @@ -0,0 +1,577 @@ +.if \n(xx .bp +.if !\n(xx \{\ +.so tmac.p \} +.nr H1 3 +.if n 'ND +.NH +Input/output +.PP +This section describes features of the Pascal input/output environment, +with special consideration of the features peculiar to an +interactive implementation. +.NH 2 +Introduction +.PP +Our first sample programs, in section 2, used the file +.I output . +We gave examples there of redirecting the output to a file and to the line +printer using the shell. +Similarly, we can read the input from a file or another program. +Consider the following Pascal program which is similar to the program +.I cat +(1). +.LS +% \*bpix -l kat.p clean.p\fR +.LE +Note that since the shell creates the output file `clean.p' before +.XP +executes, so `clean.p' and `dirty.p' must not be the same file. +.PP +.I Pxp +automatically paragraphs the program, performing housekeeping +chores such as comment alignment, and +treating blank lines, lines containing exactly one blank +and lines containing only a form-feed character as though they +were comments, preserving their vertical spacing effect in the output. +.I Pxp +distinguishes between four kinds of comments: +.HP +.RS +.IP 1) +Left marginal comments, which begin in the first column of the +input line and are placed in the first column of an output line. +.IP 2) +Aligned comments, which are preceded by no input tokens on the +input line. +These are aligned in the output with the running program text. +.IP 3) +Trailing comments, which are preceded in the input line by a token with +no more than two spaces separating the token from the comment. +.IP 4) +Right marginal comments, which are preceded in the input line +by a token from which they are separated by at least three spaces or a tab. +These are aligned down the right margin of the output, +currently to the first tab stop after the 40th column from the current +``left margin''. +.RE +.LP +Consider the following program. +.LS +% \*bcat comments.p\fR +.so comments1.p +.LE +When formatted by +.XP +the following output is produced. +.LS +% \*bpxp comments.p\fR +.so commentsout +% +.LE +The following formatting related options are currently available in +.XP . +The options +.B f +and +.B j +described in the previous section may also be of interest. +.SH +Strip comments \-s +.PP +The +.B s +option causes +.XP +to remove all comments from the input text. +.SH +Underline keywords \- \_ +.PP +A command line argument of the form +.B \-\_ +as in +.LS +% \*bpxp -_ dirty.p\fR +.LE +can be used to cause +.XP +to underline all keywords in the output for enhanced readability. +.SH +Specify indenting unit \- [23456789] +.PP +The normal unit which +.XP +uses to indent a structure statement level is 4 spaces. +By giving an argument of the form +\fB\-\fId\fR +with +.I d +a digit, +2 \(<= +.I d +\(<= 9 +you can specify that +.I d +spaces are to be used per level instead. +.NH 2 +Pcc and carriage control +.PP +The +.UX +system printer driver does not implement +.SM FORTRAN +style carriage control. +Thus the function +.I page +on +.UX +does not output a character `1' +in column 1 of a line, but rather puts out a form-feed +character. +For those who wish to use carriage control, the filter +.I pcc +is available which interprets this control. +A sample usage is: +.LS +% \*bpx | pcc\fR +.LE +or +.LS +% \*bpix prog.p | pcc | lpr\fR +.LE +for printer copy. +.I Pcc +is fully described by its manual documentation +.I pcc +(6). +.NH 2 +Pxref +.PP +The cross-reference program +.I pxref +may be used to make cross-referenced listings of Pascal +programs. +To produce a cross-reference of the program in the file +`foo.p' +one can execute the command: +.LS +% \*bpxref foo.p\fR +.LE +The cross-reference is, unfortunately, not block structured. +Full details on +.I pxref +are given in its manual section +.I pxref +(6). +.NH 2 +Pascals +.PP +A version of Wirth's subset Pascal translator +.I pascals +is available on +.UX . +It was translated to interpreter code by +.PI +and is invoked by a command of the form: +.LS +% \*bpascals prog.p\fR +.LE +The program in the file given is translated to interpretive code +which is then immediately executed. +.I Pascals +is thus similar to +.I pix . +Only small programs can be handled. +.I Pascals +is most interesting to those wishing to study its error recovery techniques, +which are described in Wirth's book +.I "Algorithms + Data Structures = Programs" . +.NH 2 +Multi-file programs +.PP +A text inclusion facility is available with +.UP . +This facility allows the interpolation of source text from other +files into the source stream of the translator. +It can be used to divide large programs into more manageable pieces +for ease in editing, listing, and maintenance. +.PP +The +.B include +facility is based on that of the +.SM +UNIX +.NL +C compiler. +To trigger it you can place the character `#' in the first portion of +a line and then, after an arbitrary number of blanks or tabs, +the word +`include' +followed by a filename enclosed in single `\(aa' or double `"' quotation +marks. +The file name may be followed by a semicolon `;' if you wish to treat +this as a pseudo-Pascal statement. +The filenames of included files must end in `.i'. +An example of the use of included files in a main program would be: +.LS +\*bprogram\fR compiler(input, output, obj); + +#\*binclude\fR "globals.i" +#\*binclude\fR "scanner.i" +#\*binclude\fR "parser.i" +#\*binclude\fR "semantics.i" + +\*bbegin\fR + { main program } +\*bend\fR. +.LE +.PP +At the point the +.B include +pseudo-statement is encountered in the input, the lines from +the included file are interpolated into the input stream. +For the purposes of translate- and run-time diagnostics and +statement numbers in the listings and post-mortem backtraces, +the lines in the included file are numbered from 1. +Nested includes are possible up to 10 deep. +.PP +See the descriptions of the +.B i +and +.B n +options of +.PI +in section 5.2 +above; +these can be used to control listing when +.B include +files are present. +.PP +.I Include +control lines are never printed in a listing. +If the +.B n +option is not set, they are replaced by a line containing +the file name and a `:' character. +This is the default setting. +If the +.B n +new page option is enabled then the +.B include +line is replaced with a banner line similar to the first line +of a listing. +This line is placed on a new page in the listing. +.PP +When a non-trivial line is encountered in the source text after an +.B include +finishes, the +`popped' filename is printed, in the same manner as above. +.PP +For the purposes of error diagnostics when not making a listing, the filename +will be printed before each diagnostic if the current +filename has changed since the last +filename was printed. diff --git a/doc/pascal/pumanA.n b/doc/pascal/pumanA.n new file mode 100644 index 0000000000..ff2453c7b0 --- /dev/null +++ b/doc/pascal/pumanA.n @@ -0,0 +1,893 @@ +.if \n(xx .bp +.if !\n(xx \{\ +.so tmac.p \} +.ND +.nr H1 0 +.af H1 A +.NH +Appendix to Wirth's Pascal Report +.PP +This section is an appendix to +the definition of the Pascal language in Niklaus Wirth's +.I "Pascal Report" +and, with that Report, precisely defines the +Berkeley +implementation. +This appendix includes a summary of extensions to the language, +gives the ways in which the undefined specifications were resolved, +gives limitations and restrictions of the current implementation, +and lists the added functions and procedures available. +It concludes with a list of differences with the commonly available +Pascal 6000\-3.4 implementation, +and some comments on standard and portable Pascal. +.NH 2 +Extensions to the language Pascal +.PP +This section defines non-standard language constructs available in +.UP . +The +.B s +standard Pascal option of the translator +.PI +can be used to detect these extensions in programs which are to be transported. +.SH +String padding +.PP +.UP +will pad constant strings with blanks in expressions and as +value parameters to make them as long as is required. +The following is a legal +.UP +program: +.LS +\*bprogram\fP x(output); +\*bvar\fP z : \*bpacked\fP \*barray\fP [ 1 .. 13 ] \*bof\fP char; +\*bbegin\fP + z := 'red'; + writeln(z) +\*bend\fP; +.LE +The padded blanks are added on the right. +Thus the assignment above is equivalent to: +.LS +z := 'red ' +.LE +which is standard Pascal. +.SH +Octal constants, octal and hexadecimal write +.PP +Octal constants may be given as a sequence of octal digits followed +by the character `b' or `B'. +The forms +.LS +write(a:n \*boct\fP) +.LE +and +.LS +write(a:n \*bhex\fP) +.LE +cause the internal representation of +expression +.I a, +which must be Boolean, character, integer, pointer, or a user-defined enumerated +type, +to be written in octal or hexadecimal respectively. +.SH +Assert statement +.PP +An +.B assert +statement causes a +.I Boolean +expression to be evaluated +each time the statement is executed. +A runtime error results if any of the expressions evaluates to be +.I false . +The +.B assert +statement is treated as a comment if run-time tests are disabled. +The syntax for +.B assert +is: +.LS +\*bassert\fP +.LE +.br +.ne 8 +.NH 2 +Resolution of the undefined specifications +.SH +File name \- file variable associations +.PP +Each Pascal file variable is associated with a named +.UX +file. +Except for +.I input +and +.I output, +which are +exceptions to some of the rules, a name can become associated +with a file in any of three ways: +.IP "\ \ \ \ \ 1)" 10 +If a global Pascal file variable appears in the +.B program +statement +then it is associated with +.UX +file of the same name. +.IP "\ \ \ \ \ 2)" +If a file was reset or rewritten using the +extended two-argument form of +.I reset +or +.I rewrite +then the given name +is associated. +.IP "\ \ \ \ \ 3)" +If a file which has never had +.UX +name associated +is reset or rewritten without specifying a name +via the second argument, then a temporary name +of the form `tmp.x' +is associated with the file. +Temporary names start with +`tmp.1' and continue by incrementing the last character in the +.SM +USASCII +.NL +ordering. +Temporary files are removed automatically +when their scope is exited. +.SH +The program statement +.PP +The syntax of the +.B program +statement is: +.LS +\*bprogram\fP ( { , } ) ; +.LE +The file identifiers (other than +.I input +and +.I output ) +must be declared as variables of +.B file +type in the global declaration part. +.SH +The files input and output +.PP +The formal parameters +.I input +and +.I output +are associated with the +.UX +standard input and output and have a +somewhat special status. +The following rules must be noted: +.IP "\ \ \ \ \ 1)" 10 +The program heading +.B must +contains the formal parameter +.I output. +If +.I input +is used, explicitly or implicitly, then it must +also be declared here. +.IP "\ \ \ \ \ 2)" +Unlike all other files, the +Pascal files +.I input +and +.I output +must not be defined in a declaration, +as their declaration is automatically: +.LS +\*bvar\fP input, output: text +.LE +.IP "\ \ \ \ \ 3)" +The procedure +.I reset +may be used on +.I input. +If no +.UX +file name has ever been associated with +.I input, +and no file name is given, then an attempt will be made +to `rewind' +.I input. +If this fails, a run time +error will occur. +.I Rewrite +calls to output act as for any other file, except that +.I output +initially has no associated file. +This means that a simple +.LS +rewrite(output) +.LE +associates a temporary name with +.I output. +.SH +Details for files +.PP +If a file other than +.I input +is to be read, +then reading must be initiated by a call to the +procedure +.I reset +which causes the Pascal system to attempt to open the +associated +.UX +file for reading. +If this fails, then a runtime error occurs. +Writing of a file other than +.I output +must be initiated by a +.I rewrite +call, +which causes the Pascal system to create the associated +.UX +file and +to then open the file for writing only. +.SH +Buffering +.PP +The buffering for +.I output +is determined by the value of the +.B b +option +at the end of the +.B program +statement. +If it has its default value 1, +then +.I output +is +buffered in blocks of up to 512 characters, +flushed whenever a writeln occurs +and at each reference to the file +.I input. +If it has the value 0, +.I output +is unbuffered. +Any value of +2 or more gives block buffering without line or +.I input +reference flushing. +All other output files are always buffered in blocks of 512 characters. +All output buffers are flushed when the files are closed at scope exit, +whenever the procedure +.I message +is called, and can be flushed using the +built-in procedure +.I flush. +.PP +An important point for an interactive implementation is the definition +of `input\(ua'. +If +.I input +is a teletype, and the Pascal system reads a character at the beginning +of execution to define `input\(ua', then no prompt could be printed +by the program before the user is required to type some input. +For this reason, `input\(ua' is not defined by the system until its definition +is needed, reading from a file occurring only when necessary. +.SH +The character set +.PP +Seven bit +.SM USASCII +is the character set used on +.UX . +The standard Pascal +symbols `and', 'or', 'not', '<=', '>=', '<>', +and the uparrow `\(ua' (for pointer qualification) +are recognized.\*(dg +.FS +\*(dgOn many terminals and printers, the up arrow is represented +as a circumflex `^'. +These are not distinct characters, but rather different graphic +representations of the same internal codes. +.FE +Less portable are the +synonyms tilde `~' +for +.B not , +`&' for +.B and , +and `|' for +.B or . +.PP +Upper and lower case are considered distinct. +Keywords and built-in +.B procedure +and +.B function +names are +composed of all lower case letters. +Thus the identifiers GOTO and GOto are distinct both from each other and +from the keyword +\*bgoto\fP. +The standard type `boolean' is also available as `Boolean'. +.PP +Character strings and constants may be delimited by the character +`\'' +or by the character `#'; +the latter is sometimes convenient when programs are to be transported. +Note that the `#' character has special meaning +.up +when it is the first character on a line \- see +.I "Multi-file programs" +below. +.SH +The standard types +.PP +The standard type +.I integer +is conceptually defined as +.LS +\*btype\fP integer = minint .. maxint; +.LE +.I Integer +is implemented with 32 bit twos complement arithmetic. +Predefined constants of type +.I integer +are: +.LS +\*bconst\fP maxint = 2147483647; minint = -2147483648; +.LE +.PP +The standard type +.I char +is conceptually defined as +.LS +\*btype\fP char = minchar .. maxchar; +.LE +Built-in character constants are `minchar' and `maxchar', `bell' and `tab'; +ord(minchar) = 0, ord(maxchar) = 127. +.PP +The type +.I real +is implemented using 64 bit floating point arithmetic. +The floating point arithmetic is done in `rounded' mode, and +provides approximately 17 digits of precision +with numbers as small as 10 to the negative 38th power and as large as +10 to the 38th power. +.SH +Comments +.PP +Comments can be delimited by either `{' and `}' or by `(*' and `*)'. +If the character `{' appears in a comment delimited by `{' and `}', +a warning diagnostic is printed. +A similar warning will be printed if the sequence `(*' appears in +a comment delimited by `(*' and `*)'. +The restriction implied by this warning is not part of standard Pascal, +but detects many otherwise subtle errors. +.SH +Option control +.PP +Options of the translator may be controlled +in two distinct ways. +A number of options may appear on the command line invoking the translator. +These options are given as one or more strings of letters preceded by the +character `\-' and cause the default setting of +each given option to be changed. +This method of communication of options is expected to predominate +for +.UX . +Thus the command +.LS +% \*bpi \-ls foo.p\fR +.LE +translates the file foo.p with the listing option enabled (as it normally +is off), and with only standard Pascal features available. +.PP +If more control over the portions of the program where options are enabled is +required, then option control in comments can and should be used. +The +format for option control in comments is identical to that used in Pascal +6000\-3.4. +One places the character `$' as the first character of the comment +and follows it by a comma separated list of directives. +Thus an equivalent to the command line example given above would be: +.LS +{$l+,s+ listing on, standard Pascal} +.LE +as the first line of the program. +The `l' +option is more appropriately specified on the command line, +since it is extremely unlikely in an interactive environment +that one wants a listing of the program each time it is translated. +.PP +Directives consist of a letter designating the option, +followed either by a `+' to turn the option on, or by a `\-' to turn the +option off. +The +.B b +option takes a single digit instead of +a `+' or `\-'. +.SH +Notes on the listings +.PP +The first page of a listing +includes a banner line indicating the version and date of generation of +.PI . +It also +includes the +.UX +path name supplied for the source file and the date of +last modification of that file. +.PP +Within the body of the listing, lines are numbered consecutively and +correspond to the line numbers for the editor. +Currently, two special +kinds of lines may be used to format the listing: +a line consisting of a form-feed +character, control-l, which causes a page +eject in the listing, and a line with +no characters which causes the line number to be suppressed in the listing, +creating a truly blank line. +These lines thus correspond to `eject' and `space' macros found in many +assemblers. +Non-printing characters are printed as the character `?' in the listing.\*(dg +.FS +\*(dgThe character generated by a control-i indents +to the next `tab stop'. +Tab stops are set every 8 columns in +.UX . +Tabs thus provide a quick way of indenting in the program. +.FE +.SH +Multi-file programs +.PP +It is also possible to prepare programs whose parts are placed in more +than one file. +The files other than the main one are called +.B include +files and have names ending with `.i'. +The contents of an \*binclude\fR file are referenced through a pseudo-statement +of the form: +.LS +#\*binclude\fR "file.i" +.LE +The `#' character must be the first character on the line. +The file name may be delimited with `"' or `\'' characters. +Nested +.B include s +are possible up to 10 deep. +More details are given in sections 5.9 and 5.10. +.SH +The standard procedure write +.PP +If no minimum field length parameter is specified +for a +.I write, +the following default +values are assumed: +.KS +.TS +center; +l n. +integer 10 +real 22 +Boolean 10 +char 1 +string length of the string +oct 11 +hex 8 +.TE +.KE +The end of each line in a text file should be explicitly +indicated by `writeln(f)', where `writeln(output)' may be written +simply as `writeln'. +For +.UX , +the built-in function `page(f)' puts a single +.SM ASCII +form-feed character on the output file. +For programs which are to be transported the filter +.I pcc +can be used to interpret carriage control, as +.UX +does not normally do so. +.NH 2 +Restrictions and limitations +.SH +Files +.PP +Files cannot be members of files or members of dynamically +allocated structures. +.SH +Arrays, sets and strings +.PP +The calculations involving array subscripts and set elements +are done with 16 bit arithmetic. +This +restricts the types over which arrays and sets may be defined. +The lower bound of such a range must be greater than or equal to +\-32768, and the upper bound less than 32768. +In particular, strings may have any length from 1 to 32767 characters, +and sets may contain no more than 32767 elements. +.SH +Line and symbol length +.PP +There is no intrinsic limit on the length of identifiers. +Identifiers +are considered to be distinct if they differ +in any single position over their entire length. +There is a limit, however, on the maximum input +line length. +This is quite generous however, currently exceeding 160 +characters. +.SH +Procedure and function nesting and program size +.PP +At most 20 levels of +.B procedure +and +.B function +nesting are allowed. +There is no fundamental, translator defined limit on the size of the +program which can be translated. +The ultimate limit is supplied by the +hardware and the fact that the \s-2PDP\s0-11 has a 16 bit address space. +If +one runs up against the `ran out of memory' diagnostic the program may yet +translate if smaller procedures are used, as a lot of space is freed +by the translator at the completion of each +.B procedure +or +.B function +in the current +implementation. +.SH +Overflow +.PP +There is currently no checking for overflow on arithmetic operations at +run-time. +.br +.ne 15 +.NH 2 +Added types, operators, procedures and functions +.SH +Additional predefined types +.PP +The type +.I alfa +is predefined as: +.LS +\*btype\fP alfa = \*bpacked\fP \*barray\fP [ 1..10 ] \*bof\fP \*bchar\fP +.LE +.PP +The type +.I intset +is predefined as: +.LS +\*btype\fP intset = \*bset of\fP 0..127 +.LE +In most cases the context of an expression involving a constant +set allows the translator to determine the type of the set, even though the +constant set itself may not uniquely determine this type. +In the +cases where it is not possible to determine the type of the set from +local context, the expression type defaults to a set over the entire base +type unless the base type is integer\*(dg. +.FS +\*(dgThe current translator makes a special case of the construct +`if ... in [ ... ]' and enforces only the more lax restriction +on 16 bit arithmetic given above in this case. +.FE +In the latter case the type defaults to the current +binding of +.I intset, +which must be ``type set of (a subrange of) integer'' at that point. +.PP +Note that if +.I intset +is redefined via: +.LS +\*btype\fP intset = \*bset of\fP 0..58; +.LE +then the default integer set is the implicit +.I intset +of +Pascal 6000\-3.4 +.SH +Additional predefined operators +.PP +The relationals `<' and `>' of proper set +inclusion are available. +With +.I a +and +.I b +sets, note that +.LS +(\*bnot\fR (\fIa\fR < \fIb\fR)) <> (\fIa\fR >= \fIb\fR) +.LE +As an example consider the sets +.I a += [0,2] +and +.I b += [1]. +The only relation true between these sets is `<>'. +.SH +Non-standard procedures +.IP argv(i,a) 25 +where +.I i +is an integer and +.I a +is a string variable +assigns the (possibly truncated or blank padded) +.I i \|'th +argument +of the invocation of the current +.UX +process to the variable +.I a . +The range of valid +.I i +is +.I 0 +to +.I argc\-1 . +.IP date(a) +assigns the current date to the alfa variable +.I a +in the format `dd mmm yy ', where `mmm' is the first +three characters of the month, i.e. `Apr'. +.IP flush(f) +writes the output buffered for Pascal file +.I f +into the associated +.UX +file. +.IP halt +terminates the execution of the program with +a control flow backtrace. +.IP linelimit(f,x)\*(dd +.FS +\*(ddCurrently ignored by +.X . +.FE +with +.I f +a textfile and +.I x +an integer expression +causes +the program to be abnormally terminated if more than +.I x +lines are +written on file +.I f . +If +.I x +is less than 0 then no limit is imposed. +.IP message(x,...) +causes the parameters, which have the format of those +to the +built-in +.B procedure +.I write, +to be written unbuffered on the diagnostic unit 2, +almost always the user's terminal. +.IP null +a procedure of no arguments which does absolutely nothing. +It is useful as a place holder, +and is generated by +.XP +in place of the invisible empty statement. +.IP remove(a) +where +.I a +is a string causes the +.UX +file whose +name is +.I a, +with trailing blanks eliminated, to be removed. +.IP reset(f,a) +where +.I a +is a string causes the file whose name +is +.I a +(with blanks trimmed) to be associated with +.I f +in addition +to the normal function of +.I reset. +.IP rewrite(f,a) +is analogous to `reset' above. +.IP stlimit(i) +where +.I i +is an integer sets the statement limit to be +.I i +statements. +Specifying the +.B p +option to +.I pc +disables statement limit counting. +.IP time(a) +causes the current time in the form `\ hh:mm:ss\ ' to be +assigned to the alfa variable +.I a. +.SH +Non-standard functions +.IP argc 25 +returns the count of arguments when the Pascal program +was invoked. +.I Argc +is always at least 1. +.IP card(x) +returns the cardinality of the set +.I x, +i.e. the +number of elements contained in the set. +.IP clock +returns an integer which is the number of central processor +milliseconds of user time used by this process. +.IP expo(x) +yields the integer valued exponent of the floating-point +representation of +.I x ; +expo(\fIx\fP) = entier(log2(abs(\fIx\fP))). +.IP random(x) +where +.I x +is a real parameter, evaluated but otherwise +ignored, invokes a linear congruential random number generator. +Successive seeds are generated as (seed*a + c) mod m and +the new random number is a normalization of the seed to the range 0.0 to 1.0; +a is 62605, c is 113218009, and m is +536870912. +The initial seed +is 7774755. +.IP seed(i) +where +.I i +is an integer sets the random number generator seed +to +.I i +and returns the previous seed. +Thus seed(seed(i)) +has no effect except to yield value +.I i. +.IP sysclock +an integer function of no arguments returns the number of central processor +milliseconds of system time used by this process. +.IP undefined(x) +a Boolean function. +Its argument is a real number and +it always returns false. +.IP wallclock +an integer function of no arguments returns the time +in seconds since 00:00:00 GMT January 1, 1970. +.NH 2 +Remarks on standard and portable Pascal +.PP +It is occasionally desirable to prepare Pascal programs which will be +acceptable at other Pascal installations. +While certain system dependencies are bound to creep in, +judicious design and programming practice can usually eliminate +most of the non-portable usages. +Wirth's +.I "Pascal Report" +concludes with a standard for implementation and program exchange. +.PP +In particular, the following differences may cause trouble when attempting +to transport programs between this implementation and Pascal 6000\-3.4. +Using the +.B s +translator option may serve to indicate many problem areas.\*(dg +.FS +\*(dgThe +.B s +option does not, however, check that identifiers differ +in the first 8 characters. +.I Pi +also does not check the semantics of +.B packed . +.FE +.SH +Features not available in Berkeley Pascal +.IP +Formal parameters which are +.B procedure +or +.B function . +.IP +Segmented files and associated functions and procedures. +.IP +The function +.I trunc +with two arguments. +.IP +Arrays whose indices exceed the capacity of 16 bit arithmetic. +.SH +Features available in Berkeley Pascal but not in Pascal 6000-3.4 +.IP +The procedures +.I reset +and +.I rewrite +with file names. +.IP +The functions +.I argc, +.I seed, +.I sysclock, +and +.I wallclock. +.IP +The procedures +.I argv, +.I flush, +and +.I remove. +.IP +.I Message +with arguments other than character strings. +.IP +.I Write +with keyword +.B hex . +.IP +The +.B assert +statement. +.SH +Other problem areas +.PP +Sets and strings are more general in \* +.UP ; +see the restrictions given in +the +Jensen-Wirth +.I "User Manual" +for details on the 6000\-3.4 restrictions. +.PP +The character set differences may cause problems, +especially the use of the function +.I chr, +characters as arguments to +.I ord, +and comparisons of characters, +since the character set ordering +differs between the two machines. +.PP +The Pascal 6000\-3.4 compiler uses a less strict notion of type equivalence. +In +.UP , +types are considered identical only if they are represented +by the same type identifier. +Thus, in particular, unnamed types are unique +to the variables/fields declared with them. +.PP +Pascal 6000\-3.4 doesn't recognize our option +flags, so it is wise to +put the control of +.UP +options to the end of option lists or, better +yet, restrict the option list length to one. +.PP +For Pascal 6000\-3.4 the ordering of files in the program statement has +significance. +It is desirable to place +.I input +and +.I output +as the first two files in the +.B program +statement. diff --git a/doc/pascal/sin1.p b/doc/pascal/sin1.p new file mode 100644 index 0000000000..21248836fe --- /dev/null +++ b/doc/pascal/sin1.p @@ -0,0 +1,13 @@ +program sinout(output); +begin + + + + + + + + + +write(sin(1,2)); +end. diff --git a/doc/pascal/sin2.p b/doc/pascal/sin2.p new file mode 100644 index 0000000000..4a2cc3177e --- /dev/null +++ b/doc/pascal/sin2.p @@ -0,0 +1,13 @@ +program sinout(output); +begin + + + + + + + + + +write(sin('*')); +end. diff --git a/doc/pascal/sinout1 b/doc/pascal/sinout1 new file mode 100644 index 0000000000..6620f40f94 --- /dev/null +++ b/doc/pascal/sinout1 @@ -0,0 +1 @@ +E 12 - sin takes exactly one argument diff --git a/doc/pascal/sinout2 b/doc/pascal/sinout2 new file mode 100644 index 0000000000..e0b6cd2460 --- /dev/null +++ b/doc/pascal/sinout2 @@ -0,0 +1 @@ +E 12 - sin's argument must be integer or real, not char diff --git a/doc/pascal/synerr.p b/doc/pascal/synerr.p new file mode 100644 index 0000000000..33c13e7403 --- /dev/null +++ b/doc/pascal/synerr.p @@ -0,0 +1,9 @@ +progran syn(output); +var i, j are integer; +begin + for j :* 1 to 20 begin + write(j); + i = 2 ** j; + writeln(i)) + end +end. diff --git a/doc/pascal/synerr2.p b/doc/pascal/synerr2.p new file mode 100644 index 0000000000..4b7be594db --- /dev/null +++ b/doc/pascal/synerr2.p @@ -0,0 +1,7 @@ +program synerr2(input,outpu); +integer a(10) +begin + read(b); + for c := 1 to 10 do + a(c) := b * c; +end. diff --git a/doc/pascal/synerr2out b/doc/pascal/synerr2out new file mode 100644 index 0000000000..43bf620f25 --- /dev/null +++ b/doc/pascal/synerr2out @@ -0,0 +1,23 @@ +Berkeley Pascal PI -- Version 1.1 (January 4, 1979) + +Sat Mar 31 11:50 1979 synerr2.p + + 1 program synerr2(input,outpu); + 2 integer a(10) +E \l'\w`w `u-\w`E `u '\l'\w` 2 `u-\w`w `u\&\(rh'\l'(\w`i`u-\w`^`u)/2 '\(ua\l'(\w`i`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Malformed declaration + 3 begin + 4 read(b); +E \l'\w`w `u-\w`E `u '\l'\w` 4 read(`u-\w`w `u\&\(rh'\l'(\w`b`u-\w`^`u)/2 '\(ua\l'(\w`b`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Undefined variable + 5 for c := 1 to 10 do +E \l'\w`w `u-\w`E `u '\l'\w` 5 for `u-\w`w `u\&\(rh'\l'(\w`c`u-\w`^`u)/2 '\(ua\l'(\w`c`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Undefined variable + 6 a(c) := b * c; +E \l'\w`w `u-\w`E `u '\l'\w` 6 `u-\w`w `u\&\(rh'\l'(\w`a`u-\w`^`u)/2 '\(ua\l'(\w`a`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Undefined procedure +E \l'\w`w `u-\w`E `u '\l'\w` 6 a(c) `u-\w`w `u\&\(rh'\l'(\w`:`u-\w`^`u)/2 '\(ua\l'(\w`:`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Malformed statement + 7 end. +E 1 - File outpu listed in program statement but not declared +e 1 - The file output must appear in the program statement file list +In program synerr2: + E - a undefined on line 6 + E - b undefined on line 4 + E - c undefined on lines 5 6 +Execution suppressed due to compilation errors diff --git a/doc/pascal/synerrout b/doc/pascal/synerrout new file mode 100644 index 0000000000..66e963e2d4 --- /dev/null +++ b/doc/pascal/synerrout @@ -0,0 +1,20 @@ +Berkeley Pascal PI -- Version 1.1 (January 4, 1979) + +Sat Mar 31 11:50 1979 synerr.p + + 1 progran syn(output); +e \l'\w`w `u-\w`e `u '\l'\w` 1 `u-\w`w `u\&\(rh'\l'(\w`p`u-\w`^`u)/2 '\(ua\l'(\w`p`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Replaced identifier with a keyword program + 2 var i, j are integer; +e \l'\w`w `u-\w`e `u '\l'\w` 2 var i, j `u-\w`w `u\&\(rh'\l'(\w`a`u-\w`^`u)/2 '\(ua\l'(\w`a`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Replaced identifier with a ':' + 3 begin + 4 for j :* 1 to 20 begin +e \l'\w`w `u-\w`e `u '\l'\w` 4 for j :`u-\w`w `u\&\(rh'\l'(\w`*`u-\w`^`u)/2 '\(ua\l'(\w`*`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Replaced '*' with a '=' +e \l'\w`w `u-\w`e `u '\l'\w` 4 for j :* 1 to 20 `u-\w`w `u\&\(rh'\l'(\w`b`u-\w`^`u)/2 '\(ua\l'(\w`b`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted keyword do + 5 write(j); + 6 i = 2 ** j; +e \l'\w`w `u-\w`e `u '\l'\w` 6 i `u-\w`w `u\&\(rh'\l'(\w`=`u-\w`^`u)/2 '\(ua\l'(\w`=`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted ':' +E \l'\w`w `u-\w`E `u '\l'\w` 6 i = 2 *`u-\w`w `u\&\(rh'\l'(\w`*`u-\w`^`u)/2 '\(ua\l'(\w`*`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Inserted identifier + 7 writeln(i)) +E \l'\w`w `u-\w`E `u '\l'\w` 7 writeln(i)`u-\w`w `u\&\(rh'\l'(\w`)`u-\w`^`u)/2 '\(ua\l'(\w`)`u-\w`^`u)/2 '\l'\w`---`u\&\(rh' Deleted ')' + 8 end + 9 end. diff --git a/doc/pascal/tmac.p b/doc/pascal/tmac.p new file mode 100644 index 0000000000..08901f1d9a --- /dev/null +++ b/doc/pascal/tmac.p @@ -0,0 +1,76 @@ +'so /usr/lib/tmac/tmac.s +.if t .tr \(rh- +.if t .tr *\(**=\(eq/\(sl+\(pl +.bd S B 3 +.de SM +.if "\\$1"" .ps -2 +.if !"\\$1"" \s-2\\$1\s0\\$2 +.. +.de LG +.if "\\$1"" .ps +2 +.if !"\\$1"" \s+2\\$a\s0\\$2 +.. +.de HP +.nr pd \\n(PD +.nr PD 0 +.if \\n(.$=0 .IP +.if \\n(.$=1 .IP "\\$1" +.if \\n(.$>=2 .IP "\\$1" "\\$2" +.nr PD \\n(pd +.rm pd +.. +.de LS \"LS - Literal display, ASCII, constant spaced DS +.XD +.ID +.nf +.if t .tr '\'`\`^\(ua-\(mi +.if t .tr _\(ul +.. +.de LE \"LE - End literal display +.DE +.tr ''``__--^^ +.. +.de UP +Berkeley Pascal\\$1 +.. +.de PD +\s-2PDP\s0 +.if \\n(.$=0 11/70 +.if \\n(.$>0 11/\\$1 +.. +.de DK +Digital Equipment Corporation\\$1 +.. +.de IN +.I +.if \\n(.$<2 \\$1 1.0 Implementation Notes +.if \\n(.$>=2 \\$1 1.0 Implementation Notes\\c +.R +.if \\n(.$>=2 \\$2 +.. +.de UM +.I +User's Manual +.R +.. +.de PI +.I pi \\$1 +.. +.de XP +.I pxp \\$1 +.. +.de IX +.I pix \\$1 +.. +.de X +.I px \\$1 +.. +.if n .ds dg + +.if t .ds dg \(dg +.if n .ds dd * +.if t .ds dd \(dd +.if n .nr FM 1.12i +.if t .ds b \\fB +.if n .ds b \\fI +.ds i \\fI +.nr xx 1 diff --git a/doc/pascal/typequ.p b/doc/pascal/typequ.p new file mode 100644 index 0000000000..7d080dc50d --- /dev/null +++ b/doc/pascal/typequ.p @@ -0,0 +1,10 @@ +program x(output); +var + x: ^ integer; + y: ^ integer; +begin + new(y); + x := y; + x^ := 1; + x := x; +end. diff --git a/doc/pascal/typequout b/doc/pascal/typequout new file mode 100644 index 0000000000..46615f2790 --- /dev/null +++ b/doc/pascal/typequout @@ -0,0 +1,2 @@ +E 7 - Type clash: non-identical pointer types + ... Type of expression clashed with type of variable in assignment diff --git a/doc/pascal/xxxxqqqout b/doc/pascal/xxxxqqqout new file mode 100644 index 0000000000..a2c8ee2ef2 --- /dev/null +++ b/doc/pascal/xxxxqqqout @@ -0,0 +1,5 @@ +xxxxqqq: No such file or directory + + Error at "kat"+5 near line 11 + +4 statements executed in 0.01 seconds cpu time diff --git a/doc/pascal/xxxxqqqout2 b/doc/pascal/xxxxqqqout2 new file mode 100644 index 0000000000..79145e8748 --- /dev/null +++ b/doc/pascal/xxxxqqqout2 @@ -0,0 +1 @@ +xxxxqqq: No such file or directory diff --git a/doc/px/fig1.1.n b/doc/px/fig1.1.n new file mode 100644 index 0000000000..3acfbbfd8a --- /dev/null +++ b/doc/px/fig1.1.n @@ -0,0 +1,45 @@ +.KF +.TS +center; +c l +l l +_ l +| l | +| cw(18) | aw(28) +| _ | l +| c | +| _ | a +| c | +| l | +| _ | l +c l. +Base of stack frame + + + +Block mark Positive offsets +.sp + \(<- Display entry points here +T{ +.sp +Local variables +T} + Negative offsets +T{ +.sp +Temporary +.br +expression +.br +space +T} + + +.sp +Top of stack frame +.sp +.TE +.ce +Figure 1.1 \- Structure of stack frame +.sp +.KE diff --git a/doc/px/fig1.2.n b/doc/px/fig1.2.n new file mode 100644 index 0000000000..3dd4caa2fe --- /dev/null +++ b/doc/px/fig1.2.n @@ -0,0 +1,47 @@ +.KF +.TS +center; +l l +| lw(22n) | aw(20n). +_ +T{ +.ce 1000 +.sp +Saved lino +.sp +Saved lc +.sp +Saved dp +.sp +.ce 0 +T} T{ +.if n .sp 2 +Created by \s-2CALL\s0 +T} +_ +T{ +.ce 1000 +.sp +Saved dp contents +.sp +Pointer to current +section name and +entry line +.sp +Current file name +and buffer +.sp +Top of stack reference +.sp +.ce 0 +T} T{ +.if n .sp 2 +Created by \s-2BEG\s0 +T} +_ +.TE +.sp +.ce +Figure 1.2 \- Block mark structure +.sp +.KE diff --git a/doc/px/fig1.3.n b/doc/px/fig1.3.n new file mode 100644 index 0000000000..958d745ff3 --- /dev/null +++ b/doc/px/fig1.3.n @@ -0,0 +1,27 @@ +.TS +center, allbox; +lw(20). +T{ +.nf +.ce 1000 +Space for +value returned +from f +.ce 0 +.fi +T} +T{ +.ce +Value of a +T} +T{ +.sp +.ce +Block Mark +.sp +T} +.TE +.sp .1i +.ce +Figure 1.3 \- Stack structure on function call `f(a)' +.sp .1i diff --git a/doc/px/fig2.1.n b/doc/px/fig2.1.n new file mode 100644 index 0000000000..e74836e6d3 --- /dev/null +++ b/doc/px/fig2.1.n @@ -0,0 +1,92 @@ +ABORT 2.2 Halt execution immediately for debugging +ABS* 2.7 Absolute value +ADD* 2.7 Addition +AND 2.4 Boolean and +ARGC 2.13 Built-in function +ARGV 2.13 Built-in procedure +AS* 2.5 Assignment operators +ASRT 2.12 Assert true to continue +ATAN 2.13 Built-in function +BEG w,w," 2.2,1.8 Write second part of block mark, enter block +BUFF 3.6 Specify buffering for file output +CALL l,a 2.2,1.8 Procedure or function call +CARD s 2.11 Cardinality of set +CASEOP* 2.9 Case statements +CHR* 2.13 Built-in function +CLCK 2.13 Built-in function clock +CON* v 2.5 Load constant operators +COUNT s 2.10 Count a statement count point +CTTOT s,w,w 2.11 Construct set +DATE 2.13 Built-in procedure +DEFNAME s 3.6 Attach file name for prgram statement files +DISPOSE 2.13 Built-in procedure +DIV* 2.7 Division +DVD* 2.7 Floating division +END 2.2,1.8 End block execution +EOF 3.6 Boolean built-in function +EOLN 3.6 Boolean built-in function +EXP 2.13 Built-in function +EXPO 2.13 Built-in function yielding exponent of real +FNIL 3.6 Check file initialized, not eof, synced +FOR* a 2.12 For statements +GET 3.6 File procedure get +GOTO l,a 2.2,1.8 Non-local goto statement +HALT 2.2 Produce control flow backtrace +IF a 2.3 Conditional transfer +IN s,w,w 2.11 Set membership +INCT 2.11 Membership in a constructed set +IND* 2.6 Indirection operators +INX* s,w,w 2.6 Subscripting (indexing) operator +ITOD 2.12 Convert integer to real +ITOS 2.12 Convert integer to short integer +LINO s 2.2 Set line number, count statements +LLIMIT 2.13 Built-in procedure +LN 2.13 Built-in function +LV l,w 2.6 Address of operator +MESSAGE l 3.6 Write to terminal, built-in procedure +MOD* 2.7 Modulus +MUL* 2.7 Multiplication +NEG* 2.7 Negation +NEW s 2.13 Built-in procedure +NIL 2.6 Assert non-nil pointer +NODUMP w 2.2 \s-2BEG\s0 main program, suppress pm dump +NOT 2.4 Boolean not +ODD* 2.13 Built-in function +OFF s 2.5 Offset address (i.e. for field reference) +OR 2.4 Boolean or +PAGE 3.6 Built-in procedure +POP s 2.2,1.9 Pop (arguments) off stack +PRED* 2.13 Built-in function +PUSH s 2.2,1.9 Clear space (for function result) +PUT 3.6 File procedure put +PXPBUF w 2.10 Initialize \fIpxp\fP count buffer +RANDOM 2.13 Built-in function +RANG* v 2.8 Subrange checking +READ* 3.6 Built-in procedure +REL* r 2.3 Relational test yielding Boolean result +REMOVE s 3.6 Remove a file +RESET s,w 3.6 Built-in procedure +REWRITE s,w 3.6 Built-in procedure +ROUND 2.13 Built-in function +RV* l,a 2.5 Rvalue (load) operators +SCLCK 2.13 Built-in function sysclock +SDUP 2.2 Duplicate top stack word +SEED 2.13 Built-in function +SIN 2.13 Built-in function +SQR* 2.7 Squaring +SQRT 2.13 Built-in function +STLIM 2.13 Built-in procedure for changing statement limit +STOD 2.12 Convert short integer to real +STOI 2.12 Convert short to long integer +SUB* 2.7 Subtraction +SUCC* 2.13 Built-in function +TIME 2.13 Built-in procedure +TRA a 2.2 Transfer of control (local goto) +TRACNT w,a 2.10 Count a procedure entry +TRUNC 2.13 Built-in function +UNDEF 2.13 Built-in function +UNIT* 3.6 Set active file +WRHEX* l 3.6 Hexadecimal write +WRITE* l 3.5 Built-in procedure +WRITELN 3.6 Write a new line character +WROCT* l 3.6 Octal write diff --git a/doc/px/fig2.1.raw b/doc/px/fig2.1.raw new file mode 100644 index 0000000000..9bed8f3c2d --- /dev/null +++ b/doc/px/fig2.1.raw @@ -0,0 +1,92 @@ +ABORT 2.2 Halt execution immediately for debugging +HALT 2.2 Produce control flow backtrace +BEG w,w," 2.2,1.8 Write second part of block mark, enter block +END 2.2,1.8 End block execution +CALL l,a 2.2,1.8 Procedure or function call +NODUMP w 2.2 \s-2BEG\s0 main program, suppress pm dump +PUSH s 2.2,1.9 Clear space (for function result) +POP s 2.2,1.9 Pop (arguments) off stack +TRA a 2.2 Transfer of control (local goto) +LINO s 2.2 Set line number, count statements +GOTO l,a 2.2,1.8 Non-local goto statement +IF a 2.3 Conditional transfer +REL* r 2.3 Relational test yielding Boolean result +AND 2.4 Boolean and +OR 2.4 Boolean or +NOT 2.4 Boolean not +RV* l,a 2.5 Rvalue (load) operators +CON* v 2.5 Load constant operators +AS* 2.5 Assignment operators +OFF s 2.5 Offset address (i.e. for field reference) +INX* s,w,w 2.6 Subscripting (indexing) operator +NIL 2.6 Assert non-nil pointer +LV l,w 2.6 Address of operator +IND* 2.6 Indirection operators +ADD* 2.7 Addition +SUB* 2.7 Subtraction +MUL* 2.7 Multiplication +SQR* 2.7 Squaring +DIV* 2.7 Division +MOD* 2.7 Modulus +ABS* 2.7 Absolute value +NEG* 2.7 Negation +DVD* 2.7 Floating division +RANG* v 2.8 Subrange checking +CASEOP* 2.9 Case statements +FOR* a 2.12 For statements +PXPBUF w 2.10 Initialize \fIpxp\fP count buffer +TRACNT w,a 2.10 Count a procedure entry +COUNT s 2.10 Count a statement count point +CTTOT s,w,w 2.11 Construct set +CARD s 2.11 Cardinality of set +STOI 2.12 Convert short to long integer +STOD 2.12 Convert short integer to real +ITOD 2.12 Convert integer to real +ITOS 2.12 Convert integer to short integer +GET 3.6 File procedure get +PUT 3.6 File procedure put +MESSAGE l 3.6 Write to terminal, built-in procedure +FNIL 3.6 Check file initialized, not eof, synced +BUFF 3.6 Specify buffering for file output +EOF 3.6 Boolean built-in function +EOLN 3.6 Boolean built-in function +RESET s,w 3.6 Built-in procedure +REWRITE s,w 3.6 Built-in procedure +REMOVE s 3.6 Remove a file +UNIT* 3.6 Set active file +READ* 3.6 Built-in procedure +WRITE* l 3.5 Built-in procedure +PAGE 3.6 Built-in procedure +WROCT* l 3.6 Octal write +WRHEX* l 3.6 Hexadecimal write +DEFNAME s 3.6 Attach file name for prgram statement files +LLIMIT 2.13 Built-in procedure +ARGC 2.13 Built-in function +ARGV 2.13 Built-in procedure +SCLCK 2.13 Built-in function sysclock +CLCK 2.13 Built-in function clock +DATE 2.13 Built-in procedure +TIME 2.13 Built-in procedure +SEED 2.13 Built-in function +RANDOM 2.13 Built-in function +DISPOSE 2.13 Built-in procedure +NEW s 2.13 Built-in procedure +EXPO 2.13 Built-in function yielding exponent of real +ATAN 2.13 Built-in function +EXP 2.13 Built-in function +LN 2.13 Built-in function +SIN 2.13 Built-in function +SQRT 2.13 Built-in function +CHR* 2.13 Built-in function +ODD* 2.13 Built-in function +PRED* 2.13 Built-in function +STLIM 2.13 Built-in procedure for changing statement limit +SUCC* 2.13 Built-in function +ROUND 2.13 Built-in function +TRUNC 2.13 Built-in function +UNDEF 2.13 Built-in function +SDUP 2.2 Duplicate top stack word +WRITELN 3.6 Write a new line character +ASRT 2.12 Assert true to continue +IN s,w,w 2.11 Set membership +INCT 2.11 Membership in a constructed set diff --git a/doc/px/fig2.2.n b/doc/px/fig2.2.n new file mode 100644 index 0000000000..c0b79e4023 --- /dev/null +++ b/doc/px/fig2.2.n @@ -0,0 +1,27 @@ +.TS +center, allbox; +cw(15) +c +l +l. +\s-2CASEOP\s0 +No. of cases +T{ +.sp +.nf +.ce 3 +Case +transfer +table +.fi +T} +T{ +.sp +.nf +.ce 2 +Array of case +label values +.fi +.sp +T} +.TE diff --git a/doc/px/makefile b/doc/px/makefile new file mode 100755 index 0000000000..47f4c208e6 --- /dev/null +++ b/doc/px/makefile @@ -0,0 +1,4 @@ +pxin: fig2.1.n + soelim pxin?.n | tbl | /usr/new/vtroff -o-1,22- +fig2.1.n: fig2.1.raw + sort fig2.1.raw >fig2.1.n diff --git a/doc/px/pxin0.n b/doc/px/pxin0.n new file mode 100644 index 0000000000..cc8b44a7db --- /dev/null +++ b/doc/px/pxin0.n @@ -0,0 +1,98 @@ +.if !\n(xx .so tmac.p +.RP +.TL +Berkeley Pascal +PX Implementation Notes +.br +Version 1.1 \- April, 1979 +.AU +William N. Joy\*(dg +.AI +Computer Science Division +Department of Electrical Engineering and Computer Science +University of California, Berkeley +Berkeley, California 94720 +.AB +.PP +Berkeley Pascal +is designed for interactive instructional use and runs on the +\s-2PDP\s0 11 computer family. +..A version of \fIpx\fR for the \s-2VAX\s0 11/780 is nearly complete. +The interpreter +.I px +executes the Pascal binaries generated by the Pascal translator +.I pi . +.PP +The +.I +PX Implementation Notes +.R +describe the overall organization of +.I px , +detail the various operations of the interpreter, +with a special section describing the file input/output structure. +Conclusions are given as to the viability of an interpreter +based approach to language implementation for an instructional environment. +.AE +.if n 'ND +.SH +Introduction +.PP +This +.I +PX Implementation Notes +.R +consists of four major parts. +The first part outlines the overall organization of +.I px . +Section 2 describes the operations (instructions) of the interpreter +while section 3 focuses on input/output related activity. +A final section gives conclusions about the viability of an interpreter +based approach to language implementation for instruction. +.SH +Related Berkeley Pascal documents +.PP +The +.I "PXP Implementation Notes" +give details of the internals of the execution profiler +.I pxp; +parts of the interpreter related to +.I pxp +are discussed in section 2.10. +A paper describing the syntactic error recovery mechanism used in +.I pi +will be presented at the ACM Conference on Compiler Construction +in Boulder Colorado in August, 1979. +.SH +Acknowledgements +.PP +This version of +.I px +is heavily based on an earlier +.I px +which was designed and implemented by Ken Thompson, +the author of the first +.UP +system. +Without his work, this +.UP +system would never have existed. +Charles Haley, who collaborated with the author on this project, wrote +some of the more difficult input/output routines in this version of +.I px, +and helped to debug it all. +His assistance in teaching this author about +.UX +and Pascal is gratefully acknowledged and appreciated. +The author would also like to thank his faculty advisor Susan L. Graham +for her encouragement, +her helpful comments and suggestions +relating to +.UP +and her excellent editorial assistance. +.FS +\*(dg The financial support of the National Science Foundation under grants +MCS74-07644-A03 and MCS78-07291 +and of an \s-2IBM\s0 Graduate Fellowship are gratefully acknowledged. +.FE +.bp diff --git a/doc/px/pxin1.n b/doc/px/pxin1.n new file mode 100644 index 0000000000..efb2e34965 --- /dev/null +++ b/doc/px/pxin1.n @@ -0,0 +1,559 @@ +.if !\n(xx .so tmac.p +.nr H1 0 +.NH +Organization +.PP +Most of +.I px +is written in the +\s-2PDP\s0-11 +assembly language, using the +.UX +assembler +.I as. +Portions of +.I px +are also written in the +.UX +systems programming language C. +.I Px +consists of a main procedure which reads in the interpreter code, +a main interpreter loop which transfers successively to various +code segments implementing the abstract machine operations +and built-in procedures and functions, +the code segments themselves, and +a number of routines which support the implementation of the +Pascal input-output environment. +.PP +The interpreter runs at a fraction of the speed of equivalent +compiled C code, with this fraction varying from 1/5 to 1/15. +The fact that the interpreter implements 32 bit integer arithmetic +on a 16 bit machine notably degrades its speed. +In a code generated Pascal for a +\s-2PDP\s0-11, 32 bit integers would be undesirable. +.PP +The interpreter occupies 14.6K bytes of instruction space, which is shared +between all instances of the interpreter, and 5K bytes of data space +of which there is a copy for each interpreter execution. +.PP +The interpreter occupies 14.6K bytes of instruction space, shared among +all processes executing Pascal, and has 4.6K bytes of data space (constants, +error messages, etc.) a copy of which is allocated to each executing process. +.NH 2 +Format of the object file +.PP +.I Px +normally interprets the code left in an object file by a run of the +Pascal translator +.I pi. +The file where the translator puts the object originally, and the most +commonly interpreted file, is called +.I obj. +We will first describe the way the object file was prepared in version 1.0 +of the interpreter. +.PP +In version 1.0 of the interpreter, the +.I obj +file has an extremely simple format. +The first word of the file has the octal value 404, +a ``magic'' number. +This number, +like the numbers 407, 410, and 411 which signify executable files to the +system, +can be recognized by a modified shell (command interpreter) +which can then fork instances of +.I px +to interpret the file. +In this way, Pascal objects can be referred to at the shell level by typing +their names. +The modified shell can open each file which is executable +but does not have a magic number recognized by the operating system. +If the first word of such a file is 404, then the shell recognizes +the file as a Pascal object, and creates an instance of the Pascal +interpreter with the specified file as its first argument. +This, importantly, allows all processes executing Pascal objects to share +the same interpreter, and allows the Pascal object files to be small +as they do not contain a copy of the interpreter. +.PP +With version 1.1 of the Pascal system an option exists to have the translator +prepare true executable files. In order that all persons using +.I px +share a common text image, this executable file is not an interpreter, +but rather a small process which coordinates with the iinterpreter to start +execution. +The way in which this happens is somewhat complicated. +When one of these object files is created, the interpreter code is placed +at the end of a special ``header'' file and the size of the initialized +data area of this header file is expanded to include this code. +When the process executes, the interpreter code is thus available at a +easily determined address in its data space. +When executed, the object process creates an +.I pipe , +creates another process by doing a +.I fork , +and arranges that the resulting parent process becomes an instance of +.I px . +The child process then writes, through the pipe whicch it has to the parent, +interpreter process, the interpreter code. +When this process is complete, the child exits. +.PP +The real advantage of this approach is that it does not require modifications +to the shell, and that the resultant objects are ``true objects'' not +requiring special treatment. +A simpler mechanism would be to determine the name of the file which was +executed and pass this to the interpreter. +However it is not possible to determine this name in all cases.\u\*(dg\d +.FS +\*(dgFor instance, if the +.I pxref +program is placed in the directory +`/usr/bin' +then when the user types +``pxref prog1.p'' +the first argument to the program, nominally the programs name, is +``pxref.'' +While it would be possible to search in the standard place, +i.e. the current directory, and the system directories +`/bin' +and +`/usr/bin' +for a corresponding object file, +this would be expensive and not guaranteed to succeed. +Several shells exist which allow other directories to be searched +for commands, and there is, +in general, +no way to determine what these directories are. +.FE +.PP +After the first word containing the value 404, +the remainder of the +.I obj +file contains the object code. +.NH 2 +General features of object code +.PP +Pascal object code is relocatable as all addressing references for +control transfers within the code are relative. +The code consists of instructions interspersed with inline data. +All instructions have a length which is an even number of bytes, +that is, an integral number of words. +No variables are kept in the object code area. +.PP +The first byte of a Pascal interpreter instruction contains an operation +code. +This allows a total of 256 major operation codes, and 219 of these are +in use in the current +.I px. +The second byte of each interpreter instruction is called the +``sub-operation code'', +or more commonly the +.I subop. +It contains a small integer which may, for example, be used as a +block-structure level for the associated operation. +If the instruction can take a fullword constant, +this constant is often packed into the subop +if it fits into 8 bits and is not zero. +A subop value of 0 indicates that the constant wouldn't +fit and therefore follows in the next word. +This is a space optimization, the value of 0 for flagging +the longer case being convenient because it is easy to test. +.PP +Other instruction formats are used. +The branching +instructions take an offset in the following word, +operators which load constants onto the stack +take arbitrarily long inline constant values, +and a large number of operations deal exclusively with data on the +interpreter stack, requiring no inline data. +.NH 2 +Stack structure of the interpreter +.PP +The interpreter emulates a stack-structured Pascal machine. +The ``load'' instructions put values onto the stack, where all +arithmetic operations take place. +The ``store'' instructions take values off the stack +and place them in an address which is also contained on the stack. +The only way to move data or to compute in the machine is with the stack. +.PP +To make the interpreter operations more powerful +and to thereby increase the interpreter speed, +the arithmetic operations in the interpreter are ``typed''. +That is, length conversion of arithmetic values occurs when they are +used in an operation. +This eliminates the need for interpreter cycles for length conversion +and the associated overhead. +For example, when adding an integer which fits in one byte to one which +requires four bytes to store, no ``conversion'' operators are required. +The one byte integer is loaded onto the stack, followed by the four +byte integer, and then an adding operator is used which has, implicit +in its definition, the sizes of the arguments. +.NH 2 +Data types in the interpreter +.PP +The interpreter deals with several different fundamental data types. +In the memory of the machine, 1, 2, and 4 byte integers are supported, +with only 2 and 4 byte integers being present on the stack. +The interpreter always converts to 4 byte integers when there is a possibility +of overflowing the shorter formats. +This corresponds to the Pascal language definition of overflow in +arithmetic operations which requires that the result be correct +if all partial values lie within the bounds of the base integer type: +4 byte integer values. +.PP +Character constants are treated similarly to 1 byte integers for +most purposes, as are Boolean values. +All enumerated types are, in fact, treated as integer values of +an appropriate length, usually 1 byte. +The interpreter also has real numbers, occupying 8 bytes of storage, +and sets and strings of varying length. +The appropriate operations are included for each data type, such as +set union and intersection and an operation to write a string +which is on top of the stack to a file. +.PP +No special +.B packed +data formats are supported by the interpreter. +The smallest unit of storage occupied by any variable is one byte. +The built-ins +.I pack +and +.I unpack +thus degenerate to simple memory to memory transfers with +no special processing. +.NH 2 +Runtime environment +.PP +The interpreter runtime environment uses a stack data area and a heap +data area, which are kept at opposite ends of memory +and grow towards each other. +All global variables and variables local to procedures and functions +are kept in the stack area. +Dynamically allocated variables and buffers for input/output are +allocated in the heap. +.PP +The addressing of block structured variables is accomplished through +a fixed display which contains, for each +statically active block, the address of its stack frame.\*(dg +.FS +\*(dg Here ``block'' is being used to mean any +.I procedure , +.I function +or the main program. +.FE +This display is referenced by instructions which load and store +variables and maintained by the operations for +block entry and exit, and for non-local +.B goto +statements. +.NH 2 +Dp, lc, lp +.PP +Three ``global'' variables in the interpreter, in addition to the +``display'', are the +.I dp, +.I lc, +and the +.I lp. +The +.I dp +is a pointer to the display entry for the current block; +the +.I lc +is the abstract machine location counter; +and the +.I lp +is a register which holds the address of the main interpreter +loop so that returning to the loop to fetch the next instruction is +a fast operation. +.NH 2 +The stack frame structure +.PP +Each active block +has a stack frame consisting of three parts: +a block mark, local variables, and temporary storage for partially +evaluated expressions. +The stack in the interpreter grows from the high addresses in memory +to the low addresses, +so that those parts of the stack frame which are ``on the top'' +of the stack have the most negative offsets from the display +entry for the block. +The major parts of the stack frame are represented in Figure 1.1. +.so fig1.1.n +Note that the local variables of each block +have negative offsets from the corresponding display entry, +the ``first'' local variable having offset `\-2'. +.NH 2 +The block mark +.PP +The block mark contains the saved information necessary +to restore the environment when the current block exits. +It consists of two parts. +The first and top-most part is saved by the +.SM CALL +instruction in the interpreter. +This information is not present for the main program +as it is never ``called''. +The second part of the block mark is created by the +.SM BEG +begin block operator which also allocates and clears the +local variable storage. +The format of these blocks is represented in Figure 1.2. +.sp +.so fig1.2.n +.PP +The data saved by the +.SM CALL +operator includes the line number +.I lino +of the point of call, +which is printed if the program execution terminates abnormally; +the location counter +.I lc +giving the return address; +and the current display entry address +.I dp +at the time of call. +.PP +The +.SM BEG +begin operator saves the previous display contents at the level +of this block, so that the display can be restored on block exit. +A pointer to 10 bytes of information giving the first eight characters of the +name of this block and its beginning line number is also saved. +This information is stored in the intepretor object code in-line after the +.SM BEG +operator. +It is used in printing a post-mortem backtrace. +The saved file name and buffer reference are necessary because of +the input/output structure +(this is discussed in detail in +sections 3.3 and 3.4). +The top of stack reference gives the value the stack pointer should +have when there are no expression temporaries on the stack. +It is used for a consistency check in the +.SM LINO +line number operators in the interpreter, which occurs before +each statement executed. +This helps to catch bugs in the interpreter, which often manifest +themselves by leaving the stack non-empty between statements. +.PP +Note that there is no explicit static link here. +Thus to set up the display correctly after a non-local +.B goto +statement one must ``unwind'' +through all the block marks on the stack to rebuild the display. +.NH 2 +Arguments and return values +.PP +A function returns its value into a space reserved by the calling +block. +Arguments to a +.B function +are placed on top of this return area. +For both +.B procedure +and +.B function +calls, arguments are placed at the end of the expression evaluation area +of the caller. +When a +.B function +completes, expression evaluation can continue +after popping the arguments to the +.B function +off the stack, +exactly as if the function value had been ``loaded''. +The arguments to a +.B procedure +are also popped off the stack by the caller +after its execution terminates. +.KS +.PP +As a simple example consider the following stack structure +for a call to a function +.I f, +of the form ``f(a)''. +.so fig1.3.n +.KE +.PP +If we suppose that +.I f +returns a +.I real +and that +.I a +is an integer, +the calling sequence for this function would be: +.DS +.TS +lp-2w(8) l. +PUSH -8 +RV4 \fIa\fR +CALL \fIf\fR +POP 4 +.TE +.DE +.ZP +Here we use the operator +.SM PUSH +to clear space for the return value, +load +.I a +on the stack with an ``rvalue'' operator, +call the function, +pop off the argument +.I a , +and can then complete evaluation of the containing expression. +The operations used here will be explained in section 2. +.PP +If the function +.I f +were given by +.LS + 10 \*bfunction\fR f(i: integer): real; + 11 \*bbegin\fR + 12 f := i + 13 \*bend\fR; +.LE +then +.I f +would have code sequence: +.DS +.TS +lp-2w(8) l. +BEG 0 + "f" + 11 +LV \fIl\fR,20 +RV4 \fIl\fR,16 +AS48 +END +.TE +.DE +.ZP +Here the +.SM BEG +operator takes 12 bytes of inline data. +The first word indicates the amount of local variable storage, here none. +The succeeding two lines give the name of the block and the line number +of the +.B begin +for error traceback. +The +.SM BEG +operator places a pointer to the name and line number in the block mark. +.PP +The body of the +.B function +here involved taking an address of the +.B function +result variable +.I f +using the address of operator +.SM LV . +.I a . +The next operation in the interpretation of this function is the loading +of the value of +.I i . +.I I +is at the level of the +.B function +.I f , +here symbolically +.I l, +and the first variable in the local variable area. +.PP +The +.B function +completes by assigning the 4 byte integer on the stack to the 8 byte +return location, hence the +.SM AS48 +assignment operator, and then uses the +.SM END +operator to exit the current block. +.NH 2 +The main interpreter loop +.PP +We can now describe the main interpreter loop. +It is actually quite short: +.DS +loop: + \fBmovb\fR (lc)+,r0 + \fBadd\fR r0,r0 + \fBmovb\fR (lc)+,r3 + \fBjmp\fR *optab(r0) +.DE +.ZP +First the main operation code is extracted from the first byte of +the instruction. +The code will be a small integer in the range -128 to 127. +It is then doubled to make a word index into the operation table. +Note that the sub-operation code is placed in register 3, and is thus available +for use by the individual operation sequences. +The hardware also leaves the condition codes set based on the value of this +subop. +The code will be discussed in section 2.1. +.PP +The label +.I optab +is in the middle of a branch table which has one operation address +per word. +The table is generated automatically from an abstract machine +instruction list. +The address of the instruction at +.I loop +is always contained in the register variable +.I lp +so that a return to the main interpreter loop both is quick and occupies +little space. +The return is thus a ``jmp\ (lp)'' instruction, +defined for mnemonic value as the operator ``return'' in the intepreter, i.e. +.DS +return = 115 +.DE +so that one can write the mnemonic ``return'' at the end of an interpreter +code sequence. +.NH 2 +Errors +.PP +Errors during interpretation cause a subroutine call to an error routine +in a conventional fashion. An earlier version of the interpreter +more compactly represented the raising of these conditions by using emulator +traps (\s-2EMT\s0s), a form of system call otherwise unused by \s-2UNIX\s0. +Errors were assigned small integer numbers and then referred to +symbolically in the interpreter. +The \s-2UNIX\s0 assember, +.I as , +provides a mechanism for defining the opcode ``error'' to be an ``emt,'' i.e.: +.DS +error = 104000 ^ sys +.DE +Thus there were many lines like +.DS +.TS +lw(8) lp-2. +\fBerror\fR ESTKOVFLO +.TE +.DE +in the interpreter. +These cause a process fault, +which is trapped by the system and passed to the label +.I onemt +in the interpreter which fetches the error code byte from the +.SM EMT +instruction and calls the procedure +.I error +with this argument. +.I Error +processes the error condition, +printing an appropriate error message and, usually, a backtrace. +.PP +In order that the interpreter run on a standard \s-2UNIX\s0 without +using non-standard system calls to fetch the \s-2EMT\s0 code +when running in separated instruction and data spaces, +the current version of the interpreter places the error code in a global +variable, before doing an +.SM EMT . +Thus the +.SM EMT +is used to compactly transfer control, but not for argument transmission. diff --git a/doc/px/pxin2.n b/doc/px/pxin2.n new file mode 100644 index 0000000000..eb90912304 --- /dev/null +++ b/doc/px/pxin2.n @@ -0,0 +1,905 @@ +.de mD +.ta 8n 16n 24n +.. +.if !\n(xx .so tmac.p +.nr H1 1 +.if n .ND +.NH +Operations +.NH 2 +Naming conventions and operation summary +.PP +As discussed in section 1.10, +the main interpreter loop decodes the first word of the interpreter +instruction, +using the first byte as an operation code, +and places the second byte, +the ``subop'', +in register 3. +The subop may be used to index the display, +as a small constant, +or to indicate one of several relational operators. +In the cases where a constant is needed, but it +is not small enough to fit in the byte sub-operator, +a zero is placed there and the constant follows in the next word. +Zero is easily tested for, +as the instruction which places the +subop in r3 sets the condition code flags, +and this condition code is still available after the transfer +to an operation code sequence. +A construction like +.DS +.mD +_OPER: + \fBbne\fR 1f + \fBmov\fR (lc)+,r3 +1: + ... +.DE +.IP +is all that is needed to effect this packing of data. +This technique saves a great deal of space in the Pascal +.I obj +object code. +.PP +Table 2.1 gives the codes used in the instruction descriptions +to indicate the kind of inline data expected by each instruction. +.KF +.TS +box center; +c s +l | l +ci | aw(3.25i). +Table 2.1 \- Inline data type codes +_ +Code Description += +a T{ +.fi +An address offset is given in the word +following the instruction. +T} +_ +l T{ +An index into the display, ready as an offset or a guaranteeably small integer, +is given in the sub-operation code. +T} +_ +r T{ +A relational operator encoded as described +in section 2.3 is given in the subop. +T} +_ +s T{ +A small integer is +placed in the subop, or in the next word +if it is zero or too large. +T} +_ +v T{ +Variable length inline data. +T} +_ +w T{ +A word value in the following word. +T} +_ +" T{ +An inline constant string. +T} +.TE +.KE +.PP +Before giving a list of the machine opcodes, +it is useful to note the naming conventions in the interpreter for typed +operations. +Machine instructions which have numeric operands use a simple and uniform +naming convention in which a suffix on the root operation name indicates +the type of operands expected. +These are given in Table 2.2. +Here the expression ``a above b'' means that `a' is on top of the +stack with `b' below it. +Short integers are 2 byte integers, +and long integers are 4 byte integers. +.TS +box center; +c s s +c s s +l l l +c ap-2 a. +Table 2.2 \- Operator Suffices +.sp +Unary operator suffices +.sp .1i +Suffix Example Argument type +2 NEG2 Short integer +4 SQR4 Long integer +8 ABS8 Real +.sp +.T& +c s s +l l l +c ap-2 a. +Binary operator suffices +.sp .1i +Suffix Example Argument type +2 ADD2 Two short integers +24 MUL24 Short above long integer +42 REL42 Long above short integer +4 DIV4 Two long integers +28 DVD28 Short integer above real +48 REL48 Long integer above real +82 SUB82 Real above short integer +84 MUL84 Real above long integer +.sp +.T& +c s s +l l l +c ap-2 a. +Other Suffices +.sp .1i +Suffix Example Argument types +T ADDT Sets +G RELG Strings +.TE +.PP +We now give the list of machine operations with a reference +to the appropriate sections and a short description of each. +The character `*' at the end of a name indicates that all +operations with the root prefix before the `*' are summarized by +the one entry. +.br +.ne 15 +.TS H +box center; +c s s +lw(14) | lw(12) | lw(40) +lp-2 | a | l. +Table 2.3 \- Machine operations +_ +Mnemonic Reference Description += +.TH +.so fig2.1.n +.TE +.bp +.NH 2 +Basic control operations +.LP +.SH +ABORT +.IP +This operator is used to halt execution immediately with an IOT process +fault. +It is used only for debugging +.I px +and is never generated by the translator +.I pi. +.SH +HALT +.IP +Corresponds to the Pascal procedure +.I halt ; +causes execution to terminate with a post-mortem backtrace as if a run-time +error had occurred. +.SH +BEG w1,w2," +.IP +Causes the second part of the block mark to be created, and +.I w1 +bytes of local variable space to be allocated and cleared to zero. +Stack overflow is detected here. +.I W2 +is the first line of the body of this section for error traceback, +and he inline string (length 8) the character representation of its name. +.SH +NODUMP w +.IP +Equivalent to +.SM BEG , +and used to begin the main program when the ``p'' +option is disabled so that the post-mortem backtrace will be inhibited. +.SH +END +.IP +Complementary to the operators +.SM CALL +and +.SM BEG , +exits the current block, calling the procedure +.I blkexit +to flush buffers for and release any local files. +Restores the environment of the caller from the block mark. +If this is the end for the main program, all files are +.I flushed, +the profile data file is written if necessary, and +the routine +.I psexit +which prints the statistics if desired (and does not return) is called. +.SH +CALL l,a +.IP +Saves the current line number, return address, and active display entry pointer +.I dp +in the first part of the block mark, then transfers to the entry point +given by the relative address +.I a , +which is the beginning of a +.B procedure +or +.B function +at level +.I l. +.SH +PUSH s +.IP +Clears +.I s +bytes on the stack for, e.g., the return value of a +.B function +just before calling the function. +.SH +POP s +.IP +Pop +.I s +bytes off the stack. +Used, e.g., after a +.B function +or +.B procedure +returns to remove the arguments from the stack. +.SH +TRA a +.IP +Transfer control to relative address +.I a +as a local +.B goto +or part of a structured statement. +.SH +LINO s +.IP +Set current line number to +.I s. +For consistency, check that the expression stack is empty +as it should be (as this is the start of a statement.) +This consistency check will fail only if there is a bug in the +interpreter or the interpreter code has somehow been damaged. +Increment the statement count and if it exceeds the statement limit, +generate a fault. +.SH +GOTO l,a +.IP +Transfer conrol to address +.I a +which is in the block at level +.I l +of the display. +This is a non-local +.B goto. +Causes each block to be exited as if with +.SM END , +flushing and freeing files with +.I blkexit, +until the current display entry is at level +.I l. +.SH +SDUP +.IP +Duplicate the one word integer on the top of +the stack. +This is used mostly for constructing sets. +See section 2.11. +.NH 2 +If and relational operators +.SH +IF a +.IP +The interpreter conditional transfers all take place using this operator +which examines the Boolean value on the top of the stack. +If the value is +.I true , +the subsequent code is executed, +otherwise control transfers to the specified address. +.SH +REL* r +.IP +These take two arguments on the stack, +and the sub-operation code indicates which relational operation is to +be performed, coded as follows with `a' above `b' on the stack: +.DS +.mD +.TS +lb lb +c a. +Code Operation +_ +0 a = b +2 a <> b +4 a < b +6 a > b +8 a <= b +10 a >= b +.TE +.DE +.IP +Each operation does a number of tests to set the condition code +appropriately and then does an indexed branch based on the +sub-operation code to a test of the condition here specified, +pushing a Boolean value on the stack. +.IP +Consider the statement fragment: +.DS +.mD +\*bif\fR a = b \*bthen\fR +.DE +.IP +If +.I a +and +.I b +are integers this generates the following code: +.DS +.TS +lp-2w(8) l. +RV4 \fIa\fR +RV4 \fIb\fR +REL4 \&= +IF \fIElse part offset\fR +.sp +.T& +c s. +\fI\&... Then part code ...\fR +.TE +.DE +.NH 2 +Boolean operators +.IP +The Boolean operators +.SM AND , +.SM OR , +and +.SM NOT +manipulate values on the top of the stack. +All Boolean values are kept in single bytes in memory, +or in single words on the stack. +Zero represents a Boolean \fIfalse\fP, and one a Boolean \fItrue\fP. +.NH 2 +Rvalue, constant, and assignment operators +.SH +RV* l,a +.IP +The rvalue operators load values on the stack. +They take a block number as a subop and load the appropriate +number of bytes from that block at the offset specified +in the following word onto the stack. As an example, consider +.SM RV4 : +.DS +.mD +_RV4: + \fBmov\fR _display(r3),r0 + \fBadd\fR (lc)+,r0 + \fBsub\fR $4,sp + \fBmov\fR sp,r2 + \fBmov\fR (r0)+,(r2)+ + \fBmov\fR (r0)+,(r2)+ + \fBreturn\fR +.DE +.IP +Here the interpreter first generates the source address in r0 by adding the +display entry to the offset in the next instruction word. +It then reserves a long integer space on the stack (4 bytes) +and moves the data from the source onto the stack. +The pseudo-operation ``return'' +takes the interpreter back to the main interpreter loop. +Note that the sub-operation code is already in +r3 and multiplied by 2 to be immediately usable as a word index +into the display. +.SH +CON* r +.IP +The constant operators load a value onto the stack from inline code. +Small integer values are condensed and loaded by the +.SM CON1 +operator, which is given by +.DS +.mD +_CON1: + \fBmov\fR r3,-(sp) + \fBreturn\fR +.DE +.IP +Here note that little work was required as the required constant +had already been placed in register 3. +For longer constants, more work is required; +the operator +.SM CON +takes a length specification in the subop and can be used to load +strings and other variable length data onto the stack. +.SH +AS* +.IP +The assignment operators are similar to arithmetic and relational operators +in that they take two operands, both in the stack, +but the lengths given for them indicate +first the length of the value on the stack and then the length +of the target in memory. +The target address in memory is under the value to be stored. +Thus the statement +.DS +i := 1 +.DE +.IP +where +.I i +is a full-length, 4 byte, integer, +will generate the code sequence +.DS +.TS +lp-2w(8) l. +LV \fIi\fP +CON1 1 +AS24 +.TE +.DE +.IP +Here +.SM LV +will load the address of +.I i, +which is actually given as a block number in the subop and an +offest in the following word, +onto the stack, occupying a single word. +.SM CON1 , +which is a single word instruction, +then loads the constant 1, +which is in its subop, +onto the stack. +Since there are not one byte constants on the stack, +this becomes a 2 byte, single word integer. +The interpreter then assigns a length 2 integer to a length 4 integer using +.SM AS24 \&. +The code sequence for +.SM AS24 +is given by: +.DS +.mD +_AS24: + \fBmov\fR (sp)+,r1 + \fBsxt\fR r0 + \fBmov\fR (sp)+,r2 + \fBmov\fR r0,(r2)+ + \fBmov\fR r1,(r2) + \fBreturn\fR +.DE +.IP +Thus the interpreter gets the single word off the stack, +extends it to be a 4 byte integer in two registers, +gets the target address off the stack, +and finally stores the parts of the value in the target. +This is a typical use of the constant and assignment operators. +.NH 2 +Addressing operations +.SH +LV l,w +.IP +The most common operation performed by the interpreter +is the ``lvalue'' or ``address of'' operation. +It is given by: +.DS +.mD +_LV: + \fBmov\fR _display(r3),r0 + \fBadd\fR (lc)+,r0 + \fBmov\fR r0,-(sp) + \fBreturn +.DE +.IP +It calculates an address in the block specified in the subop +by adding the associated display entry to the +offset which appears in the following word. +.SH +OFF s +.IP +The offset operator is used in field names. +Thus to get the address of +.LS +p^.f1 +.LE +.IP +.I pi +would generate the sequence +.DS +.mD +.TS +lp-2w(8) l. +RV \fIp\fP +OFF \fIf1\fP +.TE +.DE +.IP +where the +.SM RV +loads the value of +.I p, +given its block in the subop and offset in the following word, +and the interpreter then adds the offset of the field +.I f1 +in its record to get the correct address. +.SM OFF +takes its argument in the subop if it is small enough. +.SH +NIL +.IP +The example above is incomplete, lacking a check for a +.B nil +pointer. +The code generated would, in fact, be +.DS +.TS +lp-2w(8) l. +RV \fIp\fP +NIL +OFF \fIf1\fP +.TE +.DE +.IP +where the +.SM NIL +operation checks for a +.I nil +pointer and generates the appropriate runtime error if it is. +.SH +INX* s,w,w +.IP +The operators +.SM INX2 +and +.SM INX4 +perform subscripting. +For example, the statement +.DS +a[i] := 2.0 +.DE +.IP +with +.I i +a short integer, such as a subrange ``1..1000'', +and +.I a +an +``array [1..1000] of real'' +would generate +.DS +.TS +lp-2w(8) l. +LV \fIa\fP +RV2 \fIi\fP +INX2 8,1,999 +CON8 2.0 +AS8 +.TE +.DE +.IP +Here the +.SM LV +operation takes the address of +.I a +and places it on the stack. +The value of +.I i +is then placed on top of this on the stack. +We then perform an indexing of the array address by the +length 2 index (a length 4 index would use +.SM INX4 ) +where the individual elements have a size of 8 bytes. +The code for +.SM INX2 +is: +.DS +.mD +_INX2: + \fBtst\fR r3 + \fBbne\fR 1f + \fBmov\fR (lc)+,r3 +1: + \fBmov\fR (sp)+,r1 + \fBsub\fR (lc)+,r1 + \fBbmi\fR 1f + \fBcmp\fR r1,(lc)+ + \fBbgt\fR 1f + \fBmul\fR r3,r1 + \fBadd\fR r1,(sp) + \fBreturn +1: + \fBerror\fR ESUBSCR +.DE +.IP +Here the index operation subtracts the constant value 1 from the +supplied subscript, +this being the low bound of the range of permissible subscripts. +If the result is negative, +or if the normalized subscript then exceeds 999, which +is the maximum permissible subscript if the first is numbered 0, +the interpreter generates a subscript error. +Otherwise, the interpreter multiplies the offset by 8 and adds it to the address +which is already on the stack for +.I a , +to address ``a[i]''. +Multi-dimension subscripts are translated as a sequence of single subscriptings. +.SH +IND* +.IP +For indirect references through +.B var +parameters and pointers, +the interpreter has a set of indirection operators which convert a pointer +on the stack into a value on the stack from that address. +different +.SM IND +operators are necessary because of the possibility of different +length operands. +.NH 2 +Arithmetic operators +.IP +The interpreter has a large number of arithmetic operators. +All operators produce results long enough to prevent overflow +unless the bounds of the base type are exceeded. +No overflow checking is done on arithmetic, but divide by zero +and mod by zero are detected. +.NH 2 +Range checking +.IP +The interpreter has a number of range checking operators. +The important distinction among these operators is between values whose +legal range begins at 0 and those which do not begin at 0, i.e. with +a subrange variable whose values range from 45 to 70. +For those which begin at 0, a simpler ``logical'' comparison against +the upper bound suffices. +For others, both the low and upper bounds must be checked independently, +requiring two comparisons. +.NH 2 +Case operators +.IP +The interpreter includes three operators for +.B case +statements which are used depending on the width of the +.B case +label type. +For each width, the structure of the case data is the same, and +is represented in the following figure. +.sp 1 +.KF +.so fig2.2.n +.KE +.sp 1 +.IP +The +.SM CASEOP +case statement operators do a sequential search through the +case label values. +If they find the label value, they take the corresponding entry +from the transfer table and cause the interpreter to branch to the +indicated statement. +If the specified label is not found, an error results. +.IP +The +.SM CASE +operators take the number of cases as a subop +if possible. +Three different operators are needed to handle single byte, +word, and double word case transfer table values. +For example, the +.SM CASEOP1 +operator has the following code sequence: +.DS +.mD +_CASEOP1: + \fBbne\fR 1f + \fBmov\fR (lc)+,r3 +1: + \fBmov\fR lc,r0 + \fBadd\fR r3,r0 + \fBadd\fR r3,r0 + \fBmov\fR r3,r2 + \fBtst\fR (sp)+ +1: + \fBcmpb\fR (r0)+,-2(sp) + \fBbeq\fR 5f + \fBsob\fR r3,1b + \fBerror\fR ECASE +5: + \fBsub\fR r3,r2 + \fBadd\fR r2,r2 + \fBadd\fR lc,r2 + \fBadd\fR (r2),lc + \fBreturn +.DE +.IP +Here the interpreter first computes the address of the beginning +of the case label value area by adding twice the number of case label +values to the address of the transfer table, since the transfer +table entries are full word, 2 byte, address offsets. +It then searches through the label values, and generates an ECASE +error if the label is not found. +If the label is found, we calculate the index of the entry in +the transfer table which is desired and then add that offset +to the interpreter location counter. +.NH 2 +Operations supporting pxp +.IP +For the purpose of execution profiling the following operations +are defined. +.SH +PXPBUF w +.IP +Causes the interpreter to allocate a count buffer +with +.I w +counters, each of which is a 4 byte integer, +and to clear the counters to 0. +The count buffer is placed within an image of the +.I pmon.out +file as described in the +.I "PXP Implementation Notes." +The contents of this buffer will be written to the file +.I pmon.out +when the program terminates. +.SH +COUNT s +.IP +Increments the counter specified by +.I s. +.SH +TRACNT w,a +.IP +Used at the entry point to procedures and functions, +combining a transfer to the entry point of the block with +an incrementing of its entry count. +.NH 2 +Set operations +.IP +The set operations +set union +.SM ADDT, +intersection +.SM MULT, +and the set relationals +.SM RELT +are straightforward. +The following operations are more interesting. +.SH +CARD s +.IP +Takes the cardinality of a set of size +.I s +bytes on top of the stack, leaving a 2 byte integer count. +.SM CARD +uses a table of 4-bit population counts to count set bits +in each 4-bit nibble of each byte in the set. +.SH +CTTOT s,w,w +.IP +Constructs a set. +This operation requires a non-trivial amount of work, +checking bounds and setting individual bits or ranges of bits. +This operation sequence is very slow, +and motivates the presence of the operator +.SM INCT +below. +The arguments to +.SM CTTOT +include the number of elements +.I s +in the constructed set, +the lower and upper bounds of the set, +the two +.I w +values, +and a pair of values on the stack for each range in the set, single +elements in constructed sets being duplicated with +.SM SDUP +to form degenerate ranges. +.SH +IN s,w,w +.IP +The operator +.B in +for sets. +The value +.I s +specifies the size of the set, +the two +.I w +values the lower and upper bounds of the set. +The value on the stack is checked to be in the set on the stack, +and a Boolean value of +.I true +or +.I false +replaces the operands. +.SH +INCT +.IP +The operator +.B in +on a constructed set without constructing it. +The left operand of +.B in +is on top of the stack followed by the number of pairs in the +constructed set, +and then the pairs themselves, all as single word integers. +Pairs designate runs of values and single values are represented by +a degenerate pair with both value equal. +A typical situation for this operator to be generated is +.LS +\fBif\fR ch \fBin\fR ['+', '-', '*', '/'] +.LE +.IP +or +.LS +\fBif\fR ch \fBin\fR ['a'..'z', '$', '_'] +.LE +.IP +These situations are very common in Pascal, and +.SM INCT +makes them run much faster in the interpreter, +as if they were written as an efficient series of +.B if +statements. +.NH 2 +Miscellaneous +.IP +Other miscellaneous operators which are present in the interpreter +are +.SM ASRT +which causes termination if the Boolean value on the stack is not +.I true, +and +.SM STOI , +.SM STOD , +.SM ITOD , +and +.SM ITOS +which convert between different length arithmetic operands for +use in aligning the arguments in +.B procedure +and +.B function +calls, and with some untyped built-ins, such as +.SM SIN +and +.SM COS \&. +.IP +Finally, if the program is run with the run-time testing disabled, there +are special operators for +.B for +statements +and special indexing operators for arrays +which have individual element size which is a power of 2. +The code can run significantly faster using these operators. +.NH 2 +Functions and procedures +.IP +.I Px +has a large number of built-in procedures and functions. +The mathematical functions are taken from the standard +system library. +The linear congruential random number generator is described in +the +.I "Berkeley Pascal User Manual" +.IP +The procedures +.I linelimit +and +.I dispose +are included here but currently ignored. +One surprise is that the built-ins +.I pack +and +.I unpack +are here and quite complex, functioning as a memory to memory +move with a number of semantic checks. +They do no ``unpacking'' or ``packing'' in the true sense, however, +as the interpreter supports no packed data types. diff --git a/doc/px/pxin3.n b/doc/px/pxin3.n new file mode 100644 index 0000000000..87ada68620 --- /dev/null +++ b/doc/px/pxin3.n @@ -0,0 +1,303 @@ +.if !\n(xx .so tmac.p +.nr H1 2 +.if n .ND +.NH +Input/output +.NH 2 +The files structure +.PP +Each file in the Pascal environment is represented by a pointer +to a +.I files +structure in the heap. +At the location addressed by the pointer is the element +in the file's window variable. +Behind this window variable is information about the file, +at the following offsets: +.TS +center; +n l l. +\-14 FBUF Pointer to i/o buffer +\-12 FCHAIN Chain to next file +\-10 FLEV Pointer to associated block mark +\-8 PFNAME Name of file for error messages +\-6 FNAME Name of associated file +\-4 FUNIT Unit number packed with flags +\-2 FSIZE Size of elements in the file +0 File window element +.TE +.PP +Here +.SM FBUF +is a pointer to the input or output buffer for the file. +The standard system routines +.I getc +and +.I putc +are used and provide block buffered input/output, +with 512 characters normally transferred at each read or write. +.PP +The files in the +Pascal environment, +with the exception of +.I input +and +.I output +are all linked together on a single file chain through the +.SM FCHAIN +links. +For each file the +.SM FLEV +pointer gives its associated block mark. +These are used to free files at block exit as described in section 3.3 +below. +.PP +The +NAME +and +PFNAME +give the associated +file name for the file and the name to be used when printing +error diagnostics respectively. +Although these names are usually the same, +.I input +and +.I output +usually have no associated +file name so the distinction is necessary. +.PP +The +FUNIT +word contains the +unit number on which the file is open as well as a set of flags. +These flags and their representations are: +.TS +center; +l l l. +EOF 00400 At end-of-file +EOLN 01000 At end-of-line +SYNC 02000 File window is out of sync +TEMP 04000 File is temporary +FREAD 02000 File is open for reading +FWRITE 04000 File is open for writing +FTEXT 08000 File is a text file; process EOLN +.TE +.PP +The +EOF +and +EOLN +bits here reflect the associated built-in function values. +TEMP +indicates that the file has a generated temporary name and that +it should therefore be removed when its block exits. +FREAD +and +FWRITE +indicate that +.I reset +and +.I rewrite +respectively have been performed on the file so that +input or output operations should be attempted. +FTEXT +indicates the file is a text file so that +EOLN +processing should be done, +with newline characters turned into blanks, etc. +.PP +The +SYNC +bit, +when true, +indicates that there is no usable image in the file buffer window. +As discussed in the +.I "Berkeley Pascal User's Manual," +it is necessary, +because of the interactive environment, +to have ``input^'' essentially undefined at the beginning +of execution so that a program may print a prompt +before the user is required to type input. +The +SYNC +bit implements this. +When it is set, +it indicates that before the element in the window +can be used the Pascal system must actually put something there. +This is never done until necessary. +.NH 2 +Initialization of files +.PP +All the variables in the Pascal runtime environment are cleared to zero on +block entry. +This is necessary for simple processing of files. +If a file is unused, its pointer will be +.B nil. +All references to an inactive file are thus references through a +.B nil +pointer. +If the Pascal system did not clear storage to zero before execution +it would not be possible to detect inactive files in this simple way; +it would probably be necessary to generate (possibly complicated) +code to initialize +each file on block entry. +.PP +When a file is first mentioned in a +.I reset +or +.I rewrite +call, +a buffer of the form described above is associated with it, +and the necessary information about the file is placed in this +buffer. +The file is also linked into the active file chain. +This chain is kept sorted by block mark address, the +FLEV +entries. +.NH 2 +Block exit +.PP +When block exit occurs the interpreter must free the files which are in +use in the block +and their associated buffers. +This is simple and efficient because the files in the active file chain are +sorted by increasing block mark address. +This means that the files for the current block will be at the front +of the chain. +For each file which is no longer accessible +the interpreter first flushes the files buffer +if it is an output file. +The interpreter then returns the file buffer and the files structure and window +to the free space in the heap and removes the file from the active file chain. +.NH 2 +Flushing +.PP +Flushing all the file buffers at abnormal termination, +or on a call to the procedure +.I flush +or +.I message +is quite easy. +The Pascal system simply flushes the file +.I output +and each file on the file chain which has the +FWRITE +bit set in its flags word. +.NH 2 +The active file +.PP +For the purposes of input-output, +.I px +maintains a notion of an active file. +Each operation which references a file makes the file +it will be using the active file and then performs its operation. +A subtle point here is that one may do a procedure call to +.I write +which involves a call to a function which references another file, +thereby destroying the active file set up before the +.I write. +For this reason, +the active file is saved at block entry +in the block mark and restored at block exit.\*(Dg +.FS +\*(dgIt would probably be better to dispense with the notion of +active file and use another mechanism which did not involve extra +overhead on each procedure and function call. +.FE +.NH 2 +File operations +.PP +Files in Pascal can be used in two distinct ways: +as the object of +.I read, +.I write, +.I get, +and +.I put +calls, or indirectly as though they were pointers. +It should be noted that the second use as pointers must be careful +not to destroy the active file in a reference such as +.LS +write(output, input\(ua) +.LE +or the system would end up writing on the input device. +.PP +The fundamental operator related to the use of a file is +FNIL. +This takes the file variable, as a pointer, +insures that the pointer is not +.B nil, +and also that a usable image is in the file window, +by forcing the +SYNC +bit to be cleared. +.PP +The rest of the uses of files and the file operations may be summarized +by a simple example: +.LS +write('*') +.LE +which generates the code +.LS +\s-2UNITOUT\s0 +\s-2CONC\s0 '*' +\s-2WRITC\s0 +.LE +Here the operator +.SM UNITOUT +is an abbreviated form of the operator +.SM UNIT +which sets the active file, +when the file to be made active is +.I output. +Thus to write a character to the file +.I output +it is only necessary to make +.I output +the active file, +to place the character to be output +on the stack, +and to do a +.SM WRITC +write character operation. +.PP +Files other than +.I output +differ from this example only in that the operator +.op UNIT +is used preceded by an evaluation of the file variable expression. +Thus +.LS +writeln(f) +.LE +produces +.LS +\s-2RV\s0 \fIf\fP +\s-2UNIT\s0 +\s-2WRITELN\s0 +.LE +.PP +Write widths are easily handled here by packing information +about the presence or absence of width specifications and their +types into the sub-operation code and pushing the values +of the write widths onto the top of the stack. +.PP +One other operation worth mentioning is +.SM DEFNAME +which is used to implement the program statement association of +file names. +.SM DEFNAME +simply allocates the +.I files +(section 3.1) area for the given file as though +it had been the object of a +.I reset +or +.I rewrite +call, initializing the +FNAME +field, but omitting the system interactions associated with +and actual +.I reset +or +.I rewrite. diff --git a/doc/px/pxin4.n b/doc/px/pxin4.n new file mode 100644 index 0000000000..1724d8707e --- /dev/null +++ b/doc/px/pxin4.n @@ -0,0 +1,72 @@ +.if !\n(xx .so tmac.p +.nr H1 3 +.if n .ND +.NH +Conclusions +.PP +It is appropriate to consider, +given the amount of time invested in rewriting the interpreter, +whether the time was well spent, or whether a code-generator +could have been written with an equivalent amount of effort. +It is the author's belief that the existing code generator for the +.SM +PDP-11 +.NL +series in the +.SM +UNIX +.NL +C compiler could have been easily modified to produce good quality +code for Pascal with not much more work than was involved in +rewriting +.I px. +...FS +..\*(dg With the release of Version 7 +...UX +..and the portable C compiler, an effort has begun to have +...I pi +..use this code generator. +..We hope to have such a system working by September, 1979. +..This would allow Pascal, \s-2FORTRAN\s0\-77 and C programs +..to run together on all systems which support the portable C compiler. +...FE +.PP +The author feels, however, that such an endeavor +would not have been a good choice for an instructional environment. +The speed of binary preparation would have been degraded, and the +necessary loading and assembly processes would have slowed the overall +compilation process to a noticeable degree. +This effect would be further exaggerated by the fact that +student users spend more time in compilation than in execution. +Measurements over the course of a quarter at Berkeley with a mixture +of students from beginning programming to a upper division compiler +construction show that the amount of time in compilation exceeds the amount +of time spent in the interpreter, the ratio being approximately 60/40. +.PP +A more promising approach might have been a throw-away code generator +such as was done for the +.SM +WATFIV +.NL +system. +Here the generated code runs at full machine speed, and compilation +speed is still very fast. +Any code generation scheme would be hindered, however, +if it tried to implement 32 bit integers as implemented by the +current +Berkeley Pascal interpreter. +Given the small number of registers available and the difficulty +of some of the long integer operations it is not clear that +reasonable code generation is possible using long integers. +A 16 bit code generated Pascal would be much simpler, and several +other such implementations exist. +.PP +All things considered, interpretation seems +to be a reasonable choice for a student environment. +While a code generator for +Berkeley Pascal +would be a useful addition to the system, +the author believes that, for instructional use, +a high-quality post-mortem and interactive debugging facility +would be a more valuable addition to the system than a code generator. +The interpreter would be easy to modify to accomodate such facilities. diff --git a/doc/px/tmac.p b/doc/px/tmac.p new file mode 100644 index 0000000000..65c44e9b3c --- /dev/null +++ b/doc/px/tmac.p @@ -0,0 +1,77 @@ +'if \n(FM=0 'so /usr/lib/tmac/tmac.s +.if n .nr FM 1.2i +.if t .tr *\(**=\(eq/\(sl+\(pl +.bd S B 3 +.de SM +.if "\\$1"" .ps -2 +.if !"\\$1"" \s-2\\$1\s0\\$2 +.. +.de LG +.if "\\$1"" .ps +2 +.if !"\\$1"" \s+2\\$a\s0\\$2 +.. +.de HP +.nr pd \\n(PD +.nr PD 0 +.if \\n(.$=0 .IP +.if \\n(.$=1 .IP "\\$1" +.if \\n(.$>=2 .IP "\\$1" "\\$2" +.nr PD \\n(pd +.. +.de ZP +.nr pd \\n(PD +.nr PD 0 +.PP +.nr PD \\n(pd +.. +.de LS \"LS - Literal display; ASCII DS +.if \\n(.$=0 .DS +.if \\n(.$=1 \\$1 +.if \\n(.$>1 \\$1 "\\$2" +.if t .tr '\'`\`^\(ua-\(mi +.if t .tr _\(ul +.. +.de LE \"LE - End literal display +.DE +.tr ''``__--^^ +.. +.de UP +Berkeley Pascal\\$1 +.. +.de PD +\s-2PDP\s0 +.if \\n(.$=0 11/70 +.if \\n(.$>0 11/\\$1 +.. +.de DK +Digital Equipment Corporation\\$1 +.. +.de PI +.I pi \\$1 +.. +.de Xp +.I Pxp \\$1 +.. +.de XP +.I pxp \\$1 +.. +.de IX +.I pix \\$1 +.. +.de X +.I px \\$1 +.. +.de PX +.I px \\$1 +.. +.if n .ds dg + +.if t .ds dg \(dg +.if n .ds Dg \*(dg +.if t .ds Dg \u\s-2\*(dg\s0\d +.if n .ds dd * +.if n .ds Dd \*(dd +.if t .ds Dd \u\s-2\*(dd\s0\d +.if t .ds dd \(dd +.if t .ds b \\fB +.if n .ds b \\fI +.nr xx 1 diff --git a/doc/pxp/makefile b/doc/pxp/makefile new file mode 100644 index 0000000000..bdebbc2804 --- /dev/null +++ b/doc/pxp/makefile @@ -0,0 +1,2 @@ +pxpin: + /usr/new/vtroff -o-2 pxpin?.n diff --git a/doc/pxp/pcrt0.s b/doc/pxp/pcrt0.s new file mode 100644 index 0000000000..903d31a005 --- /dev/null +++ b/doc/pxp/pcrt0.s @@ -0,0 +1,55 @@ +.LS .ID +.ta 8n 16n 24n +.nf +/ +/ Modified C runtime startoff for pcx +/ with floating point interpreter +/ +\&.globl savr5 +\&.globl fptrap +\&.globl _exit, _pxpbuf, _main + +start: +/ +/ If non shared text the following +/ three words will be the beginning of the core image +/ + br 1f + 0 / 0 = Non-shared text + _pxpbuf +1: + sys signal; 4; fptrap + setd + mov sp,r0 + mov (r0),-(sp) + tst (r0)+ + mov r0,2(sp) + jsr pc,_main + cmp (sp)+,(sp)+ + mov r0,(sp) + jsr pc,*$_exit + sys exit + +\&.bss +savr5: .=.+2 +\&.data +/ +/ If pcx is loaded with shared text -n +/ or separate i and d -i, then the +/ following three words will be the first +/ in the core image. Note that in this +/ case the pointer to the buffer will +/ be deceivingly large. The first word +/ of offset can be subtracted to correct +/ it without having to do the involved +/ calculations to really calculate the +/ address of the buffer correctly. We +/ can get away with this because we know the +/ buffer is not in stack space. +/ +_info: + _info + 1 / 1 = pure text + _pxpbuf +.fi +.LE diff --git a/doc/pxp/pxpin0.n b/doc/pxp/pxpin0.n new file mode 100644 index 0000000000..e2ae72128a --- /dev/null +++ b/doc/pxp/pxpin0.n @@ -0,0 +1,114 @@ + +.so tmac.p +'nr H1 -1 +.RP +.TL +Berkeley +Pascal +PXP Implementation Notes +.br +Version 1.1 \- April, 1979 +.AU +William N. Joy* +.AI +Computer Science Division +.br +Department of Electrical Engineering and Computer Science +.br +University of California, Berkeley +.br +Berkeley, California 94720 +.AB +.PP +Berkeley +Pascal is designed for interactive instructional use and runs +on the +\s-2PDP\s0 11 family of computers. +..A version of +...I pxp +..for the \s-2VAX\s0 11/780 is nearly complete. +The Pascal execution profiler +.XP +can be used to generate restructured source program listings +which are annotated with counts of the number of times each statement +in the profiled parts of the program was executed for a +particular run of the program. +A number of options of +.XP +provide easy control over the parts of the program to be profiled. +.Xp +can also be used to produce restructured program listings, +i.e. as a pretty-printer. +.PP +The +.I "PXP Implementation Notes" +describe the design decisions which lead to the present form of +.XP +and give details of the internal organization. +The notes conclude with thoughts on similar facilities for future systems. +.AE +.if n 'ND +.SH +Introduction +.PP +This +.I "PXP Implementation Notes" +consists of four major sections. +In the first section we outline the design considerations which led to the +present +.XP . +Section 2 describes the implementation, with +the comment reformatting process described separately in section 3. +Comments on the viability of the current approach and the +possible shape of future systems are given in section 4. +.SH 2 +Related +.SM +UNIX +.NL +Pascal documents +.PP +The Pascal translator +.I pi +shares with +.I pxp +a common parser and error recovery routines, which is described in +[1]. +.PP +Pascal programs are currently interpreted by a program +.X +as described in the +.I "PX Implementation Notes" +[2]. +An understanding of the particular details of the interpreter is not, however, +necessary to understand the workings of +.XP . +.PP +The +.I "Berkeley Pascal User's Manual" +[3] +gives examples of using +.XP +and is the general reference guide for the system. +.SH +Acknowledgements +.PP +Ken Thompson wrote the first version of +Berkeley +Pascal without which none of this would have been. +Chuck Haley collaborated with the author on the Pascal system +development and his help in teaching the author the ins and outs +of +.UX +was indispensable. +The author's faculty advisor, +Susan L. Graham, +has been a source of much encouragement, support, +and many helpful comments and suggestions. +.FS +* The financial support of an \s-2IBM\s0 Graduate Fellowship +and the National Science Foundation under grants +MCS74-07644-A03 and MCS78-07291 +are gratefully acknowledged. +.FE +.bp diff --git a/doc/pxp/pxpin1.n b/doc/pxp/pxpin1.n new file mode 100644 index 0000000000..a0248ddb20 --- /dev/null +++ b/doc/pxp/pxpin1.n @@ -0,0 +1,677 @@ +.if !\n(xx .so tmac.p +.ND +.nr H1 0 +.NH +Design Considerations +.NH 2 +Goals +.PP +As more fully described in [1], the goals of this +Berkeley +Pascal system are: +.IP +.RS +.HP 1) +To provide an easily usable teaching tool. +.IP 2) +To provide high-quality diagnostics to the user. +.IP 3) +To provide fast compilation at the expense, if necessary, +of execution speed. +.IP 4) +To faithfully implement Pascal 6000\-3.4 as described in [5], and +to be as compatible as possible with the +.SM CDC +implementation of the language. +.RE +.PP +The Pascal execution profiler, hereafter referred to simply as +.XP , +results from the second design goal. +The system, however, would benefit +greatly from a more complete debugging facility. +A design for an +interactive and post-mortem debugger +.I pdb +for the system exists [6], but +has not been implemented as of this writing. +.NH 2 +Placement of statement counters +.NH 3 +Basic considerations +.PP +Execution profiling is quite simple in concept. +One merely places +counters at a sufficient number of points in the program to allow +the determination of the number of times each statement has been executed. +Knuth, in [7], gives an algorithm for determining the minimum number +of counters necessary to gather complete information. +.PP +Berkeley +Pascal code is interpreted. +Thus the addition of statement counters +does not tend to have a significant degrading effect on the speed of execution. +Even in heavily travelled loops, a statement counter is of low enough +execution cost that techniques for, e.g., moving counters out of +.B for +loops were determined to be unnecessary. +More complicated techniques +such as determining the number of calls on a +.B procedure +or +.B function +by adding together the call counts for all calling sites would +not materially decrease the time in execution and would add significantly +to the complexity of the post-processing. +It was thus decided not to do +any counting optimization of this type. +.NH 3 +Goto statements +.PP +A more subtle consideration involved non-local +.B goto +statements. +Without global +analysis, which was not available in the one-pass compiler scheme being +used, there is always the possibility that an arbitrary +.B procedure +or +.B function +call will not return to the calling site. +To maintain +accurate counts and a simple scheme when non-local +.B goto +statements are allowed +would likely involve the placement of a counter after each such +.B procedure +or +.B function +call. +The presence of these extra counters could easily multiply the number +of counters +required for typical programs by a factor of 5 or more. +.PP +As +.B goto +statements which cut across levels of control tend to be used +only in infrequently occurring error situations, it was decided not to place +counters to allow for non-local +.B goto +statements. +Counters are not placed after each +.B procedure +and +.B function +call so, +if a call fails to return, the counts will be inaccurate to +the next sampling point. +.PP +An option to allow for correct counts in the presence of non-local +.B goto +statements +was considered, but rejected. +It was felt that +such an option would rarely, or never, be used. +It is the author's belief that +summary data flow information indicating possible non-local +control transfers would be necessary if the placement of counters were +to be done appropriately. +.NH 3 +Counter placement rules +.PP +Thus, it was decided to place counters at the following program points: +.IP +.RS +.HP 1) +At the entry point to each +.B function +and +.B procedure . +.IP 2) +In the +.B then +part of each +.B if +statement. +The +.B else +part +of each +.B if +statement is counted by subtracting the count for the +.B then +part from the pre-statement count. +.IP 3) +In the body of each +.B repeat , +.B while , +and +.B for +loop. +.IP 4) +On each case of a +.B case +statement, with one counter +for each group of case labels. +.IP 5) +After each +.B goto +statement. +.IP 6) +Before any statement which has a +.B label +preceding it. +.RE +.PP +The counts are made completely accurate in the presence of local +.B goto +statements +by placing an extra counter after each +.B if , +.B repeat , +.B while +and +.B for +statement which contains a +.B goto . +If there is no +.B goto +statement in such a statement, +the count after the statement is taken to be the count before the statement. +.PP +It was later suggested to the author that one could count the frequency +of each individual label in a +.B case +statement, rather than keeping one count for each group. +This might provide useful information for some programs, +but has not been implemented +as an option. +.NH 3 +Partial program counting +.PP +A final consideration related to the placement of counters over parts +of the program only. +This would surely be desirable if gathering profile data were expensive. +In this case a +user might be able to restrict his cost by specifying which +parts of his code were to be counted. +After it was decided +that the profile listing would be constructed by reparsing +the source text of the program and combining it with the profile data, +it seemed clear that the savings from such partial counting would not +materially affect the overall cost of producing a profile. +It was therefore decided to allow selectivity of profile output +in +.XP +rather than selectivity of count gathering at compile or +execute time. +.NH 2 +Producing the profile +.PP +Given the collected data in the form of an array of statement counts, +one then wishes to produce a listing of all or part of the program +with the count information appended in an easily understandable form. +It seems clear that a system which presents the count information +to the user with associated source text from his program will be +superior to one which merely produces a table of counts for identified +points in the program. +.PP +Satterthwaite's +.SM "ALGOL W" +debugging system [8] produced such a listing by +.I unparsing +a saved internal form of the source program. +In his system +this internal form was also used to provide symbolic flow-trace +information at run time. +As we did not propose to do symbolic statement tracing in our +debugger design [6], there was no need for an internal form of the +source program to be available at run time. +Given the fact that our operating system is primarily disk-space +limited, it was decided that reparsing the source text of the program +to produce the execution profile was a reasonable approach. +This allows the profiler to use the existing source text of the +program without requiring a potentially large intermediate form. +This also allowed the profiler to use the existing parser and to +receive as its input a well defined parse tree as described in [1]. +.PP +Thus the execution of a program normally produces a file named +.I pmon.out +which contains an array of counters. +The code generated need contain +only the instructions required to prepare these counts. +This solution +is very conservative of disk storage resources. +.NH 2 +Abnormal termination +.PP +In cases where the execution of a Pascal program terminates abnormally, +or has to be terminated due to apparent infinite looping, it is often +desirable to obtain a profile to help discern the cause of the error. +The Pascal runtime system will create the +.I pmon.out +file in these cases, and profiling is still possible.\u\s-2\*(dg\s0\d +.FS +\*(dg If the Pascal runtime system terminates due to a fault, +either because of a bug in the runtime system, +a severe misuse of pointers, +or an untested out-of-range subscript, +a core-image file will be produced. +It is possible, +using a +.XP +option, +to extract the profile information from this core image, +allowing profiling in this case also. +.FE +It should be noted that, +in general, +the information so gathered is not as usable as that which could be +garnered easily by using a debugger such as +.I pdb +[6], +since variable values are not available. +.PP +A final point to be noted is that the counts are inaccurate +near the suspended control points whenever the program terminates abnormally. +This is explained more fully in [3]. +The complete +debugging system design included the marking in the profile of the +point of abnormal termination in a fashion similar to that used by +Satterthwaite [9], but this has not yet been implemented. +.NH 2 +Formatting of the program +.PP +As already noted, easy comprehension by the user of the the profile +produced by +.I pxp +requires that the profile be in a readable form. +One possibility would be an annotated source listing, using the +form of the original source text. +This has the advantage that +the listing is in a form familiar to the user. +A major disadvantage +in this approach is the fact that the format of the source may not +leave room for easy placement of all of the profile information. +.NH 3 +Pretty printers +.PP +There have been a number of systems designed or constructed which +provide automatically restructured listings of programs +[10] [11] [12] [13]. +Such programs have often been called ``pretty printers.'' +It is not hard to see that the production of a readable profile +from a well-structured listing would not be difficult given +the framework of a pretty printer. +It was therefore decided to produce such a restructured listing +and to annotate it with the profile information. +An option to use the execution profiler as a pretty printer was +also provided. +.NH 3 +Comments and output compression +.PP +One problem with the evolving approach was the treatment of comments. +The interface from the parser to the semantic routines in the compiler, +which was the available and highly suitable framework, had no +provision for the placement of comment text anywhere in the parse tree. +For the purposes of profiling this could be easily tolerated. +An effort can be made when profiling to suppress output which is not absolutely +necessary in the profile. +In particular, comments, declarations, and the bodies of +unexecuted procedures and functions could be normally suppressed. +In fact, early versions of +.XP +suppressed all of these. +In the current implementation, however, +the default is that only the bodies of unexecuted +functions and procedures are suppressed. +All such suppression is controllable through options as described in +[3]. +.PP +The design of the comment formatting facility for +.XP +is presented in section 3. +The author feels that significantly better approaches to program +maintenance and formatting are possible +in future systems. +Some possibilities are discussed in section 4. +.NH 3 +Bushy if\-then\-elses +.PP +Many different formats for presenting Pascal structure are possible. +The author's personal programming style largely determined +the structure of programs produced by +\fIpxp\fR. +In particular, the author was bothered by one feature of other ``pretty +printers.'' +Many other pretty printers +present a ``bushy'' +.I "if\-then\-else" +construct in a fashion similar +to the following: +.LS +\*bif\fR condition1 + \*bthen\fR statement1 + \*belse\fR \*bif\fR condition2 + \*bthen\fR statement2 + \*belse\fR ... +.LE +This could be termed ``wandering across the page.'' +.PP +In structured programs, especially in a language which contains +no +.B return +or other escape statement, it is easy to get ``buried'' +in many levels of conditions. +While the merits of escape-less programming are debatable, it seems +important to present the structure of the above construct as +clearly as possible. +The author feels that a more appropriate way to present +this statement is often the following: +.LS +\*bif\fR condition1 \*bthen\fR + statement1 +\*belse\fR \*bif\fR condition2 \*bthen\fR + statement2 +\*belse\fR + ... +.LE +.NH 3 +Begin\-end pairs and well\-bracketing +.PP +Another aspect of modern programming languages which are not +.I "well-bracketed" +is the presence of +.I "begin\-end" +pairs, which, if mismatched, can cause problems, +especially +if they escape detection at compile time. +With an automatically reformatted listing, the user +no longer needs to worry that his listing may textually represent +the structure of the program in a way different from the true structure. +Given this situation, the author feels that the words +.B begin +and +.B end +convey no information to the user that is not already reflected in +a more convenient form by the textual indentation. +.PP +Thus in considering +how to represent the ``bushy'' +.I "if\-then\-else" +when +.I statement1 +and +.I statement2 +are +.I "begin\-end" +blocks and choosing between: +.LS +\*bif\fR condition1 \*bthen\fR +\*bbegin\fR + statement list 1 +\*bend\fR +\*belse\fR \*bif\fR condition2 \*bthen\fR +\*bbegin\fR + statement list 2 +\*bend\fR +.LE +and +.LS +\*bif\fR condition1 \*bthen\fR \*bbegin\fR + statement list 1 +\*bend\fR \*belse\fR \*bif\fR condition2 \*bthen\fR \*bbegin\fR + statement list 2 +\*bend\fR +.LE +the author chose the latter, which he prefers. +.PP +It should be noted that this is essentially the syntax of +the language +.SM +ALGOL 68 +.NL +[14], +and is similar to Wirth's +.SM +MODULA +.NL +[15], e.g.: +.LS +\*bif\fR condition \*bthen\fR + statement list 1 +\*belsif\fR condition2 \*bthen\fR + statement list 2 +\*bfi\fR +.LE +.NH 3 +Indenting of structured levels +.PP +Another issue of style arises in choosing how many spaces to indent +each structured statement of the source text. +While 8 spaces per level is very +convenient since +one level then corresponds to one +.SM +ASCII +.NL +tab character, +4 spaces seemed to work best with the execution profile when using +an adaptation of the format of Satterthwaite [8]. +Thus, options were provided to allow a level to be defined as +any small number of column positions, with 4 columns the default. +.NH 3 +Expressions +.PP +The printing of expressions presented yet another problem. +It was felt that a format which reflected the true structure of an expression +was best. +For this reason, a fully parenthesized expression format was first tried. +This turned out to be a very poor choice as it made complicated +expressions very hard to read. +The author then implemented a minimal-parenthesis format as the default +with full parenthesization as an option. +.PP +It is probably true that many users would prefer to have their +parenthesization preserved even when the parentheses deleted are, in fact, +unnecessary. +This would be even more true in a language which had a large number +of precedence levels with a large number of operators. +It is not as necessary in Pascal since there are only a small number +of levels here, but such an option would have been useful in any case. +This option is not, however, included in the current +\fIpxp\fR. +.NH 3 +Procedures and functions +.PP +It was decided that +.B procedure +and +.B function +definitions which are nested +within one another would be indented one structured statement +level by default to improve readability. +An option was included to omit this indenting if desired. +.PP +The +.B end +keyword of each +.B procedure +and +.B function +is labelled with the name of the +.B procedure +or +\*bfunction\fR. +This is done also for the opening +.B begin +if any nested +.B procedure +or +.B function +definitions occur within the +.B procedure +or +\*bfunction\fR. +.NH 3 +Case statements +.PP +When first designing the statement formats, the author felt that +the statements in a +.B case +statement should be formatted so that cases with one and cases with +more than one statement would line up for easy readability. +At the time, 8 spaces per level was the default format and the choice +was between: +.LS +\*bcase\fR ch \*bof\fR + \(aa \(aa: + col := col + 1; + tab: + col := (col + 8) \*bmod\fR 8; + \(aa*\(aa: + \*bbegin\fR + tok := star; + tokval := line + \*bend\fR +\*bend\fR +.LE +and +.LS +\*bcase\fR ch \*bof\fR + \(aa \(aa: + col := col + 1; + tab: + col := (col + 8) \*bmod\fR 8; + \(aa*\(aa: + \*bbegin\fR + tok := star; + tokval := line + \*bend\fR +\*bend\fR +.LE +.PP +With the eventual choice of 4 spaces per structured level as the +default indentation, the difference between the corresponding formats +is slight. +In retrospect, this was not +necessarily sufficiently valuable to justify the amount of time spent on the +.B case +statement format, +as different strategies were needed +for each indenting option, and the format was optimized +to be ``pretty'' in each case subject to the alignment constraint. +Thus the current +.XP +uses only the simpler first strategy. +.NH 3 +Labels and miscellania +.PP +Labels are place on a separate line, aligned with the header +line of the +containing +.I program, +.I procedure +or +.I function. +Placed this way, they are easy to locate. +.PP +In general, +the text editing facilities on the +.SM +UNIX +.NL +system are geared toward +line oriented editing. +Thus it is extremely convenient to have statements on single +lines. +For this reason the format of the programs produced by +the pretty printer gives section keywords like +.B var +and +.B type +alone on a line. +In this way deleting the first declaration +of such a section is made easier \- there is no need to split +the keyword away from the first declaration. +.PP +Other options, such as an option to underline all of the keywords +in the program, are provided by +.XP . +These are detailed more fully in [3]. +.NH 3 +Summary +.PP +In summary, the profiler format reflects the taste of +the author in Pascal formatting at the time this program was +written. +It largely succeeds in producing readable Pascal texts. +.PP +Treatment of long statements and placement of multiple statements per line +are desirable additions +and a design for some of these is described in section 2. +They were omitted from the original +design only because the author was not initially sure of a reasonable way +to proceed in these areas, and felt that these were more important +in the context of a pretty printer. +.Xp +was intended primarily as an execution profiler. +Even without the features of section 3, earlier versions of +.XP +were useful in showing students who had trouble formatting their programs +one acceptable way of writing Pascal. +.NH 2 +Profile Data Presentation +.PP +The basic format for the profile is essentially that of Satterthwaite [8] [9]. +Examples are given in [3]. +The following pieces of information are included with the profile +in addition to the basic count information. +.IP +.RS +.HP 1) +The version number and date of the instance of +.XP +which produced the profile. +.RE +.IP +.RS +.HP 2) +The version of the program being profiled (taken to be the time at which +the file it is contained in was last modified.) +.IP 3) +The time at which the profile data was gathered. +.RE +.LP +This information serves to identify uniquely the program involved. +.NH 3 +Count interpretation +.PP +The algorithm for count interpretation is given in [3] and is essentially +the same as that given by Satterthwaite in [9]. +.NH 3 +Data compression +.PP +Two options for compressing profile data are available. +One gives a table of the procedures and functions with their activation +counts. +This requires only a very small amount of data even for large programs. +.PP +More easily readable than a simple table are profiles of parts of a +program. +These can be obtained without modifying the source text. +One can give a list of +.B procedure +or +.B function +names on the command +line, and profiles will be enabled for these and their contained +procedures and functions only. +.PP +This ability to extract selective information and to be able to do it +without modifying the source code is critical. +Editing the source code (at least twice!) for each profiling pass +would not only be tedious, but could easily be done incorrectly. +The command line syntax is simple and relatively foolproof. +This feature is fully described in [3]. +.bp diff --git a/doc/pxp/pxpin2.n b/doc/pxp/pxpin2.n new file mode 100644 index 0000000000..8603bfb138 --- /dev/null +++ b/doc/pxp/pxpin2.n @@ -0,0 +1,1415 @@ +.if !\n(xx .so tmac.p +.ND +.nr H1 1 +.NH +Implementation +.PP +.Xp +is written in the +.UX +systems programming language C. +The structure of +.XP +is very similar to that of the Pascal translator +.PI . +In fact +.XP +was, until recently, a conditional compilation of +.PI . +.Xp +uses the same parser and scanner as +.PI ; +these are described in [1]. +.PP +The major changes to the compiler in writing +.XP +were the rewriting of the +semantic routines of the compiler and the addition of three +``clusters'' +of routines; +one for profiling, +one for the production of the restructured program listing, +and one for the processing of comments. +These ``clusters'' +are written with local data bases, are largely +independent of the other parts of the program, and consist +of a large number of small, related routines. +By structuring the program in this way, functional +independence is obtained. +Clusters are organized separately +from the rest of the program, and accessed through a high-level and abstract +interface. +The concrete implementation of a cluster is not fixed by these +external specifications, and could be changed without the need to +rewrite any other +part of the program provided that the routines then implemented +a suitable interpretation of the same abstraction. +This organization provides a powerful and convenient decomposition +of the profiling process. +.PP +The print cluster routines are kept in the file +.I pp.c. +Their basic function is to provide +an interface to a high-level +printing automaton, with primitives such as +``print keyword'' +and +``print number.'' +Information about the macro- and micro-structure of the output is passed to +the routines implicitly by calling the appropriate entry points. +Thus, after a statement is processed, the routines are informed that an +``item'' is finished so that an intelligent decision can be made about +where to place the statement. +Similarly, when processing a list of items such as a constant type +declaration, the print cluster is given information as to where +the ``left bracket,'' i.e. `(' occurs, where each ``separator,'' i.e. `,' +occurs, and, when the final `)' occurs, this is noted as a ``right bracket.'' +With this information, an implementation of the printing cluster can be +provided which sensibly divides long structured constructs even though it has +no knowledge of the high-level language structure of its input. +.PP +The profile cluster, which is kept in the file +.I pmon.c, +has a number of related functions. +Initially, it deals with the problem of extracting the count information +from the profile data file. +If the execution of the interpreter terminated abnormally, then the data must +be extracted from the +.I core +process image file. +There is an image of the profile data file in the +.I core +image. +To extract the data from +.I core, +.I pxp +need only determine the offset of this image in the file. +.PP +After extracting the data from the file, the profile cluster provides +operations to return successive counters from the count buffer. +In addition it +builds the data structure for storing the information used to print +the optional table summarizing +.B procedure +and +.B function +invocation counts. +Other functions provided include +saving and restoring counts before +and after structured statements, +determining when embedded +.B goto +statements will have caused extra counts to be generated, +generating pseudo-counters for the +.B else +parts of +.B if +statements, +and controlling when the counts are to be printed in the listing +by keeping track of whether each count has been printed. +All manipulation of counts and counters is handled by these routines, +and focuses on a single counter structure called +.PX +which contains the current count. +.PP +In section 2.1 the profile data format and +the process of getting the data from the profile +data file or the +.PX +process +.I core +image are discussed. +Section 2.2 gives the data and control structures of the profiling +and printing clusters, and section 2.3 describes the tree walk +at the function level, and at illustrative parts of the statement +and expression levels. +The implementation description concludes in section 2.4 with +a note on the handling of multi-file programs. +.NH 2 +External data structures +.PP +The following sections deal with the recovery of the profile data. +The simplest case, that of normal termination, is dealt with in section 2.1.1. +The remaining sections deal with the handling of +.I core +process image files. +These are likely to be of interest to +system programmers only. +.NH 3 +Format of the profile data file +.PP +The +.I pmon.out +data file, +is normally written by the Pascal system at the end of profiling +execution. +The record structure of the header at the beginning of the file is as +follows: +.LS +.ta 8n 16n 40n +\*bstruct\fP { + \*bint\fP magic; /* 0426 */ + \*bint\fP magic2; /* 0 */ + \*blong\fP proftime; /* Time profiled */ + \*bint\fP cnt; /* # statement cntrs */ + \*bint\fP pfcnt; /* # procedures+functions + 1 */ +} header; +.LE +Each counter is a long integer so the rest of the file is essentially +an array: +.LS +\*blong\fP counts[header\*b.\fPcnt]; +.LE +.PP +As an error check, +.XP +first insures that the first word is 0426 +and the second is a 0. +If this is true, and the size of the remainder of the file is the size of +the +.I counts +array as implied by the number +.I cnt +in the header, then +profiling can proceed. +If not, then the specified profile data file has a bad format, and +.XP +reports this fact. +.NH 3 +Core data files +.PP +.Xp +has the capability to +extract the profile information from the +.I core +data file dumped by an +abnormal +.PX +termination. +This is greatly simplified by the fact that there is, in the core image, +an exact replica of the +.I pmon.out +file which would have been written at normal termination. +In order to extract the profile data, it is only necessary +to locate this buffer. +.PP +The first 1024 bytes of the core image file is a copy of +the system's per-user data for the process, including the registers +as they were at the time of the fault. +The remainder of the file represents the actual contents of the user's +core area when the core image was written. +If the text segment of the process was write-protected and shared, +it will not be present; otherwise the entire address space will have +been dumped. +.NH 3 +Shared text programs +.PP +It is possible in +.UX +for the text image of a program to be shared by all of the persons +who invoke it. +The instructions will be write protected, and each process which +executes this +.I pure +text will have only a data area, sharing one +common text. +Thus, when such a process is swapped out, only its data area need +be swapped. +The text space can always be abandoned and read in from external +storage when needed, as it cannot have changed. +.PP +When a core image is dumped, +the text space is not dumped if the process was running as shared text. +This is the situation with the installed version of +.PX . +The disadvantage of shared text is that breakpoint debugging +is impossible in this case. +For this reason +.X +is most often debugged +as non-shared text. +It is desirable, therefore, to have +.XP +be able +to extract data correctly in either case. +.PP +The important fact here, which allows a number of simplifications +to the extraction method, is that +the non-stack data space of the process +is dumped immediately after the system area. +If the text space was not ``shared,'' then the first word dumped will +have been location 0 in the process address space, otherwise it will +have been the first data word, as the text of the process appears +first in the process space. +.NH 3 +Extraction methods +.PP +The structure needed to navigate in the +.I core +image is the +.I pcx +information structure\u\s-2\*(dg\s0\d, which has the following format: +.FS +\*(dg +.I Px +was previously +.I pcx +hence the name of this structure +.FE +.LS +\*bstruct\fR { + \*bchar\fR *buf; + \*bint\fR cnt; +} pcx; +.LE +The +.I buf +pointer here points to the image of +.I pmon.out +in core, and is a memory address. +The +.I cnt +gives the size of this image, +and is not currently used by +.XP +as the size is determined from information in the image itself. +If the +.I buf +pointer is 0, i.e. a +.I NIL +pointer, then +.PX +was not +gathering profile data in the execution which abnormally terminated. +.PP +To locate this structure, the runtime start up routine for the interpreter +was modified from the standard C start up to be as given in the following +figure. +.so pcrt0.s +This runtime start up is structured so that it is possible to determine, +from the first three words after the system area, whether +the process was executed as shared text, and the offset of the +.PX +structure in the file. +If the second word here is a 0, then this can only be a non-pure +core image; if it is a 1 then this can only be a pure core image. +If it is neither then this is not a +.PX +core image. +.PP +If the core image is pure, the first word dumped of the process +was not at location 0 in the process data space. +In this case, however, the runtime start up is set up so the +first word contains its address in memory. +Thus it is possible to can convert the third core image word, which is the index +into memory, into an index into the core image by subtracting +this offset from it. +In this way, +.XP +can find the +.I pcx +structure in the +.I core +image. +.PP +As noted above, if the +.I buf +pointer is +NIL, +then +.PX +was not gathering profile data and an appropriate diagnostic will +be printed. +Otherwise, the +.I buf +pointer is offset by subtracting the first word +after the system area in the +.I core +image if the process was pure, +.XP +seeks to the +implied location and a routine common to the +.I core +and +.I pmon.out +profile data gathering routines +.I pmread +is called. +The only notable difference is that after calling +.I pmread +when processing a +.I pmon.out +file, +.XP +checks that all the data on the file is +exhausted. +This is not done when reading a +.I core +data file. +.PP +If any of this seeking or reading terminates abnormally +a +.I "bad format" +diagnostic is given. +.NH 2 +Internal data structures +.NH 3 +External data copies +.PP +The following data items are kept internally after being read from +the +.I pmon.out +or +.I core +data file. +They are available only by using the routines in the cluster in the file +.I pmon.c . +.PP +The integer +.I zcnt +gives the total number of counters, the integer +.I zpfcnt +the total number of procedures and functions. +The pointer +.I zbuf +is (effectively) a dynamic array of long integers +representing the profile counts. +In addition, the external variable +.I ptvec +contains the internal +representation of the time the profile was made. +.NH 3 +Profile cluster data structures +.PP +There are two major profile cluster structures. +The first structure is the primitive unit for storing a piece +of count information and is given by: +.LS +\*bstruct\fP pxcnt { + \*blong\fP ntimes; + \*bint\fP counter; + \*bint\fP gos; + \*bint\fP printed; +}; +.LE +Here +.I ntimes +is the actual count data. +The variable +.I counter +gives a unique identifying tag to this structure, +.I gos +is the number of gotos which had been encountered when this counter +was created, and +.I printed +is actually a Boolean value indicating +whether the counter is considered to have been printed for +the purposes of the profile. +.I Counter +may actually be an index into the array of +values read in from +.I pmon.out , +or it may be a negative number indicating +that it is a counter which was generated by calculations, e.g. for +an +.B else +part of an +.B if +statement. +Other uses of this structure will be described below. +.PP +The other major structure which records information +for each +.B procedure +or +.B function +for the summary table. Its format is: +.LS +\*bstruct\fP pftab { + \*blong\fP pfcnt; + \*bint\fP pfline; + \*bchar\fP *pfname; + \*bint\fP pflev; +} *zpf; +.LE +The field +.I pfcnt +gives the invocation count for each routine, +.I pfline +is the approximate source program line number for the routine, +.I pfname +points to the character string name of the routine, and +.I pflev +gives the nesting level of the routine so it is possible to print +the table with nesting indicating structure. +The variable +.I zpf +is actually a dynamic array holding these counters. +.NH 3 +The profile cluster primitives +.PP +The following are the primitive operations of the profile cluster +kept in the source file +\fIpmon.c\fP. +They deal in particular with one special counter structure +.I px +which holds the current count information as processing progresses. +.IP +.RS +.HP "\*blong\fP nowcnt()" +.br +Returns a \*blong\fP integer which is the current count. +.RE +.IP +.RS +.HP nowcntr() +.br +Returns an integer uniquely identifying the current counter. +.IP "\*blong\fP cntof(pxc)" +.HP "\*bstruct\fP pxcnt *pxc;" +.br +Returns the \*blong\fP integer +.I count +associated with the structure addressed by +\fIpxc\fP. +.IP "setcnt(l)" +.HP "\*blong\fP l;" +.br +Makes the current counter have count +\fIl\fP. +A new, unique counter is generated for this purpose. +This is used, e.g., to assign counts to +.B else +parts of +.B if +statements. +.IP "savecnt(pxc)" +.HP "\*bstruct\fP pxcnt *pxc;" +.br +Saves the information associated with the current count +.I px +in the given structure. +.IP "rescnt(pxc)" +.HP "\*bstruct\fP pxcnt *pxc;" +.br +The inverse of +.I savecnt +setting the fields of +.I px +from the given structure. +.I Rescnt +also returns non-zero exactly when there were embedded gotos. +.IP "getcnt()" +.br +Takes the next counter from the +.I pmon.out +or +.I core +data and places it and associated information into +\fIpx\fP. +The fact that there are less counters in the file than +required by the supplied program is diagnosed as a +``Counter mismatch'' here. +.IP "cnttab(s, no)" +.HP "\*bchar\fP *s;" +.HP "\*bint\fP no;" +.br +Records the current count as being that of a +.B procedure +or +.B function +with number +\fIno\fP. +The number of +procedures and functions are also counted +here so they can be checked for consistency at the end of processing. +.RE +.NH 3 +Profile-printing cluster interface +.PP +The following routines, which are part of the +.I pmon.c +cluster, interface to the printing cluster, and are used +to control the annotation of the program listing with +profile data. +.IP +.RS +.HP "unprint()" +.br +Causes the current counter to become logically ``unprinted'' +so that it will be printed again. +Used, e.g., after restoring a count saved before a loop +to force it to be printed again. +.RE +.IP +.RS +.HP "baroff()" +.br +Turns the printing of the bar `|' in the profile off. +.IP "baron()" +.br +The inverse of +\fIbaroff\fP. +.IP "shudpcnt()" +.br +Returns an integer indicating the type of annotation of the +current line which is desired. +A return value of 0 indicates that only the bar `|' is to +be printed, a value of 1 that the current count and the +bar `|' are to be printed, and a value of -1 indicates that +only white space is to be printed. +A flag set by the routines +.I baroff +and +.I baron +is inspected here. +If the bar `|' to be printed is printed, it is noted that the +current counter was printed so the count will not be printed again. +.RE +.NH 3 +The printing cluster +.PP +The file +.I pp.c +contains the cluster which performs the nitty-gritty business +of preparing the output to be printed. +It was the author's intention, when he wrote the program, to +pass sufficient information to this cluster to allow it to do +the job of breaking up long statements and of placing multiple +statements on each line. +This has not been implemented yet. +The description of how the routines of this cluster +work together to produce the profile is deferred to a later, higher level +view. +.PP +This cluster currently has a very minimal set of data structures. +These structures would expand greatly if the statement folding and +multiple statement placement were implemented. +As it stands +the input is interpreted only in a very simpleminded way. +For this purpose it is only noted whether anything is being printed +at all, indicated by the flag +\fInopflg\fP, +which if non-zero indicates that no printing is to occur, and some information +about the way in which the listing is to be indented. +This is contained in an array giving the indenting in spaces for +each of three levels, i.e.: +.LS +\*b#define\fP DECL 0 +\*b#define\fP STAT 1 +\*b#define\fP PRFN 2 + +\*bint\fP pplev[3]; +.LE +.PP +These levels have rough interpretations as follows. +The white space generated at the very left by the indenting +of nested +.B procedure +and +.B function +declarations is assigned to +\fIpplev[PRFN]\fP, +the white space generated in declaration parts by structured declarations +such as records to DECL, and the white space generated by indenting +of structured statements to STAT. +.PP +The white space is dispersed on the line, separating the left margin, +labels, the profile information, and the program text graphically +given below. +.DS C +line# PRFN label: STAT 999.---| DECL text +.DE +Thus by indenting in the DECL part deeper text nesting can be shown +without the bar wandering to the right, and when indenting in the +STAT part the bar is moved over. +Similarly, the option to indent nested procedures and functions +is trivially handled by indenting in PRFN. +.NH 3 +Printing cluster primitives +.PP +There are two kinds of routines in the printing cluster. +One kind deals with printing the various kinds of tokens in +Pascal programs, e.g. keywords, strings, etc. +The other set of routines deals with the specifics of printing +the profile, i.e. turning printing on and off, indenting, and +the nasty details like the placement of labels. +.IP +.RS +.HP "ppkw(s)" +.HP "\*bchar\fP *s;" +.br +Prints the character string representing the keyword. +Underlining and overstriking of keywords is also handled. +This routine facilitate the suppression of blank lines at the beginning +of partial profiles, +setting a flag the first time it prints a keyword. +Since any solid output always begins with a keyword, +.I ppnl +refuses to print a newline until a keyword is printed. +.IP "ppid(s)" +.HP "\*bchar\fP *s;" +.br +Prints the identifier +.I s +or `{identifier}' if +.I s +is null because of a syntax error. +.IP "ppop(s)" +.HP "\*bchar\fP *s;" +.br +Prints operators. +.IP "ppnumb(s)" +.HP "\*bchar\fP *s;" +.br +Prints numbers. +.IP "ppstr(s)" +.HP "\*bchar\fP *s;" +.br +Prints strings, dealing with doubling of the string metacharacter. +.IP "pplab(s)" +.HP "\*bchar\fP *s;" +.br +Prints a label. +.IP "ppbra(s)" +.HP "ppket(s)" +.HP "ppsep(s)" +.HP "\*bchar\fP *s;" +.br +These routines +are used to indicate the recursive structure of the input +at the microscopic level. +Thus, when printing out the argument list to a +.B procedure +or +.B function, +the opening `(' would be printed with +\fIppbra\fP, +each separating `,' with +\fIppsep\fP, +and the closing `)' with +\fIppket\fP. +This would, conceivably, allow this cluster to break the output sensibly +to conform with the nature of the output medium without having +to deal with the passed-through data at a more difficult macroscopic +level. +.IP "ppspac()" +.HP "pptab()" +.HP "ppitem()" +.HP "ppnl()" +.br +These routines are all used to put separation into the output stream. +In the initial design, the difference between the routines +.I ppitem +and +.I ppnl +was that +.I ppnl +would always force a new-line, while +.I ppitem +separated major units such as statements, but didn't require the +following statement to start on a new line, leaving the possibility +that it be placed on the same line. +In the current implementation, however, both +.I ppitem +and +.I ppnl +force the output to be on a new line. +Note that forcing the output to a new line does not force the +leading white space to be printed! +.RE +.PP +The utility routines which don't deal directly with +the printing of the actual program text follow. +.IP +.RS +.HP "setprint()" +.br +Is called at the beginning of each +.B procedure +or +.B function +body and examines the global environment and option flags +to decide whether that routine should be printed in the profile. +.RE +.IP +.RS +.HP "printon()" +.br +Turns the printing on. +If profiling is notoccuring, a summary table is desired +then this actually turns the printing off! +If neither profiling or a summary table is being producd, +then this call has no effect. +.IP "printoff()" +.br +Turns the printing of the profile off. +.IP "indent()" +.br +If printing, ask +.I linopr +to print the line number. +If producing a profile (rather than just a pretty-print) +indent over +.I +pplev[PRFN] + pplev[STAT] +.R +spaces, and then, depending on the result of a call to +.I shudpcnt +print either a count, some dashes and a bar, just a bar, +or spaces. +Finally, indent +.I pplev[DECL] +more spaces and return. +.IP "dashes(c)" +.HP "\*bchar\fP c;" +.br +Spaces over an amount determined by the indenting level using +the character given. +.IP "indent1(in)" +.HP "\*bint\fP in;" +.br +Actually advance the indent by +.I in +spaces. +If pretty-printing +it is safe to optimize the output by producing tabs, +otherwise spaces must be used. +.IP "linopr()" +.br +Prints the line number if required. +.IP "indentlab()" +.br +Indents for a label print, +.I pplev[PRFN] +spaces using +\fIindent1\fP. +.IP "ppgoin(lv)" +.HP "ppgoout(lv)" +.br +These routines each take one of PRFN, STAT or DECL and increase +or decrease the indentation at that level respectively. +.RE +.NH 2 +Producing the profile +.PP +It should be obvious from the discussion above, that little +difference can be discerned at the top level between producing +a profile and prettyprinting. +When prettyprinting, a large +number of routine calls return without doing any real work. +.PP +The production of the profile is discussed at each of four levels. +The first level is the main routine and option processing. +This is discussed only to give an outline of the work done here. +.PP +The second level is the level of procedures and functions and +involves such considerations as the +.B z +command line option with list of +.B procedure +and +.B function +names, forward declarations, and the recording, saving and +restoring of count information. +.PP +The third level is that of individual statements, and the final +level is that of expressions. These levels are illustrated +with actual code to make the discussion more concrete. +.NH 3 +Main routine and option processing +.PP +The main routine sets up the default options such as setting +the indenting to 4 spaces and turning on nested +.B procedure +and +.B function +indents. +It then examines the arguments and, +importantly, sets the variable +.I profile +if profiling and +.I table +if producing a table of procedure and function counts. +.PP +If a list of +.B procedure +and +.B function +names is given it is saved as referenced by the variables +.I pflist +and +.I pflstc +for examination by the routine +.I inpflist +which is called by routines at +.B procedure +and +.B function +entry and exit. +.PP +After processing all the options, the main routine makes a call +to the +.I pmon.c +cluster to get the profile data if appropriate. +It sets up the input and does some special processing for processing +of +.I include +files as described further in section 2.4 below. +It finally calls the parser which completes the processing of the profile. +.NH 3 +Procedure and function level processing +.PP +The +.B procedure +and +.B function +level processing routines are contained in the file +\fIfdec.c\fP. +The routines here and their functions are: +.IP +.RS +.HP "funchdr(r)" +.HP "\*bint\fP *r;" +.br +Called with a tree node representing the initial declaration +of a function or procedure, e.g.: +.LS +\*bfunction\fP sine(a: angle): \*breal\fP; +.LE +this routine first determines if the routine is in the list +of procedures and functions given on the command line. +If it is, then the +.B z +option value is saved on a stack, +and then turned on. +It then gets the counter associated with the procedure header +and calls a routine in the print cluster to determine whether this +routine should be printed or not. +.IP +It then saves the count information for this routine at its level +in a global array of +.I pxcnt +structures called +\fIpfcnts\fP. +This counter will be restored later when the body of the routine +is encountered. +The printing of the header is also processed here, but this is +similar to other processing to be described later. +This printed header is indented if nested definitions are being indented, +to be unindented after completing the printing of the header. +.RE +.IP +.RS +.HP "funcfwd(fp)" +.HP "\*bchar\fP *fp;" +.br +This routine prints the keyword +.B forward +indented an appropriate amount. +It returns its argument. +.IP "funcbody(fp)" +.HP "\*bchar\fP *fp;" +.br +This routine, called when the actual, resolving declaration of +a +.B procedure +or +.B function +is encountered, indents if the indent nested procedures option +is set, and increments the structured statement level, returning +its argument. +.IP "funcend(fp, blk)" +.HP "\*bchar\fP *fp;" +.HP "\*bint\fP *blk;" +.br +This routine sets up for all of the actual work in printing the body +of procedures and functions. +It restores the count saved by +.I funchdr +from the +.I pfcnts +array, +.I unprints +the count to force it to come out again if there +were any nested procedures or functions, (if the last block number in the +variable +.I lastbn +is not the current block number) +and then prints the body of the procedure or function. +.IP +To print the body, it +\fIindents\fP, +prints the keyword +.B begin, +and if there were nested sections prints +the name of this routine in a comment. +It then goes in a level in DECL (without shifting the bar over!) +and prints the statement list given by the parameter +\fIblk\fP. +.RE +.PP +This is an appropriate place to note the following important fact: +When a routine is called to put out an item at the statement level, +the +.I "output cursor" +is usually at the end of the previous line, and if the routine +wants to print on a clean line, then it calls +.I ppnl +before it begins. +If it is willing to print on the same line then it can call +\fIppitem\fP. +It also turns out that this structure is critical for the processing +of comments which is described in section 3. +A delay in printing +the new line character allows the comment processing to function +correctly. +.PP +Thus, after the routine +.I statlist +processes the parameter +.I blk +the rotuines +\fIppnl\fP, +an +\fIindent\fP, +are called and the keyword +.B end +is printed followed by the routine name in a comment and a final +.I ; +or +.I \&. +character. +Finally unwind from any indenting that may have been done due +to the indent nested sections option occurs, and the +.B z +option stack is popped if this routine was in the command line +.B procedure +and +.B function +list. +.NH 3 +Statement processing +.PP +The statement level processing is done by the routines in the file +.I stat.c +and for case statements by the code in the file +\fIcase.c\fP. +As noted above, the cursor for each statement is generally left +on the previous line so that a statement will ask for the cursor +to be advanced to the next line if so desired. +This is also necessary to make the placement of +.B begin +and +.B end +pairs work as desired. +The basic loop for processing a group of statements is as follows: +.LS +statlist(sl) + \*bregister\fP \*bint\fP *sl; +{ + \*bif\fP (sl != NIL) + \*bfor\fP (;;) { + statement(sl[1]); + sl = sl[2]; + \*bif\fP (sl == NIL) + \*bbreak\fP; + ppsep(";"); + } + \*belse\fP + statement(NIL); +} +.LE +This is quite simple. +A pointer to a tree structure is received, treated as an array +of integers. +The first word of each such node is a magic number giving the +kind of node, the second word points to a statement and the third +word links to the next such node, or NIL if this is the last node +in the statement list. This is more fully described in [1], +the nodes here being of type T_LISTPP. +.PP +To illustrate the processing for statements in general, +a subset of the code from the +.I stat.c +file comprising that for +.B if +statements, assignment statements and +.B "begin-end" +blocks within +.B if +statements follows. +This is illustrative of the work here in general. +.so stat.c +.PP +.I Statement +receives as argument a pointer to a tree node. +For the purposes of this discussion, assume that this node is either of type +T_IF, T_IFEL, or T_ASGN. +The node type T_IFEL was added to the parser because +of the problematic case of empty +.B else +clauses. +When these empty clauses are present, it is impossible +to present the data for both +.B if +statements without +.B else +and with +.B else +parts in the one T_IF structure. +An +.B if +statement without an +.B else +part looks the same as an +.B if +statement with an empty +.B else +part in this case. +This is a problem because +.I pxp +does not realize that the discarding of such empty +.B else +parts can affect the matching of outer +.B else +clauses with +.B if +parts and alter the meaning of the program! +.PP +Now, if the argument to +.I statement +is a NIL pointer, \fInull\fR is printed, +a call on a built-in procedure that does nothing. +The fact that a +.I ppitem +rather than a +.I ppnl +is done here indicates that it does not matter if this is on the same line +with something else. +If the argument pointer is not NIL a switch is done based +on which type of statement is involved. +.PP +For assignments, as for the \fInull\fR above, +the statement can appear on the same line with something else. +Thus +.I ppitem +is called. +To print an assignment first an +.I lvalue +(essentially a variable) +and then an +.I rvalue +(an expression) +must be printed, separated by a `:='. +This is as simple as knowing which fields to pass to +procedures +.I lvalue +and +.I rvalue . +.PP +Note that +.I rvalue +here takes two arguments. +The second argument is a flag indicating whether the +expression is to be surrounded by parentheses if +it is not-atomic. +Since no ambiguity can possibly result, no parenthesis are required here. +.NH 3 +If\-then\-else's +.PP +It is required that an +.I if +statement appear on a separate line by calling +.I ppnl . +The routine +.I ifop +begins by printing: +.LS +\*bif\fP \*bthen\fP_ +.LE +where the `_' will be used to represent the invisible output cursor. +The expression here also need not be parenthesized. +.I Ifop +then saves the count before the statement by calling +\fIsavecnt\fP, +and gets the count for the +.I then +part of the statement by calling +\fIgetcnt\fP. +The +.B then +part can now be handled. +.PP +If the +.B then +part is a +.B begin\-end +block, it can be started on this line. +Thus, in this case, the routine +.I ppstbl1 +can be called with the +.I then +part as argument. +It is also passed STAT, indicating that the indent it will do +is to be reflected in the position of the bars on the left. +(For +.B with +statements among others, the bars do not move over +the text is indented.) +Now +.I ppstbl1 +prints out the keyword +.I begin +and does the indent discussed above, but does not put out a newline. +That is up to the routine +.I statement +which will be called by +\fIstatlist\fP. +The +.B end +is not put out yet because the counter for the +.B else +part belongs on the line with +it if there is an +.B else +part and that count has not been set up yet. +.PP +If the statement in the +.B then +part is not a +block then the processing here is much simpler; +it is only necessary to indent a level in the STAT part as a block, +call +.I statement +and then unindent the level. Thus a typical +position after this part is completed for a +.B then +part which is a block would be: +.LS +\*bif\fP \*bthen\fP \*bbegin\fP + stat1; + stat2_ +.LE +with the cursor convention as before. +.PP +If this +.B if +statement does not have an +.B else +part the rest of the processing is simple. +The count saved before the statement is restored, doing a +.I getcnt +if there were one or more +.B goto +statements in the body of the +statement to get the count after the statement. +If the +.B then +part was a block, +.I ppstbl2 +is called to put the keyword +.B end +indented on a new line with the restored count. +This finishes the processing in this case. +.PP +If the statement has an +.B else +part then the count for this part must first be calculated. +This is done by taking the +.I cntof +the saved structure from before the +.B if +statement and subtracting the current count which is that of the +.B then +part. +This becomes the new counter generated for the +.B else +part. +Processing of the +.B then +part is then finished either by printing a +.B end +with +.I ppstbl2 +as above, followed by a space, +or by forcing a new line in the output and calling +.I indent. +The keyword +.B else +is printed in the output and followed with a space. +.I Unprint +is called so that the count for an +.B else +part prints not only with the +.B else +but also on the statement in the +.B else +part. +This significantly improves the readability of bushy if-then-elses. +.PP +The special case of an empty statement in the +.B else +part is caught and a null statement is put out in this case. +Otherwise a check is made to see if the +.B else +part is a block, and if so, handled in a manner identical to the processing +for the +.B then +part. +Nested +.B if +statements are then caught, and are recursive call is made without +doing any indentation. +This accomplishes the goal of not ``wandering across the page'' +in if-then-else statements. +.PP +Noting that normal statements are treated as before, +the +.B else +part has been successfully completed except for some cleanup. +This cleanup involves restoration of the count and printing of the +keyword +.B end. +Note that the pre +.B if +statement count must be unprinted whenever an +.B else +occurs. +This is because of the way +.B else +parts are printed, lined up with the +.B if +parts and obstructing their counts. +.NH 3 +Expression processing +.PP +The final part of the profiling process to be discussed +is the printing of expressions. This is quite simple, +actually, with the only interesting code being that which +determines what parenthesization to do. This happens as follows. +.PP +Whenever a binary operator is encountered each of its operands +is processed in turn. +The following cases are from the +.B switch +in the routine +.I rvalue +and indicates the code for processing binary operators. +.LS +\*bcase\fP T_AND: +\*bcase\fP T_OR: +\*bcase\fP T_MULT: +\*bcase\fP T_ADD: +\*bcase\fP T_SUB: +\*bcase\fP T_DIVD: +\*bcase\fP T_MOD: +\*bcase\fP T_DIV: +\*bcase\fP T_EQ: +\*bcase\fP T_NE: +\*bcase\fP T_GE: +\*bcase\fP T_LE: +\*bcase\fP T_GT: +\*bcase\fP T_LT: +\*bcase\fP T_IN: + al = r[2]; + rvalue(al, prec(al) < prec(r) || opt('f')); + ppspac(); + \*bif\fP (alph(opname[0])) + ppkw(opname); + \*belse\fP + ppop(opname); + ppspac(); + al = r[3]; + rvalue(al, prec(al) <= prec(r) || opt('f')); + \*bbreak\fP; +.LE +.PP +The routine +.I prec +returns an integer representing the precedence of the +operator given. +It is defined by: +.LS +prec(r) + \*bregister\fP \*bint\fP *r; +{ + \*bif\fP (r == NIL) + \*breturn\fP; + \*bswitch\fP (r[0]) { + \*bcase\fP T_NOT: + \*breturn\fP (3); + \*bcase\fP T_MULT: + \*bcase\fP T_DIVD: + \*bcase\fP T_DIV: + \*bcase\fP T_MOD: + \*bcase\fP T_AND: + \*breturn\fP (2); + \*bcase\fP T_ADD: + \*bcase\fP T_SUB: + \*bcase\fP T_OR: + \*breturn\fP (1); + \*bdefault\fP: + \*breturn\fP (0); + } +} +.LE +Thus, with a binary operator, +parentheses are needed around the left operand if it is non-atomic +and its operator has lower +.I prec +than the current operator. +Parentheses are needed around the right operand if it is non-atomic +and its operator has fewer or the same +.I prec +as the current operator. +This equality condition reflects Pascal associativity. +.NH 2 +Multiple file processing +.PP +.I Pxp +has the capability of handling +.I include +files. +Just as programs to +.PI +may be split into many pieces, they may be so split and then +processed by +\fIpxp\fP. +In addition a capability for pretty printing of one piece of +a program has been included in +\fIpxp\fP. +If +.I pxp +is pretty printing and the file being pretty printed +has a name ending in +.I \&.i +then +.I pxp +will place the line +.LS +\*bprogram\fP x(output); +.LE +into the source stream before the first line of the file +and the line +.LS +\*bbegin\fP \*bend\fP. +.LE +after the last line. +In this way, if the contents of the +.I include +corresponds to a global declaration part and/or +a group of procedures and functions, the pretty print +can proceed without modifications to the source text. +This is the only case in which the pretty printer will +take anything other than a complete Pascal program. +.I Pxp +suppresses printing back out the inserted and appended lines +in this case. +.PP +.Xp +does not normally process +.I include +directives but rather prints them back out as includes. +An option to eliminate the includes is also available. +.bp diff --git a/doc/pxp/pxpin3.n b/doc/pxp/pxpin3.n new file mode 100644 index 0000000000..c0e98b638a --- /dev/null +++ b/doc/pxp/pxpin3.n @@ -0,0 +1,441 @@ +.if !\n(xx .so tmac.p +.ND +'nr H1 2 +.NH +Automatic program formatting +.NH 2 +Motivation +.PP +Just as software packages to automatically format documents +aid the construction of readable and accurate documents, +packages which aid the construction of programs by helping prepare +and maintain the text in a standard and easily readable format +can aid the entire programming process. +With an automatically structured listing, the reader can trust the +textual display of the program to be accurate and can concentrate +on understanding the program, rather than deciphering the style in +which it is written. +Even when +.I "programming secretaries" +are available, an automated preparation system can improve the +programming process by defining a standard format for programs, +making them easier to read. +After programs are completed, and modifications to provide new features +or to correct bugs are required, an automatic formatting system +can work with an intelligently designed source code control +system to help maintain clean programs with their histories. +.PP +The first version of +.I pxp +took a step toward the goal of machine aided program formatting +by formatting the code of the program. +It did not, however, in any way help with the annotation of +the program with comments. +The following sections describe a comment processing +facility design which was added to +.I pxp. +.NH 2 +Implementation +.PP +When parsing the program information is saved in the parse tree which +tells the source text coordinates (sequence numbers and columns) +for the input tokens at the boundaries of chosen productions. +The comments from the source program are saved in a separate data +structure together with information about their source text locations and a +classification of their ``type.'' +The comment reformatting process proceeds by printing out the parsed program +and periodically flushing out comments. +.NH 3 +The kinds of comments +.PP +.I Pxp +distinguishes several types of comments in the input thereby varying +their placement in the output. +The four basic kinds of comments are: +.IP +.B +Left marginal. +.R +At the left margin on input these comments are retained at the +left margin in the output. +.IP +.B +Aligned. +.R +Comments which are not at the left margin on input but which have no tokens +preceding them on the input line are aligned with the program text on output. +.IP +.B +Trailing. +.R +Comments appearing after tokens in the input line but separated from the +last token on the line by only a small amount of white space are placed +similarly in the output. +.IP +.B +Right marginal. +.R +Comments which are more than a small amount of white space past the last +token on a line are aligned about 35 spaces to the right of the running +program text. +.PP +In addition to these comments, other formatting features of the input +are preserved to the output. +These include blank lines, form ejects, and +.B include +directives. +.NH 2 +Examples of comment types +.PP +Consider the following example: +.LS +{ Factorial program - Assigment 1 + John Jones, CS 153, Fall 1977 } + +\fBprogram\fP fact(output); +\fBconst\fP maxfact = 20; {last factorial to be computed} + + \fBfunction\fP rfact(i: integer): integer; + \fBbegin\fP + \fBif\fP i <= 1 \fBthen\fP {terminate} + fact := 1 + \fBelse\fP {recurse} + fact := i * fact(i - 1) + \fBend\fP; + +\fBbegin\fP + i := 1; + j := 1; + {iterative factorial} + \fBrepeat\fP + writeln(i, j); + j := j * i; + i := i + 1; + \fBuntil\fP i > maxfact; + + {recursive factorial} + \fBfor\fP i := 1 \fBto\fP maxfact \fBdo\fP + writeln(i, rfact(i)) +\fBend\fP. +.LE +.PP +This program has all four basic comment types. +The first comment is +.I marginal +(and is followed by a blank line which is also preserved in a +reformatted listing.) +The comments in the text ``iterative factorial'' +and ``recursive factorial'' are +.I aligned +comments. +The comment on the declaration of +.I maxfact +is a +.I trailing +comment while the comments in +.I rfact +are +.I "right marginal." +.PP +Since the objective of the program reformatting is to not require the +saving of the raw programs which produced the restructured programs, +it is necessary for the reformatting to produce programs which are +.I "fixed points" +with respect to the comment processing; +that is the form of restructured programs must be preserved under +repeated reformatting. +The above types of comments have been carefully chosen so that +this occurs. +.NH 3 +Data structures (overview) +.PP +The following sections provide a brief descriptions of the data structures +used by the comment formatting cluster and the method used by the cluster +itself. +The actual reformatting process involves a number of complications not +detailed here, necessary to discern as much as possible from the source +text in order to reasonably classify comments into one of the four available +types, and in order to live with the existing structure of the parser of +.I pi . +.PP +As each comment is encountered in the source text it is chained +onto a singly linked list recording the kind of comment involved; +the comment delimiter, either `{' or `(*'; +the source text coordinates of the comment; +and a linked list of lines of comment text. +.PP +The other data structure used to gather information is a stack parallel to the +parse stack. +For each element of the parse stack this stack contains the source text +coordinates of the leftmost token shifted over in creating the associated +state. +Thus, when a reduction occurs, it is possible to identify the portion of the +input text which was reduced. +At numerous points in the parse tree where comment text is to be processed +we save the source coordinates of the first and last token in the reduced +production as well as the coordinates of the following (lookahead) token. +.NH 3 +Comment processing (overview) +.PP +Formatting of the comments back into the program uses the source text +coordinates embedded in the parse tree and attached to comments to construct +a formatted listing. +The ideas involved are quite simple. +When we begin to print out a statement level subtree we first print out +comments which precede this statement. +We then print out the statement itself, +possible invoking this process recursively. +In recursive declarations provisions are made for embedded comments also. +.PP +The most important complication is that comments which appear after the last +token of a +.B procedure +or +.B function +must be associated with this routine rather than being printed before the +next. +This requires a special ``to end of line'' kind of comment flushing. +Other complications arise because of the pre-existing data structures in +.I pxp . +The code for +.I pxp +contains a number of comments detailing the resolution of these and other +problems. +.bp +.NH +Conclusions +.NH 2 +Design +.PP +In retrospect, most of the design decisions were well-made. +The counter placement rules resulted in a small number of counters. +The reparsing of the program runs at a reasonable rate, +approximately twice the speed of compilation. +The inaccurate counts which may be generated with non-local +.B goto +statements have as yet caused no problems. +The biggest deficiency in the design is, in fact, the lack of a debugger +implementation to complement the profiling facilities. +.NH 2 +Implementation +.PP +The implementation proved to be quite simple. +The design choices allowing +.I pxp +to use the framework of +.I pi +were well taken. +The largest weakness of the implementation may be the fact that +the print cluster structure may not necessarily be the best one for +doing long statement folding across line boundaries, and for +processing the placement of multiple statements per line. +Whether or not this is true would be seen if such a implementation +modification were attempted. +.NH 2 +Profiling +.PP +The format of the profile worked out quite well. +Basing the format on [9] was an excellent choice. +For initialization procedures and some others, multiple +statement per line placements is noticeably needed. +It is felt that languages which offer initialization facilities +for structured statements will likewise need more complex format +processing in such declarations. +With comment reformatting a profile can substitute +for a program listing. +In this case the philosophy of suppressing unexecuted +.B procedure +and +.B function +bodies as well as declaration parts +might be re-examined. +.NH 2 +Reformatting +.PP +For program formatting, a comment formatting facility is a must. +The author feels that the basic format of programs is well chosen, +but most persons would prefer an (at least slightly) different format. +Again, long statement folding and the placement of multiple statements +per line would be a plus here. +Even in its present state, the formatting facilities are judged to be +useful, especially for showing students with no perceivable style +one plausible way of formatting Pascal programs. +.NH 2 +Future systems +.PP +Execution profiling is an important tool because it provides feedback at the +source program level. +A number of systems including such facilities exist or are proposed +[10] [11] [12] [13]. +The author expects the following to be components of future systems: +.HP +.RS +.IP 1) +Source language editors [16] [17] +.IP 2) +Symbolic source language debuggers [8] [16] +.IP 3) +Source code control systems [18] +.RE +.PP +A well-designed programming language system with these components could provide +systems programmers with a powerful set of system construction tools, +similar to those available in excellent \s-2LISP\s0 systems such as [16]. +.bp +.SH +References +.PP +.IP [1] +Charles B. Haley +.br +Master's Project Report +.br +U.C. Berkeley, June, 1977. +.IP [2] +William N. Joy +.br +.I "PX 1.1 Implementation Notes" +.br +October, 1978. +.IP [3] +William N. Joy, Susan L. Graham, and Charles B. Haley +.br +.I "Berkeley Pascal User's Manual" +.br +Version 1.0 \- November, 1977. +.IP [4] +K. Thompson and D. M. Ritchie +.br +.I +UNIX +Programmers Manual +.R +.br +Version 6.7 +(revised at University of California) +.br +June 1977. +.IP [5] +Kathleen Jensen and Niklaus Wirth +.br +.I +Pascal \- User Manual and Report +.R +.br +Springer-Verlag, New York +.br +1975. +.IP [6] +William N. Joy +.br +.I "PDB Design notes and draft manual" +.br +January, 1977. +.IP [7] +D. E. Knuth and F. R. Stevenson +.br +.I "Optimal measurement points for program frequency counts" +.br +BIT 13 (1973) 313-322. +.IP [8] +Edwin H. Satterthwaite +.br +.I "Source Language Debugging Tools" +.br +STAN-CS-75-494, May, 1975. +.IP [9] +Edwin H. Satterthwaite +.br +.I "Debugging Tools for High Level Languages" +.br +Software, Practice and Experience +.br +Vol. 2, 197-217, 1972. +.IP [10] +J. D. Ichbiah, J, C. H\*'eliard, J. P. Rissen, P. Cousot +.br +.I "The Systems Implementation Language LIS - Reference Manual" +.br +Technical Report 4549 E1/EN. +.br +Compagnie Internationale pour l\(aaInformatique +.br +68, route de Versailles \- 78430 LOUVECIENNES +.br +December 1974. Revised January 1976. +.IP [11] +B. W. Lampson, J. J. Horning, R. L. London, J. G. Mitchell, G. L. Popek +.br +.I "Report on the Programming Language Euclid" +.br +Sigplan Notices, Volume 12, Number 2. +.br +February 1977. +.br +Pp. 64-65. +.IP [12] +D. T. Barnard +.br +.I "Automatic generation of syntax-repairing and paragraphing parsers" +.br +Technical Report CSRG-52. +.br +Computer Systems Research Group +.br +University of Toronto, Toronto, Ontario. +.br +April 1975. +.IP [13] +R. C. Holt and D. T. Barnard +.br +.I "Syntax directed error repair and paragraphing" +.br +Computer Systems Research Group. +.br +University of Toronto, Toronto, Ontario. +.br +June, 1976. +.IP [14] +A. van Wijngaarden, et. al. +.br +.I "Revised Report on the algorithmic language ALGOL 68" +.br +Sigplan Notices, Volume 12, Number 5. +.br +May 1977. +.IP [15] +Niklaus Wirth +.br +.I "Modula: A language for modular multiprogramming" +.br +Institut f\*:ur Informatik +.br +ETH, CH 8092 Z\*:urich +.br +March, 1976. +.IP [16] +Warren Teitleman +.br +.I "Interlisp Reference Manual" +.br +Xerox Palo Alto Research Center +.br +Palo Alto, California +.br +December 1974. +.IP [17] +Steve German +.br +.I +ECL in-core editor +.R +.br +Documentation dated 10/20/1973. +.IP [18] +Rochkind, Marc J. +.br +The Source Code Control System +.br +IEEE TOSE Vol SE-1 #4 +.br +Dec. 1975, 364-370 diff --git a/doc/pxp/stat.c b/doc/pxp/stat.c new file mode 100644 index 0000000000..109985e3cb --- /dev/null +++ b/doc/pxp/stat.c @@ -0,0 +1,109 @@ +.LS .ID +.nf +statement(s) + \*bregister\fP \*bint\fR *s; +{ + + \*bif\fP (s == NIL) { + ppitem(); + ppid("null"); + \*breturn\fP; + } + line = s[1]; + \*bswitch\fP (s[0]) { + \*bdefault\fP: + panic("stat"); + \*bcase\fP T_IF: + \*bcase\fP T_IFEL: + ppnl(); + indent(); + ifop(s); + \*breturn\fP; + \*bcase\fP T_ASGN: + ppitem(); + asgnop(s); + \*breturn\fP; + } +} + +asgnop(r) + \*bregister\fP \*bint\fR *r; +{ + lvalue(r[2]); + ppsep(" := "); + rvalue(r[3], NIL); +} + +ifop(r) + \*bregister\fP \*bint\fR *r; +{ + \*bregister\fP \*bint\fR *s; + \*bstruct\fP pxcnt scnt; + + ppkw("if"); + ppspac(); + rvalue(r[2], NIL); + ppspac(); + ppkw("then"); + ppspac(); + s = r[3]; + savecnt(&scnt); + getcnt(); + \*bif\fP (s != NIL && s[0] == T_BLOCK) + ppstbl1(s, STAT); + \*b\*belse\fP\fR { + ppgoin(STAT); + statement(s); + ppgoout(STAT); + } + \*bif\fP (r[0] == T_IFEL) { + setcnt(cntof(&scnt)-nowcnt()); + \*bif\fP (s == NIL || s[0] != T_BLOCK) { + ppnl(); + indent(); + } \*belse\fP { + ppstbl2(); + ppspac(); + } + s = r[4]; + ppkw("else"); + unprint(); + ppspac(); + \*bif\fP (s == NIL) + \*bgoto\fP burp; + \*bif\fP (s[0] == T_BLOCK) + ppstbl1(s, STAT); + \*belse\fP \*bif\fR (s[0] == T_IF || s[0] == T_IFEL) + ifop(s); + \*belse\fP { +burp: + ppgoin(STAT); + statement(s); + ppgoout(STAT); + } + } + \*bif\fP (rescnt(&scnt)) + getcnt(); + \*bif\fP (r[4] != NIL) + unprint(); + \*bif\fP (s != NIL && s[0] == T_BLOCK) + ppstbl2(); +} + +ppstbl1(r, m) + \*bint\fP *r, m; +{ + ppkw("begin"); + ppgoin(m); + statlist(r[2]); + ppgoout(m); +} + +ppstbl2() +{ + ppnl(); + indent(); + ppkw("end"); +} +.fi +.LE diff --git a/doc/pxp/tmac.p b/doc/pxp/tmac.p new file mode 100644 index 0000000000..b1ea274244 --- /dev/null +++ b/doc/pxp/tmac.p @@ -0,0 +1,77 @@ +'if \n(FM=0 'so /usr/lib/tmac/tmac.s +.if n .nr FM 1.2i +.if t .tr *\(**=\(eq/\(sl+\(pl +.bd S B 3 +.de SM +.if "\\$1"" .ps -2 +.if !"\\$1"" \s-2\\$1\s0\\$2 +.. +.de LG +.if "\\$1"" .ps +2 +.if !"\\$1"" \s+2\\$a\s0\\$2 +.. +.de HP +.nr pd \\n(PD +.nr PD 0 +.if \\n(.$=0 .IP +.if \\n(.$=1 .IP "\\$1" +.if \\n(.$>=2 .IP "\\$1" "\\$2" +.nr PD \\n(pd +.. +.de ZP +.nr pd \\n(PD +.nr PD 0 +.PP +.nr PD \\n(pd +.. +.de LS \"LS - Literal display, ASCII, constant spaced DS +.if \\n(.$=0 .DS +.if \\n(.$=1 \\$1 +.if \\n(.$>1 \\$1 "\\$2" +.if t .tr '\'`\`^\(ua-\(mi +.if t .tr _\(ul +.. +.de LE \"LE - End literal display +.DE +.tr ''``__--^^ +.. +.de UP +Berkeley Pascal\\$1 +.. +.de PD +\s-2PDP\s0 +.if \\n(.$=0 11/70 +.if \\n(.$>0 11/\\$1 +.. +.de DK +Digital Equipment Corporation\\$1 +.. +.de PI +.I pi \\$1 +.. +.de Xp +.I Pxp \\$1 +.. +.de XP +.I pxp \\$1 +.. +.de IX +.I pix \\$1 +.. +.de X +.I px \\$1 +.. +.de PX +.I px \\$1 +.. +.if n .ds dg + +.if t .ds dg \(dg +.if n .ds Dg \*(dg +.if t .ds Dg \*(dg +.if n .ds dd * +.if n .ds Dd \*(dd +.if t .ds Dd \*(dd +.if t .ds dd \(dd +.if t .ds b \\fB +.if n .ds b \\fI +.nr xx 1 -- 2.20.1