Vn 3.02 5-January-2016

BCPL under Windows

This document provides a guide to installing the environment necessary to compile and run Robert Nordier's 'Classic BCPL' compiler distribution kit under Windows (XP/W7).  This Windows port of  Martin Richards'  BCPL compiler dating from the early 1970s produces executable programs (.exe files) which will run in native mode under Windows, without need for an intermediate VirtualBox unix system or Windows Cygwin installation.

This kit includes three much more recent, extended, versions of the BCPL compiler (dated 16-June-2004 ,[BCPL 2006-06-16] 13-Aug-2014 [BCPL 2014-08-13] and 17-May-2013 [X-BCPL 2013-05-17]).

A further early version of the compiler, oBCPL, chronologically a little later than the 'Classic BCPL' compiler, and which produces OCODE as its output rather than INTCODE (and hence has a rather different assembler generator again written by Robert Nordier), is available as a separate kit and is documented as 'Ocode BCPL Under Windows'.  (The output, library and OS interface modules of this compiler variant are loader-compatible with the output modules of the SIAL assembler present in this package).

Disclaimer

This is a 'work in progress'.  While it appears to function correctly, bugs may appear which will hopefully be fixed, and things which presently work may be changed to improve them - See 'Bug Fixes & Changes'

While nothing has been engineered into this kit which is intended to harm your PC or its files I have to state that this is free software.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Dave Cannon
D.Cannon(at)ex.ac.uk



0.    Contents

  1. Tools Required
  2. Why do I Need All This Stuff?
  3. One Step at a Time
    1. The BCPL KIt
    2. The GNU Compiler, Assembler and Loader
      1. GNU Loader Script Files
    3. The GNU 'make' utility
    4. The GNU CoreUtils Package
    5. The GNU util-linux-ng Package - 'getopt'
  4. Compile the Compiler!
  5. And now to BCPL...
  6. Write Your First BCPL Program
  7. Compile and Run it
    1. Other BCPL Programs
    2. Writing Your Own Code - Command-line Input
    3. The BCPL.cmd Script
  8. Notes on the Compiler
  9. Bug Fixes & Changes
  10. Known Bugs
  11. The Current BCPL Compiler...
  12. Acknowledgements

1.    Tools Required


2.    Why do I Need All This Stuff?

Firstly, you're going to compile the BCPL compiler - which is written in BCPL - so you'll need some tools to do that.

Secondly, no compiler runs without a way of talking to the user's screen or to files on disk, or without input from, say, the user's keyboard.  Equally, the programs created by the compiler need to do the same, otherwise their function is pretty limited.  Access to all these i/o facilities is granted, provided and policed by the operating system, in our case Windows.  This Windows port of Classic BCPL uses the c run-time library as an intermediary between BCPL's i/o requirements and the Windows application program interface (API) to those services - mostly because the c library API is much simpler than the Windows API - so we need to install c and some ancillary programs.  This is a Good Thing:  in addition to a functioning BCPL compiler you will also have available to you a c compiler, an assembler, a link loader, a swathe of Unix shell tools and the Code::Blocks integrated development environment!


3.    One Step at a Time

3.1    The BCPL Kit

First, download the Windows Classic BCPLkit.zip to a suitable folder on your PC, BCPL perhaps, and expand/unzip it.  This should create a folder called 'BCPLkit' containing a number of subfolders and files.  This is the BCPL compiler kit for Windows.

3.2    The GNU Compiler, Assembler and Loader

Next, download and install the GNU c compiler, assembler and loader packages.  I'm advised that identifying and installing a compatible set of these programs is non-trivial, however, there's an easy way to achieve this by downloading and installing the Code::Blocks IDE (Integrated Development Environment), which is itself built over the GNU development software.  Go to the Code::Blocks download page, select the operating system of your choice (Windows 2000/XP/Vista/7) and download the current installation .exe file from the server of your choice.

Over the years I've found two things useful:

  1. Create a folder for your installation downloads, keep and run them from there
  2. Don't second-guess the preferred installation targets of your installers.  Your preference might seem brilliant, but you'll need to remember what it was when the package gets updated, and everything that follows on from here will need to be adjusted to accept your preferred target...

There's a useful video guide, "How to install GCC compiler in Windows XP/Vista/7" on YouTube to follow here.

Once you have the Code::Blocks IDE installed, following the guide above, it's essential to check that the gcc compiler is now accessible from whereever you installed the BCPL source files (on my Windows 7 system this is "C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.6\src").  To do this, open a 'Command Prompt' window (Windows Start button, click 'run' if on XP, type 'cmd' in the search box, then double-click 'cmd.exe' in the list if on W7).  In the Command Prompt dialog box that appears, type:

