How does the BCPL global vector work?
Is the global vector zero-initialized (or something) with a fixed size at the beginning of program execution?
If the global vector is unbounded in size and new global definitions can be dynamically added, how do we prevent the vector from "bumping into" other bits of global data?
I'm interested in understanding how this worked originally in BCPL and how it works now in the updated BCPL distribution if that is substantially different.
BCPL is an old language that predates C. It has a manual here.
The key differences from C are that it is typeless (aside from the FLT
directive in modern versions) and that it has a global array of shared values as the sole means of sharing functions between translation units.
In the BCPL manual on page 37 by internal numbering (47 by pdf numbering), we have the following example code (with comments inserted).
// demohdr
GET "libhdr"
GLOBAL { f : 200 }
// demolib.b
GET "demohdr"
LET f(...) = VALOF {
...
}
// demomain.b
GET "demohdr"
LET start() BE {
f(...)
}
The language is typeless, so in all cases f
is just a {16,32,64}-bit word.
This all makes sense, at runtime it's just a pointer to a function (I think that would just be a pointer inside some text segment somewhere).
The manual includes the following description which suggests to me that portions of the global vector may be replaced at runtime in an ad hoc way, and potentially suggests that the global vector can grow without bound.
Although the global vector mechanism has disadvantages, particularly in the organisation of library packages, there are some compensating benefits arising from its extreme simplicity. One is that the output of the compiler is available directly for execution without the need for a link editing step. Sections may also be loaded and unloaded dynamically during the execution of a program using the library functions
loadseg
andunloadseg
, and so arbitrary overlaying schemes can be organised easily.