Nearby is CSTR #8, which is a report by Steve Johnson and Brian Kernighan describing the B implementation on Honeywell equipment.
The language being described was really the same, but it's interesting to look at the differences in description and environment. To describe the BNF syntax, Ken used a variant that depends on super- and subscripts to say "how many", which in the original were stacked above each other when they occurred simultaneously. This doesn't look too awful in the HTML rendering, but was probably better in the original.
The other thing that is observable is the degree to which the GCOS version had to struggle to work in that environment. Its library description is full of odd concepts like "the AFT" the *SRC file, and other peculiarities.
--DMR, July 1997 ]
{..}m m,m+1,...
{..}mn m,m+1,...,n
program ::=
{definition}0
definition ::=
name {[ {constant}01 ]}01 {ival {, ival}0}01 ;
name ( {name {, name}0}01 ) statement
ival ::=
constant
name
statement ::=
auto name {constant}01 {, name {constant}01}0 ; statement
extrn name {, name}0 ; statement
name : statement
case constant : statement
{ {statement}0 }
if ( rvalue ) statement {else statement}01
while ( rvalue ) statement
switch rvalue statement
goto rvalue ;
return {( rvalue )}01 ;
{rvalue}01 ;
rvalue ::=
( rvalue )
lvalue
constant
lvalue assign rvalue
inc-dec lvalue
lvalue inc-dec
unary rvalue
& lvalue
rvalue binary rvalue
rvalue ? rvalue : rvalue
rvalue ( {rvalue {, rvalue}0 }01 )
assign ::=
= {binary}01
inc-dec ::=
++
--
unary ::=
-
!
binary ::=
|
&
==
!=
<
<=
>
>=
<<
>>
-
+
%
*
/
lvalue ::=
name
* rvalue
rvalue [ rvalue ]
constant ::=
{digit}1
' {char}12 '
" {char}0 "
name ::=
alpha {alpha-digit}07
alpha-digit ::=
alpha
digit
*0 null
*e end-of-file
*( {
*) }
*t tab
** *
*' '
*" "
*n new line
(b? f:g[i] )(1, x>1)
*X
&x
lvalue op rvalue
if(rvalue) statement1
if(rvalue) statement1 else statement2
if(x=(rvalue)) statement1 if(!x) statement2
while(rvalue) statement
x: if(rvalue) { statement goto x; ]
switch rvalue statement1
case constant:
goto rvalue ;
return ;
return ( rvalue ) ;
extrn name1 , name2 ... ;
auto name1 {constant}01 , name2 {constant]01 ... ;
name :
main(); exit();
name {ival , ival ...}0 ;
name [ {constant}01 ] {ival , ival ...}0 ;
name ( arguments ) statement
/* The following function will print a non-negative number, n, to
the base b, where 2<=b<=10, This routine uses the fact that
in the ANSCII character set, the digits O to 9 have sequential
code values. */
printn(n,b) {
extrn putchar;
auto a;
if(a=n/b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n%b + '0');
}
/* The following program will calculate the constant e-2 to about
4000 decimal digits, and print it 50 characters to the line in
groups of 5 characters. The method is simple output conversion
of the expansion
1/2! + 1/3! + ... = .111....
where the bases of the digits are 2, 3, 4, . . . */
main() {
extrn putchar, n, v;
auto i, c, col, a;
i = col = 0;
while(i<n)
v[i++] = 1;
while(col<2*n) {
a = n+1 ;
c = i = 0;
while (i<n) {
c =+ v[i] *10;
v[i++] = c%a;
c =/ a--;
}
putchar(c+'0');
if(!(++col%5))
putchar(col%50?' ': '*n');
}
putchar('*n*n');
}
v[2000];
n 2000;
/* The following function is a general formatting, printing, and
conversion subroutine. The first argument is a format string.
Character sequences of the form `%x' are interpreted and cause
conversion of type 'x' of the next argument, other character
sequences are printed verbatim. Thus
printf("delta is %d*n", delta);
will convert the variable delta to decimal (%d) and print the
string with the converted form of delta in place of %d. The
conversions %d-decimal, %o-octal, *s-string and %c-character
are allowed.
This program calls upon the function `printn'. (see section
9.1) */
printf(fmt, x1,x2,x3,x4,x5,x6,x7,x8,x9) {
extrn printn, char, putchar;
auto adx, x, c, i, j;
i= 0; /* fmt index */
adx = &x1; /* argument pointer */
loop :
while((c=char(fmt,i++) ) != `%') {
if(c == `*e')
return;
putchar(c);
}
x = *adx++;
switch c = char(fmt,i++) {
case `d': /* decimal */
case `o': /* octal */
if(x < O) {
x = -x ;
putchar('-');
}
printn(x, c=='o'?8:1O);
goto loop;
case 'c' : /* char */
putchar(x);
goto loop;
case 's': /* string */
while(c=char(x, j++)) != '*e')
putchar(c);
goto loop;
}
putchar('%') ;
i--;
adx--;
goto loop;
}
/etc/bc source interm
/etc/ba interm asource rm interm
as asource mv a.out object rm asource
ld object /etc/brt1 -lb /etc/bilib /etc/brt2
a.out
sh /usr/b/rc x
automatic = external + 100.; va; 4 / lvalue of first automatic on stack x; .external / rvalue of external on stack c; 100. / rvalue of constant on stack b12 / binary operator #12 (+) b1 / binary operator #1 (=) ... va: mov (r3)+,r0 add r4,rO / dp+offset of automatic asr rO / lvalues are word addresses mov r0,(r5)+ jmp *(r3)+ / linkage between subroutines x: mov *(r3)+,(r5)+ jmp *(r3)+ c: mov (r3)+,(r5)+ jmp *(r3)+ b12: add -(r5),-2(r5) jmp *(r3)+ b1: mov -(r5),r0 / rvalue mov -(r5),r1 / lvalue asl r1 / now byte address mov r0,(r1) / actual assignment mov r0,(r5)+ / = returns an lvalue jmp *(r3)+
b103 =& b104 === b105 =!= b106 =<= b107 =< b110 =>= b111 => b120 =/
error name meaninq
$) -- {} imbalance
() -- () imbalance
*/ -- /* */ imbalance
[] -- [] imbalance
>c -- case table overflow (fatal)
>e -- expression stack overflow (fatal)
>i -- label table overflow (fatal)
>s -- symbol table overflow (fatal)
ex -- expression syntax
lv -- rvalue where lvalue expected
rd name name redeclaration
sx keyword statement syntax
un name undefined name
xx -- external syntax