gcc --version
and you should see something like...
gcc (tdm-1) 4.7.1
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

If you get:
'gcc' is not recognized as an internal or external command,
operable program or batch file.
then you need to check that you typed the path of the gcc compiler correctly into your computer's Environment Variables 'Path' setting.  If necessary, watch the video again.  A common error is to omit or confuse colons (:) and semi-colons (;).

3.2.1    GNU Loader Script Files


The GNU link-loader, ld, needs to be provided with a script file in order to search the correct locations for c library files during the link phases of building the compiler and any BCPL programs - by default it would search folders only present on a Unix system.  A choice of script files is provided in the distribution C:[...]\BCPL\BCPLkit\bcplkit-0.9.6\loader scripts directory.

As with 'Compiling the Compiler' (below) you should first choose which of:
i386pe_mg64.x    (for a 64-bit [Windows 7] installation) or
i386pe_mg32.x      (for a 32-bit Windows installation)
best suits your system.  Copy your chosen script file to either C:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts (on a 64-bit [Windows 7] installation) or to C:\Program Files\CodeBlocks\MinGW\mingw32\lib\ldscripts (on a 32-bit Windows installation) and then rename this file to i386pe_mgw.x.  You will have identified the first part of these pathnames when modifying your Windows Environment Variables above.

If your installation varies from standard you will need to identify the differences and edit a loader script file to suit the pathnames on your system.

3.3    The GNU 'make' Utility

If you're familiar with reading Makefiles you might consider skipping this step, but the BCPL Makefile is lengthy.  You will probably want to make and re-make the BCPL compiler a number of times, and doing this by hand will become tedious - and errorprone.  'make' solves all these issues.

Download the 'make' 'Setup' Complete package, except sources, from the GNUWin32 server, and run it to install it.  Again, don't second-guess the installation target.  Once you've done this you must modify your Windows Environment Variables 'Path' setting as you did for the GNU compiler package, but this time for the location of the GNU 'make' executable.  On a Windows 7 system this is normally:
C:\Program Files (x86)\GnuWin32\bin
while on a Windows XP system it is:
C:\Program Files\GnuWin32\bin
Close and reopen your Command Prompt window (to collect your modified path Environment Variable), and check your path, by typing:
make --version
and you should see, for example...
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-pc-mingw32
Again, if you get:
'make' is not recognized... etc
then your path is wrong or missing.  It must work before you go further.

3.4    The GNU CoreUtils Package

Nearly there!  As before, if you're willing to read and interpret the BCPL compiler Makefile yourself, you could omit this step, but the same arguments apply as above.  It's easier this way!  Go to the GNU CoreUtils page and download the Setup program of the package into your downloads folder, and install it.  If you haven't overridden the preferred installation defaults this time there's no need to amend your Environment Variables 'Path' setting again - all the core utilities will cohabit the folder that 'make' is in, so if in your Command Prompt window you type:
ls --version
you will see...
ls (GNU coreutils) 5.3.0
Written by Richard Stallman and David MacKenzie.

Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


3.5    The GNU util-linux-ng Package - 'getopt'

...one more thing:  the included BCPL.cmd scripts make use of a command-line argument parser called getopt.  Go to the GNU util-linux-ng for Windows page and download the "Complete package, except sources" Setup program into your downloads folder, and install it.  Again, this will go into your 'make' and 'core utilities' folder, so no further work is needed.  You can test the theory by typing:

getopt --version
and you should see...
getopt (enhanced) 1.1.4
If you're remotely familiar with Unix systems, you now have available to you a fully functioning subset of Unix shell commands - and, if you're interested, others are readily available on the GNUWin32 site - all you need to do is download and install them.


4.    Compile the Compiler!

We're there.  In your Command Prompt window, go to the location that your BCPL compiler kit files were unzipped to (this is "C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7" on my system, but only the bold part is likely to be replicated on your system).

So, type:

cd  C:[...]\BCPL\BCPLkit\bcplkit-0.9.7

In this folder you'll see a selection of folders and files, these being the parts of the BCPL compiler, and crucially two DOS command files to build the compilers themselves:

BCPLenv.cmd
Makeall.cmd

If you need to change the contents of either of these files - or anything else in this package - you'll need a competent editor.  My preference is the Notepad++ editor, which - if you're interested - you'll find if you search the web...

BCPLenv
is a simple command file to establish the environment necessary to build and run the BCPL compilers and programs in this package.  You MUST execute it from the directory you find it in - DO NOT move it anywhere else!  When you type...
BCPLenv
...you should see something like the following on a Windows 7 system:
BCPL environment established as:
BCPLcopt=C:\Users\Dave\Apps\BCPL\BCPLkit\copt
BCPLdir=BCPLkit-0.9.7
BCPLenv=Vn 1.03 3-Jan-2016
BCPLhdrs=C:\Users\Dave\Apps\BCPL\BCPLkit\include
BCPLlib=C:\Users\Dave\Apps\BCPL\BCPLkit\BCPL 2006-06-16
BCPLocd=C:\Users\Dave\Apps\BCPL\BCPL-0.9.8
BCPLroot=C:\Users\Dave\Apps\BCPL\BCPLkit
BCPLsrc=C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src
MCPLhdrs=C:\Users\Dave\Apps\BCPL\BCPLkit\include
GnuWin=C:\Program Files (x86)\CodeBlocks\MinGW
minGWVn=4.7.1

Now you can build the BCPL compilers, and various BCPL programs which form this distribution package.

Type
makeall
and you should see the following output scroll up your Command Prompt window:

        ________ "copt" _________
gcc  -o copt copt.c

        ________ "BCPLkit-0.9.7\src" _________
as  -o su.o su.s
gcc  -c icint.c
gcc  -c blib.c
gcc  -o icint icint.o blib.o
cat iclib0.i blib.i syn.i trn.i >st0.int
cat iclib0.i blib.i cg.i >cg0.int
icint st0.int <xgV128.b
INTCODE SYSTEM ENTERED

PROGRAM SIZE = 12346

BCPL 2
OPTIONS  L10500

TREE SIZE 7112

PHASE 1 COMPLETE

EXECUTION CYCLES = 2712730, CODE = 0
icint cg0.int <OCODE
INTCODE SYSTEM ENTERED

PROGRAM SIZE = 5299

PROGRAM LENGTH = 4092

EXECUTION CYCLES = 2134427, CODE = 0
mv INTCODE xg.i
cat iclib0.i blib_classic.i xg.i >xg0.int
icint xg0.int <xg0.int
INTCODE SYSTEM ENTERED

PROGRAM SIZE = 4207

EXECUTION CYCLES = 6725227, CODE = 0
mv ASM xg0.s
as  -o xg0.o xg0.s
as  -o rtc.o rtc.S
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o xg0.exe su.o xg0.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"
icint xg0.int <st0.int
INTCODE SYSTEM ENTERED

PROGRAM SIZE = 4207

EXECUTION CYCLES = 19037105, CODE = 0
mv ASM st0.s
as  -o st0.o st0.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o st0.exe su.o st0.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"
icint xg0.int <cg0.int
INTCODE SYSTEM ENTERED

PROGRAM SIZE = 4207

EXECUTION CYCLES = 8486255, CODE = 0
mv ASM cg0.s
as  -o cg0.o cg0.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o cg0.exe su.o cg0.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"
st0 < xgV129.b

BCPL 1067019
OPTIONS  L10500

TREE SIZE 7112

PHASE 1 COMPLETE
cg0 < OCODE

PROGRAM LENGTH = 4092
cat iclib0.i blib_classic.i INTCODE >xg1.int
xg0 <xg1.int
mv ASM xg1.s
as  -o xg1.o xg1.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o xg1.exe su.o xg1.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"
st0 < syn.b

BCPL 1067019
OPTIONS  L10500

TREE SIZE 4120

TREE SIZE 5739

TREE SIZE 5188

TREE SIZE 4258

TREE SIZE 5094

TREE SIZE 4382

TREE SIZE 4929

TREE SIZE 4381

TREE SIZE 4958

PHASE 1 COMPLETE
cg0 < OCODE

PROGRAM LENGTH = 6799
cat iclib0.i blib.i INTCODE >st1.int
st0 < trn.b

BCPL 1067019
OPTIONS  L10500

TREE SIZE 4735

TREE SIZE 5316

TREE SIZE 5124

TREE SIZE 4639

TREE SIZE 4975

TREE SIZE 4571

TREE SIZE 5053

PHASE 1 COMPLETE
cg0 < OCODE

PROGRAM LENGTH = 4476
cat INTCODE >>st1.int
xg0 <st1.int
mv ASM st1.s
as  -o st1.o st1.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o st1.exe su.o st1.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"
st0 < cg.b

BCPL 1067019
OPTIONS  L10500

TREE SIZE 4518

TREE SIZE 3424

TREE SIZE 5028

TREE SIZE 3932

TREE SIZE 3916

PHASE 1 COMPLETE
cg0 < OCODE

PROGRAM LENGTH = 2922
cat iclib0.i blib.i INTCODE >cg1.int
xg0 <cg1.int
mv ASM cg1.s
as  -o cg1.o cg1.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o cg1.exe su.o cg1.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"
st1 < syn.b

BCPL 1068376
OPTIONS  L10500

TREE SIZE 4130

TREE SIZE 5749

TREE SIZE 5198

TREE SIZE 4268

TREE SIZE 5104

TREE SIZE 4392

TREE SIZE 4939

TREE SIZE 4391

TREE SIZE 4968

PHASE 1 COMPLETE
cg1 < OCODE

PROGRAM LENGTH = 6799
cat iclib0.i blib.i INTCODE >st.int
st1 < trn.b

BCPL 1068376
OPTIONS  L10500

TREE SIZE 4745

TREE SIZE 5326

TREE SIZE 5134

TREE SIZE 4649

TREE SIZE 4985

TREE SIZE 4581

TREE SIZE 5063

PHASE 1 COMPLETE
cg1 < OCODE

PROGRAM LENGTH = 4476
cat INTCODE >>st.int
xg1 <st.int
mv ASM st.s
as  -o st.o st.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o st.exe su.o st.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"
st1 < cg.b

BCPL 1068376
OPTIONS  L10500

TREE SIZE 4528

TREE SIZE 3434

TREE SIZE 5038

TREE SIZE 3942

TREE SIZE 3926

PHASE 1 COMPLETE
cg1 < OCODE

PROGRAM LENGTH = 2922
cat iclib0.i blib.i INTCODE >cg.int
xg1 <cg.int
mv ASM cg.s
as  -o cg.o cg.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o cg.exe su.o cg.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"
st1 < xg.b

BCPL 1068376
OPTIONS  L10500

TREE SIZE 9410

PHASE 1 COMPLETE
cg1 < OCODE

PROGRAM LENGTH = 5616
cat iclib0.i blib.i INTCODE >xg.int
xg1 <xg.int
mv ASM xg.s
as  -o xg.o xg.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o xg.exe su.o xg.o rtc.o -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"

        ________ "BCPLkit-0.9.7\util" _________
..\src\bcpl bgpm.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 5510

PHASE 1 COMPLETE

PROGRAM LENGTH = 1856
..\src\bcpl cmpltest.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 6017

PHASE 1 COMPLETE

PROGRAM LENGTH = 1823
..\src\bcpl gpm.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 5424

PHASE 1 COMPLETE

PROGRAM LENGTH = 1977
..\src\bcpl hanoi.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 591

PHASE 1 COMPLETE

PROGRAM LENGTH = 78
..\src\bcpl hello.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 1948

PHASE 1 COMPLETE

PROGRAM LENGTH = 25
..\src\bcpl mlisp.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 10163

PHASE 1 COMPLETE

PROGRAM LENGTH = 5026
..\src\bcpl reftest.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 2046

PHASE 1 COMPLETE

PROGRAM LENGTH = 79
..\src\bcpl testb.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 2344

PHASE 1 COMPLETE

PROGRAM LENGTH = 424
..\src\bcpl xgtest.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 2043

PHASE 1 COMPLETE

PROGRAM LENGTH = 39
..\src\bcpl xref.b

BCPL 1068376
OPTIONS  L12000

TREE SIZE 6677

PHASE 1 COMPLETE

PROGRAM LENGTH = 2221

        ________ "BCPL 2006-06-16" _________
cp libhdr+ libhdr
"C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\bcpl" xg_i.b

BCPL 1068376
OPTIONS  L17500

TREE SIZE 10411

PHASE 1 COMPLETE

PROGRAM LENGTH = 6445
cp libhdr+ libhdr
"C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\st" < syn.b

BCPL 1068376
OPTIONS  L17500

TREE SIZE 8269

TREE SIZE 10777

TREE SIZE 7177

PHASE 1 COMPLETE
"C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\cg" < OCODE

PROGRAM LENGTH = 7732
mv INTCODE syn.i
cp libhdr+ libhdr
"C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\st" < trn.b

BCPL 1068376
OPTIONS  L17500

TREE SIZE 10222

TREE SIZE 6008

TREE SIZE 9856

PHASE 1 COMPLETE
"C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\cg" < OCODE

PROGRAM LENGTH = 7903
mv INTCODE trn.i
cp libhdr+ libhdr
"C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\st" < cg.b

BCPL 1068376
OPTIONS  L17500

TREE SIZE 6200

TREE SIZE 6603

TREE SIZE 7489

TREE SIZE 6697

TREE SIZE 7154

PHASE 1 COMPLETE
"C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\cg" < OCODE

PROGRAM LENGTH = 3058
mv INTCODE cg.i
cat "C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\iclib.i" "C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\blib.i" syn.i trn.i cg.i > bcpl+.i
"C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\xg" < bcpl+.i
mv ASM bcpl+.s
as  -o bcpl+.o bcpl+.s
ld -Bdynamic "-TC:\Program Files (x86)\CodeBlocks\MinGW\mingw32\lib\ldscripts\i386pe_mgw.x" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\crt2.o" "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtbegin.o" -o bcpl+.exe "C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\su.o" bcpl+.o "C:\Users\Dave\Apps\BCPL\BCPLkit\bcplkit-0.9.7\src\rtc.o" -lmingw32 -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 "C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\4.7.1\crtend.o"

        ________ "BCPL 2014-08-13" _________
"C:\Users\Dave\Apps\BCPL\BCPLkit\BCPL 2006-06-16\bcpl" -o bcpl+ bcpl.b

BCPL (16 June 2004)
bcpl: calling findinput(bcpl.b)
bcpl: calling findinput(bcpl.b)=>3
Code size = 108019 bytes
Code size = 18338 bytes

        ________ "X-BCPL 2013-05-17" _________
"C:\Users\Dave\Apps\BCPL\BCPLkit\BCPL 2014-08-13\bcpl" -o xbcpl xbcpl.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 107449 bytes
Code size = 18338 bytes

        ________ "BCPL 2014-08-13\sial" _________
..\bcpl bcpl2sial.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 106081 bytes
Code size = 45442 bytes
..\bcpl sial-386.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 58566 bytes
..\bcpl sial-386_w.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 55322 bytes
..\bcpl sial-sasm.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 14068 bytes
..\bcpl sial-arm.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 45723 bytes

        ________ "BCPL 2014-08-13\util" _________
..\bcpl bcplxref.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 15832 bytes
..\bcpl byteop.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 708 bytes
..\bcpl enigma.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 3526 bytes
..\bcpl mlisp.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 27487 bytes
..\bcpl procode.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 9189 bytes
..\bcpl test.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 862 bytes
..\bcpl xref.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 11592 bytes

        ________ "BCPL 2014-08-13\mial" _________
..\bcpl mcpl2mial.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 44969 bytes
Code size = 44410 bytes
Code size = 40966 bytes
Code size = 3743 bytes
..\bcpl mial-386_w.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 46544 bytes
..\bcpl prmcode.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 7121 bytes
..\bcpl prmial.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 13434 bytes

        ________ "BCPL 2014-08-13\mcpl" _________
..\bcpl mcpl2mial.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 44969 bytes
Code size = 44410 bytes
Code size = 40966 bytes
Code size = 3743 bytes
..\bcpl mial-386_w.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 46544 bytes
..\bcpl mial-386.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 47484 bytes
..\bcpl mial-masm.b

BCPL (13 Aug 2014) with simple floating point
INTCODE 32 CG (23-October-2013)
Code size = 13169 bytes

        ________ "BCPL 2014-08-13\mcpl\util" _________
..\mcpl hello.m

MCPL2MIAL 8 July 1997

Tree size 2555
CG2MIAL 20 May 1997
Program size = 34 Fcodes
Converting hello.mial to hello.s
Conversion complete
..\mcpl primes.m

MCPL2MIAL 8 July 1997

Tree size 2748
CG2MIAL 20 May 1997
Program size = 148 Fcodes
Converting primes.mial to primes.s
Conversion complete


If you did, you now have a Classic BCPL compiler, running under Windows, together with three later versions of the BCPL compiler and a set of source and compiled BCPL programs!

 If you saw an error message, typically from 'make', you'll need to check at what point the build failed, and attempt to correct the problem.  It will probably be a broken path to one of the components.  If all else fails, feel free to contact me with as full a trace as possible of what happened - I'll try to help, if I can.


5.    And now to BCPL...

So, how to use the compiler?  If you take a look in your BCPLkit-0.9.7\src folder you'll see you now have a set of (32-bit) executable programs of various sizes:
60,032
cg.exe
58,496
cg0.exe
58,496
cg1.exe
36,213
icint.exe
98,432
st.exe
93,824
st0.exe
98,432
st1.exe
64,128
xg.exe
51,328
xg0.exe
51,328
xg1.exe

A subset of these make up the BCPL compiler - st.exe is the syntax analyser and translator, producing OCODE, cg.exe is the code generator, producing INTCODE, and xg.exe is Robert Nordier's assembler generator, producing an assembler source file which is input to the GNU 'as' program to create Windows-compatible executables.  There's a DOS command file, bcpl.cmd, in the ...\src folder to make it easier to use these.


6.    Write Your First BCPL Program

This part's even easier, it's already been done for you.  The archetypal first BCPL program is 'hello.b', consisting of:
    get "libhdr"
    let start () be
        writes ("Hello, World*n")

7.    Compile and Run it

A copy of hello.b is in the 'C:[...]\BCPL\BCPLkit\bcplkit-0.9.7\util' directory, so, assuming your Command Prompt window is still in the '...\src' directory, type:
cd ..\util
and then type:
..\src\bcpl hello.b
(the '..\src\'... part is needed because the Windows script, 'bcpl.cmd' is not in the Windows 'path' Environment Variable - but you know how to fix that...)  This should output the following...
BCPL 1068376
OPTIONS  L12000

TREE SIZE 1948

PHASE 1 COMPLETE

PROGRAM LENGTH = 25

and if you then type:
hello
you should see:
Hello, World

7.1    Other BCPL Programs

The ...\util folder contains a number of more interesting programs written in BCPL, all of which should compile and run under Windows, including:
bgpm.b a later version of Christopher Strachey's GPM package (see below).  Some usage guidance is offered in the file: bgpm_readme.txt
cmpltest.b to run checks on the compiler output
gpm.b an implementation of Christopher Strachey's GPM macro language parser.  Some usage guidance is offered in the file: gpm_readme.txt
hanoi.b Amit Singh's solution of the Towers of Hanoi problem for five discs.
mlisp.b A C Norman's mini-lisp implementation (after compilation, try mlisp mlispdemo.l)
reftest.b a 'call-by-reference' test program
testb.b a test program which reads and lists items on its command line, and ends by calling MAPSTORE() to output the Global vector, the file table, and the BCPL stack
xgtest.b a test of the use of a globally defined GOTO statement
xref.b a BCPL source code cross-referencer (after compiling it, try xref < xref.b)

The included Makefile will compile all of the above - the usual caveats apply regarding your system and your installation.

If you're interested in macro processors, a BCPL implementation of Peter Brown's ML/1 is available as a separate download package: ML1.zip, and offers a thorough test of this compiler.  Extensive documentation on ML/1, its origins, implementations and test macros, are available on Bob Eager's official ML/1 site.

7.2    Writing Your Own Code - Command-line Input

BCPL was designed to be portable, so its reliance on the host Operating System services are minimal, being limited to twelve i/o requests and half a dozen system services (eg STOP() ).  These are all fairly straightforward to implement.  One facility which is undefined and therefore different on almost every BCPL port is how command-line arguments are passed through to the user's program.

The Windows BCPL port is built over the GNU c runtime API, and it seemed natural to pass c's concept of argv and argc through to the user's program - this is a fairly light touch approach where command-line arguments are separated by spaces, and each item on the argument list is passed by address to the BCPL START routine, with the number of arguments passed in argc.  The program 'testb.b' offers an example of its use:

LET start(argv, argc) BE
$(
...
FOR pct = 0 TO argc-1 DO
        WRITEF("argv!%n=%n (%s)*N", pct, argv!pct, argv!pct)
...
$)
When executed as:
testb this is a test
the program will output (amongst other things)...
Test command line args and dynamic vectors...
argv=2737088, argc=4

argv!0=2737096 (this)
argv!1=2737100 (is)
argv!2=2737104 (a)
argv!3=2737138 (test)
...

Note that every argument offered is passed through to the program as a (BCPL) text string - numbers are NOT converted to their value.  Equally spaces are the only recognised delimiter between arguments, so if you wish to perform your own argument parsing, you could use a non-space delimiter, for example comma (so: myprog arg1,arg2,longarg3) or you could enclose the whole set of arguments in quotes, eg myprog "arg1 arg2 longarg3".  In either case you will receive just one argument string.

Alternatively, blib.b, (the BCPL run-time library) offers a simple version of RDARGS() which will convert numeric arguments to their value and leave other arguments as BCPL strings - see blib.b for details.

7.3    The BCPL.cmd Script

As noted above, the most usual use for the BCPL.cmd script is 'bcpl myprog.b' to create 'myprog.exe', but typing...
bcpl
without arguments will list additional features - these are currently:
Usage:  ..\src\bcpl [-Options] [-o output] file
        where   file is a BCPL source program to be compiled
                [-o output] (optional) specifies the compiled program name
                [-Options] may be any of:
                [-O] (optional) invokes the copt code optimiser
                [-c] (optional) preserve OCODE output as 'file.ocd'
                [-i] (optional) preserve INTCODE output as 'file.i'
                [-l] (optional) preserve the 'file.o' output for ld
                [-S] (optional) preserve the 'file.asm' output

        ..\src\bcpl Vn 1.08     20-Aug-2014

If you're interested in the various intermediate stages of the creation of your executable, or you wish to optimise its code, there's an option to do it.

8.    Notes on the Compiler

This distribution package, BCPLkit.zip, is Robert Nordier's Classic BCPL kit, with a few extensions.  Classic BCPL accepted only uppercase characters, largely because the input devices of 1967/68 were Teletypes which handled only uppercase characters - though on the plus side they could read 5-track punched paper tape...   These days most keyboards default to lowercase so, to save finding that Caps Lock key, the BCPL compiler has been amended to accept BCPL reserved words, labels and variables in lowercase as well as the uppercase alternative - hence the 'hello.b' source program (above) is accepted by the compiler.

A slightly later (~1970?) development of BCPL allowed 'vectors' (arbitrary length word arrays) to be allocated and freed from 'heap' memory, using the v := GETVEC(n) and FREEVEC(v) calls.  These have also been implemented (using the underlying c library 'malloc' call) in this distribution, and a number of further additions have been made to allow the compiler to handle the current incarnation of the language (and hence compile the latest version of the compiler - see 9.    Bug Fixes & Changes for details).


If you prefer to experience Classic BCPL without these embellishments, go to the '..\src' directory, copy Makefile_Classic to Makefile then type:
make
to recompile the compiler using the original Classic BCPL source files.


9.    Bug Fixes & Changes

NB:  These changes/fixes are NOT included in the .._classic.x files (see 'Notes on the Compiler', above), except where noted.

5-January-2016:
Edits to this file to clarify loader script installation
3-January-2016:
Bug fixes to the BCPLenv script to correctly identify the Code::Blocks home directory on most systems
30-October-2015:
Introduction of BCPLenv script, to establish the environment for the makefiles, compiler and programs
13-August-2015:
Replacement of Martin Richards' 30-April-2014 compiler with his 13-August-2014 version
19-June-2014:
Inclusion of Martin Richards' 30-April-2014 compiler
31-December-2013:
tm := time() support added to rtc.S (tm is the c tm struct) and timeofday(), date() added to blib.b
18-November-2013:
stream := findfile("filename", "mode") added to rtc.S and 'libhdr', where "mode" may take any of the modes in the forms permitted by the c  library 'fopen()' call.
11-November-2013:
Code and assembler generators for the xbcpl compiler (see below) revised to handle field selector operations (SELLD, SELST), as in:
          <constant expression>  ::=  SLCT <size>:<shift>:<offset> |  SLCT <size>:<shift> |  SLCT <size>
and thus
          F OF P := E, where the appropriate number of bits from the right hand end of expression E are assigned to the specified field F
26-October-2013:
A tidy-up release:
  • Common modules moved to the 'include' directory (see BCPLHDRS below)
  • Routine names passed through the INTCODE and assembler phases to aid debugging
  • ENDSTREAM(streamno), to close the nominated input or output stream, added to blib.b and LIBHDR files
24-October-2013:
Code and Assembler generators revised to correctly encode a%<non-trivial expression> := b
4-October-2013
Code added to blib.b to support a limited version of rdargs(), handling command-line parameters, and trap(), which catches attempts to call undefined GLOBALs
19-August-2013:
All Makefiles and BCPL.cmd scripts updated to use the gcc Vn 4.7.1 c compiler, assembler and loader.  (Was 4.4.1)
18-August-2013:
SYSERR (error output listing) is now pre-opened during BCPL initialisation and can be selected at runtime using the MANIFEST constant SYSERR, as listed in 'libhdr'
14-August-2013:
Incorporation of Robert Nordier's current xg.b assembler generator, 2012.  (Vn401, 2013/08/09 21:34:16, in this distribution)
11-March-2013: Correction to 'xg.b's encoding of the infix byte operator '%', when used in a non-trivial statement such as string%(index+count) := bytevalue.  This failed to collect the required bytevalue from the BCPL stack.
10-February-2013: Fix to PATHFINDINPUT() to accept <path> specified as 0 (zero)
GETENV(<environment name>) added to 'rtc.S', 'blib.b' and 'libhdr' to support PATHFINDINPUT()
9-February-2013: PATHFINDINPUT() support added to 'rtc.S', 'blib.b' and 'libhdr'.  Later versions of the compiler use this to resolve GET "<filename>" requests in BCPL programs.  PATHFINDINPUT(<filename>, <path>) searches in the following sequence:
  1. in the local directory - a matching <filename> here thus overrides any in the nominated library directory
  2. in the directory search tree specified by the environment variable '<path>', if any - this might be:
    "BCPLHDRS", where the environment variable BCPLHDRS=C:\Program Files\CodeBlocks\MinGW\include, for example
  3. a built-in library directory specifier, currently: \Users\Dave\Apps\BCPL\BCPLkit\include
1-February-2013:
Added RENAME() and DELETE() file support to 'rtc.S', 'blib.b' and 'libhdr'
MAPSTORE() now accepts an optional argument to list the nominated number of GLOBAL vector items - default is 100
30-January-2013: Added ENDTOINPUT() support to 'rtc.S', 'blib.b' and 'libhdr'
Added ABORT() support to 'rtc.S', 'blib.b' and 'libhdr'
29-January-2013: Added FINDAPPEND() support to 'rtc.S', 'iclib.i' and 'libhdr'
Split STACKTRACE() from MAPSTORE() in 'blib.b'
27-January-2013: fix to xg.b (and xg_i.b) to translate the BCPL 'SECTION' directive to an assembler '.title' directive.  The assembler '.section' directive causes code to be inaccessible...
7-January-2013: fix to unrdch() in rtc.S - NB: this fix also applies to the 'Classic BCPL' build
6-January-2013:
syn.b modified to support the '~' (NOT) operator
22-December-2012: Mods throughout to support the ABS operator
20-December-2012: Mods throughout to support the 'SECTION' directive
20-December-2012:
Mods throughout to support the infix byte operator '%', so 'x := getbyte(vec, 3)' becomes 'x := vec%3' and 'putbyte(vec, 10, 'z')' becomes 'vec%10 := 'z''
19-December-2012:
syn.b and trn.b modified to allow '?' to be used in initialisation of variables, TABLE data, etc.
9-December-2012: syn.b modified to allow '{' and '}' as alternatives to the section brackets '$(' and '$)'.  NB - '{' and '}' may not be tagged.
6-December-2012: Mapstore() implemented in blib.b
5-December-2012: Global limit increased from 100 to 350 in trn.b
5-December-2012: Cleared bug in call to GETVEC() which limited requested space to ~8000 words.  This bug in the argument passing mechanism may also have affected other calls supported by the GNU c runtime system.
2-December-2012: Fix to xg.b to handle the INTCODE phrase 'JIGxyz', where xyz is a global number, which occurs where a program includes 'GOTO fred' and fred is declared as a global.
28-November-2012:
Constant limit increased from 4000 to 7500 in cg.b
27-October-2012:
Name limit increased from 1200 to 2200 in trn.b
3-October-2012: Mods throughout to support GETVEC() and FREEVEC() memory requests
28-September-2012:
syn.b modified to accept BCPL reserved words, labels and variables in lowercase

10.    Known Bugs

...as of:
Issue
26-October-2013: 'bcplcgint_i.b' (the INTCODE code-generator module) does not handle the floating point operations introduced in the XBCPL compiler variant, the version here dated 17-May-2013 (see below).  Code to be added to both 'bcplcgint_i.b' and 'xg_i.b' to recognise and generate appropriate assembler.
Workaround: none

11.    The Current BCPL Compiler...

BCPL has moved on from the version presented here as 'Classic BCPL'.  Martin Richards' web pages detail its current incarnation, and three versions are also present in this package.

Following the successfull build of the 'extended' version of the Classic BCPL compiler, detailed above, Makeall should have gone on to build three later generations of the BCPL compiler, capable of creating Windows executable programs conforming to the then current specification of the language.  The  'BCPL 2006-06-16',  'BCPL 2014-08-13' and 'X-BCPL 2013-05-17' subdirectories should contain, respectively, the 16-June-2006, the 13-August-2014 and the 17-May-2013 versions of the BCPL and XBCPL compilers.  These in turn are capable of creating 32-bit Windows executables from BCPL source programs.

The 'ReadMe.txt' file in the 'BCPL 2006-06-16' directory details the status of, and issues with, these versions.


12.    Acknowledgements

Along with much of the 21st century world, I'm indebted to Martin Richards, for conceiving and creating BCPL, including his much updated and extended versions included here, and to Robert Nordier for his work in making available the Classic BCPL porting kit in a way that enthused me to try a Windows version.  The vast content of this port is due to their effort, and remains their copyright.


Dave Cannon
January 2016