The BCPL Cintsys and Cintpos User Guide by Martin Richards mr@cl.cam.ac.uk http://www.cl.cam.ac.uk/users/mr10/ Computer Laboratory University of Cambridge Revision date: Wed Jan 14 10:46:33 GMT 2015 Abstract BCPL is a simple systems programming language with a small fast compiler which is easily ported to new machines. The language was first implemented in 1967 and has been in continuous use since then.
Contents Preface v 1 The System Overview 1.1 A Cintsys Console Session . . . . . . . . . . . . . . . . . . . . . . 1.2 A Cintpos Console Session . . . . . . . . . . . . . . . . . . . . . . 1 1 7 2 The BCPL Language 2.1 Language Overview . . . . . . . . . . . 2.1.1 Comments . . . . . . . . . . . . 2.1.2 The GET Directive . . . . . . . . 2.1.3 Conditional Compilation . . . . 2.1.4 Section Brackets . . . . . . . . 2.2 Expressions . . . . . . . . . . . . . . . 2.2.1 Names . . . . . . . . . . . . . . 2.2.
ii CONTENTS 2.5 2.6 2.4.1 Labels . . . . . . . . . . . . . . . . 2.4.2 Manifest Declarations . . . . . . . . 2.4.3 Global Declarations . . . . . . . . . 2.4.4 Static Declarations . . . . . . . . . 2.4.5 LET Declarations . . . . . . . . . . 2.4.6 Local Variable Declarations . . . . 2.4.7 Local Vector Declarations . . . . . 2.4.8 Function and Routine Declarations 2.4.9 Dynamic Free Variables . . . . . . Separate Compilation . . . . . . . . . . . . The objline1 Feature . . . . . . . . . . . 3 The 3.1 3.
iii CONTENTS 4.4 cli.b and cli init.b . . . . . . . . . . . . . . . . . . . . . . . . 128 5 Console Input and Output 5.1 Cintsys console streams . . 5.2 Cintpos console streams . 5.2.1 Devices . . . . . . 5.2.2 Exclusive Input . . 5.2.3 Direct access to the . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . screen and keyboard 6 Cintpos Devices 6.0.4 The Clock Device . . . 6.0.5 The Keyboard Device 6.0.6 The Screen Device . . 6.0.7 TCP/IP Devices . . . . .
iv CONTENTS 9.2.8 9.2.9 9.2.10 9.2.11 9.2.12 9.2.13 9.2.14 9.2.15 Flow of Control and Relations Switch Instructions . . . . . . Miscellaneous . . . . . . . . . Floating-point Instructions . . Select Instructions . . . . . . Undefined Instructions . . . . Corruption of B . . . . . . . . Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Preface The concept for BCPL originated in 1966 and was first outlined in my PhD thesis [4]. Its was first implemented early in 1967 when I was working at M.I.T. Its heyday was perhaps from the mid 70s to the mid 80s, but even now it is still continues to be used at some universities, in industry and by private individuals. It is a useful language for experimenting with algorithms and for research in optimizing compilers. Cintpos is the multi-tasking version of the system based on the Tripos [5].
vi CONTENTS • The SIAL intermediate code that allows easy translation of BCPL in native code for most architectures, including, for instance, the Raspberry Pi. • The MC package that allows machine independent dynamic compilation and execution of native machine code.
Chapter 1 The System Overview This document contains a full description of an interpretive implementation of BCPL that supports a command language and low level interactive debugger. As an introduction, two example console sessions are presented to exhibit some of the key features of both the single threaded version of the system (Cintsys) and the interpretive version of Tripos (Cintpos). 1.
2 CHAPTER 1. THE SYSTEM OVERVIEW LET start() = VALOF is the heading for the declaration of the function start which, by convention, is the first function to be called when a program is run. The empty parentheses () indicate that the routine expects no arguments. The text FOR i = 1 TO 5 DO introduces a for-loop whose control variable i successively takes the values from 1 to 5.
1.1.
4 CHAPTER 1. THE SYSTEM OVERVIEW the debugger. The data word at location 4 holds a special bit pattern indicating the presence of a function name placed just before the entry point. As can be seen the name in this case is start. Similar information is packed at location 60 for the function fact. Most Cintcode instructions occupy one byte and perform simple operations on the registers and memory of the Cintcode machine.
5 1.1. A CINTSYS CONSOLE SESSION This first loads the entry point of clihook (held in global variable 4) and sets (b1) a breakpoint numbered 1 at this position. The command b, without an argument, lists the current breakpoints confirming that the correct one has been set. Normal execution is continued using the c command. * c 0.010> If we now try to execute the factorial program, we immediately hit the breakpoint.
6 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * CHAPTER 1.
1.2. A CINTPOS CONSOLE SESSION 7 This shows that the total size of the compiler is 34,576 bytes and that it can be compiled (on a 1.6GHz Pentium machine) in 0.280 seconds. Since this involves executing 28,261,599 Cintcode instructions, the rate is just over 100 million Cintcode instructions per second with the current interpreter. 1.
8 CHAPTER 1. THE SYSTEM OVERVIEW There is a benchmark program called bench100.b which can be compiled and run as follows. 0.000 1> c bc bench100 bcpl com/bench100.b to cin/bench100 hdrs POSHDRS BCPL (20 Oct 2009) Code size = 1444 bytes 0.040 1> bench100 bench mark starting, Count=1000000 starting finished qpkt count = 2326410 holdcount = 930563 these results are correct end of run 9.170 1> The latest prompt (9.170 1>) indicates that the benchmark program took 9.
9 1.2. A CINTPOS CONSOLE SESSION Notice that the root CLI (task 1) completes the execution of the run command and issues a prompt (0.000 1>) before the newly created CLI (task 7) has had time to load and run the status command. As soon as task 7 finishes running the status command it commits suicide leaving the original 6 tasks. The bounce.b program provides a demonstration of communication between Cintpos tasks work. 0.000 1> type com/bounce.
10 CHAPTER 1. THE SYSTEM OVERVIEW } task, count := 7, 1_000_000 IF argv!0 DO task := !argv!0 IF argv!1 DO count := !argv!1 pkt!0, pkt!1, pkt!2 := notinuse, task, count writef("*nSending a packet to task %n, %n times*n", task, count) { LET k = pkt!2 UNLESS k BREAK pkt!2 := k-1 qpkt(pkt) pkt := taskwait() } REPEAT writes("Done*n") } 0.010 1> This program creates a packet consisting of a vector (one dimensional array) of three elements.
Chapter 2 The BCPL Language The design of BCPL owes much to the work done on CPL (originally Cambridge Programming Language) which was conceived at Cambridge to be the main language to run on the new and powerful Ferranti Atlas computer to be installed in 1963. At that time there was another Atlas computer in London and it was decided to make the development of CPL a joint project between the two Universities. As a result the name changed to Combined Programming Language.
12 CHAPTER 2. THE BCPL LANGUAGE variant of GPM, called BGPM, is included in the standard BCPL distribution. BCPL was initially similar to this subset of CPL used in the encoding of the CPL compiler. An outline of BCPL’s main features first appeared in my PhD thesis [4] in 1966 but it was not fully designed and implemented until early the following year when I was working at Project MAC of the Massachussetts Institute of Technology.
2.1. LANGUAGE OVERVIEW 2.1.2 13 The GET Directive A directives of the form GET "filename" is replaced by the contents of the named file. Early versions of the compiler only inserted the file up to the first occurring dot but now the entire file is inserted. By convention, GET directives normally appear on separate lines. If the filename does not end in .h or .b the extension .h is added.
14 2.1.4 CHAPTER 2. THE BCPL LANGUAGE Section Brackets Historically BCPL used the symbols $( and $) to bracket commands and declarations. These symbols are called section brackets and are allowed to be followed by tags composed of letters, digits, dots and underlines. A tagged closing section bracket is forced to match with its corresponding open section bracket by the automatic insertion of extra closing brackets as needed.
2.2. EXPRESSIONS 15 The following are examples of valid numbers: 1234 1_234_456 #B_1011_1100_0110 #o377 #X3fff #x_DEADC0DE Since August 2014, floating point constants are now allowed, such as the following: 1234.0 1.234_456e-5 10e0 A floating point constant must start with a digit and contain a decimal point (.) or an exponent sign (e or E). BCPL floating point numbers are the same size as other BCPL words and so, on 32-bit implementations, the precision is limited to about 6 decimal places.
16 SLCT shift:offset means SLCT offset means CHAPTER 2. THE BCPL LANGUAGE SLCT 0:shift:offset SLCT 0:0:offset Character constants consist of a single character enclosed in single quotes (’). The character returns a value in the range 0 to 255 corresponding to its normal ASCII encoding. Character (and string) constants may use the following escape sequences.
2.2. EXPRESSIONS Escape Replacement *n *c *p *s *b *t *e *" *’ ** *xhh A newline (end-of-line) character. A carriage return character. A newpage (form-feed) character. A space character. A backspace character. A tab character. An escape character. " ’ * The single character with number hh (two hexadecimal digits denoting an integer in the range [0,255]). The single character with number ddd (three octal digits denoting an integer in the range [0,255]).
18 CHAPTER 2. THE BCPL LANGUAGE length and bytes of the string are packed. If s is a string then s%0 is its length and s%1 is its first character, see Section 2.2.6. The *# escapes allow Unicode and GB2312 characters to be handled.
2.2. EXPRESSIONS 19 Here, E1 points to the fields of an object, with the convention that its zeroth field (E1 !0) is a pointer to the methods vector. Element E of this vector is applied to the given set of arguments. Normally, E is a manifest constant. An example program illustrating method calls can be found in BCPL/bcplprogs/demos/objdemo.b in the BCPL distribution system (see Chapter 12). 2.2.
20 CHAPTER 2. THE BCPL LANGUAGE when a field is updated. Suppose p!3 holds the value #x12345678, then after the assignment: (SLCT 12:8:3) OF p := 1 + (SLCT 8:20:3) OF p the value of p!3 is #x12302478. An expressions of the form E1 <>E2 ) evaluates E1 and E2 to yield a bit pattern, w say, and an integer, n say, and returns the result of shifting w to the left (or right) by n bit positions. Vacated positions are filled with zeroes. Negative shifts or ones of more than the word length return 0.
21 2.2. EXPRESSIONS 2.2.8 VALOF Expressions An expression of the form VALOF C, where C is a command, is evaluated by executing the command C. On encountering a command of the form RESULTIS E within C, execution terminates, returning the value of E as the result of the VALOF expression. Valof expressions are often used as the bodies of functions. 2.2.
22 CHAPTER 2. THE BCPL LANGUAGE Notice that these precedence values imply that ! f x ! @ x ! v ! i ! j @ v ! i ! j x << 1+y >> 1 ~ x!y ~ x=y NOT x=y b1-> x, b2 -> y,z 2.2.10 means means means means means means means means means ! (f x) ! (@ x) ! ((v!i)!j) @ ((v!i)!j) (x<<(1+y))>>1) ~ (x!y) ~ (x=y) NOT (x=y) b1 -> x, (b2 -> y, z) Manifest Constant Expressions Manifest constant expressions can be evaluated at compile time.
23 2.3. COMMANDS used, the appropriate 8 bit location is updated by the least significant 8 bits of E. If the left hand side is of the form S OFE then the field specified by the selector S in the structure pointed to by E is updated. S must be a manifest expression (typically a manifest name with a value specified using the SLCT operator). For more details see the specification of SLCT on page 19. A multiple assignment has the following form: L1 ,..,Ln := E1 ,..
24 CHAPTER 2. THE BCPL LANGUAGE where E denotes an expression and C1 and C2 denote commands. The symbols DO and THEN may be omitted whenever they are followed by a command keyword. To execute a conditional command, the expression E is evaluated in a Boolean context. If it yields a non zero value and C1 is present then C1 is executed. If it yields zero and C2 is present, C2 is executed. 2.3.
25 2.3. COMMANDS 2.3.6 Flow of Control The following commands affect the flow of control. RESULTIS E RETURN ENDCASE LOOP BREAK GOTO E FINISH RESULTIS causes evaluation of the smallest textually enclosing VALOF expression to return with the value of E. RETURN causes evaluation of the current routine to terminate. LOOP causes a jump to the point just after the end of the body of the smallest textually enclosing repetitive command (see Section 2.3.4).
26 CHAPTER 2. THE BCPL LANGUAGE In extended BCPL compilerd by xbcpl a more binding version of the sequencing operator is a allowed. It is the symbol <> and behaves like semicolon but is more binding than DO, THEN, ELSE, REPEATWHILE, REPEATUNTIL and REPEAT. It purpose is to reduce the need for section brackets ({ or }) as in IF x x:=y <> y:=t which is equivalent to: IF x
2.4. DECLARATIONS 2.4.2 27 Manifest Declarations A MANIFEST declaration has the following form: MANIFEST { N1 = K1 ;...; Nn = Kn } where N1 ,...,Nn are names (see Section 2.2.1) and K1 ,...,Kn are manifest constant expressions (see Section 2.2.10). Each name is declared to have the constant value specified by the corresponding manifest expression.
28 CHAPTER 2. THE BCPL LANGUAGE where N1 ,...,Nn are names (see Section 2.2.1) and K1 ,...,Kn are manifest constant expressions (see Section 2.2.10). Each name is declared to be a statically allocated variable initialised to the corresponding manifest expression. If a value specification (=Ki ) is omitted, the a value one larger than the previously defined manifest constant is implied, and if =K1 is omitted, then =0 is assumed.
2.4. DECLARATIONS 29 where N is a name and K is a manifest constant expression. A location is allocated for N and initialized to a vector whose lower bound is 0 and whose upper bound is K. The variable N and the vector elements (N !0 to N !K) reside in the runtime stack and only continue to exist while control remains within the scope of the declaration. 2.4.8 Function and Routine Declarations These declarations have the following form: LET N ( N1 ,..., Nn ) = E LET N ( N1 ,...
30 CHAPTER 2. THE BCPL LANGUAGE (@x)!1, (@x)!2,. . . where x is the first argument. This feature is useful in the definition of functions, such as writef, having a variable number of arguments. The scope of the formal parameters is the body of the function or routine. Function and routine calls are cheap in both space and execution time, with a typical space overhead of three words of stack per call plus one word for each formal parameter.
31 2.5. SEPARATE COMPILATION restriction is exemplified below. GLOBAL { var:200 } LET f1(...) BE { LET oldvar = var var := ... ... f2(...) ... IF ... DO f1(...) var := oldvar } AND f2(...) BE { ... var ... 2.
32 CHAPTER 2. THE BCPL LANGUAGE When these sections are loaded, global 200 is initialized to the entry point of function f defined in demolib.b and so is can be called from the function start defined in demomain.b. The header file, libhdr, contains the global declarations of all the resident library functions and routines making all these accessible to any section that started with: GET "libhdr". The library is described in the next chapter.
Chapter 3 The Library This manual describes three variants of the BCPL system. The simplest is invoked by the shell command cintsys and provides a single threaded command language interpreter. The system invoked by cintpos provides a multi-threaded system where the individual threads (called tasks) are run in parallel and are pre-emptible. A third version is available for some architectures and provides a single threaded version in which the BCPL source is compiled into native machine code.
34 CHAPTER 3. THE LIBRARY Most implementations use pack 4 bytes into 32-bit words requiring B2Wsh=2, but on 64-bit implementations, such as native code on the DEC Alpha or the 64-bit Cintcode version of BCPL, its value is 3. bootregs CIN:n, POS:y, NAT:n This is the location in Cintcode memory used in Cintpos to hold Cintcode registers during system startup. bytesperword CIN:y, POS:y, NAT:y Its value is 1<
3.1. MANIFEST CONSTANTS 35 function name is too long its first and last five character are packed into the string separated by a single quote ’. Typically entryword=#x0000DFDF. CIN:y, POS:y, NAT:n fl . . . Constants of the form fl ... are mnemonics for the floating point operations performed by the call sys(Sys flt, op, ...) as described near page 65. globword CIN:y, POS:y, NAT:n This constant is used to assist the debugging of Cintcode programs.
36 CHAPTER 3. THE LIBRARY CIN:y, POS:y, NAT:y rtn . . . The root node is a vector accessible to all running programs to provide access to all global information. It is available in all versions of BCPL but many of its fields are only used in Cintpos. The global variable rootnode holds a pointer to the root node. On some systems the address of the root node is also held in the manifest constant rootnodeaddr. Manifest constants starting with rtn give the positions of the fields within the root node.
3.1. MANIFEST CONSTANTS 37 CIN:n, POS:y, NAT:n rtn clwkq Under Cintpos, this field is used to holds the ordered list of packets waiting to be released by the clock device. rtn context CIN:y, POS:y, NAT:n Under certain circumstances the entire Cintcode memory is dumped in a compacted form to the file DUMP.mem for later inspection by commands such as dumpsys and dumpdebug. This field is set at the time a dump file is written to specify why the dump was requested.
38 CHAPTER 3. THE LIBRARY CIN:y, POS:y, NAT:n rtn hdrsvar This field holds the name of the environment variable giving the directories holding BCPL headers, typically ”BCPLHDRS” or ”POSHDRS”. See Section 3.6 for more details. rtn idletcb CIN:n, POS:y, NAT:n This rootnode field holds the TCB of the IDLE task for used by the standalone debugger and the commands dumpsys and dumpdebug. The task number of the IDLE task is zero but it is not a proper task and does not have an entry in the task table.
3.1. MANIFEST CONSTANTS 39 CIN:y, POS:y, NAT:n rtn membase, rtn memsize These rootnode fields hold, respectively, the start of the memory block chain and the upper bound in words of the Cintcode memory. rtn msecs CIN:y, POS:y, NAT:n This field holds the number of milli-seconds since midnight. It is repeatedly updated by the interpreter and its value is normally correct to the nearest milli-second.
40 CHAPTER 3. THE LIBRARY CIN:y, POS:y, NAT:n rtn vecstatsv This points to a vector holding counts of how many blocks of each requested size have been allocated by getvec but not yet returned. It is used by the vecstats command. rtn vecstatsvupb This field hold the upper bound of vecstatsv. CIN:y, POS:y, NAT:n saveregs CIN:n, POS:y, NAT:n This is the location in Cintcode memory used in Cintpos to hold the Cintcode registers at the time of the most recent interrupt. scb . . .
3.1. MANIFEST CONSTANTS 41 CIN:y, POS:y, NAT:n scb id This SCB field holds one of the values id inscb, id outscb or id inoutscb, indicating whether the stream is for input, output or both. CIN:y, POS:y, NAT:n scb lblock This SCB field holds the number of last block. The first block of a stream is numbered zero. scb ldata CIN:y, POS:y, NAT:n This SCB field holds the number of bytes in the last block of a stream.
42 CHAPTER 3. THE LIBRARY scbt net, scbt file, scbt ram, scbt console or scbt mbx, scbt tcp. The last three have strictly positive values causing output to be triggered by end-of-line characters, while the first three are negative and only trigger output when the IO buffer is full.
43 3.2. GLOBAL VARIABLES modules hold the relocatable byte stream interpretive code used by all BCPL interpretive systems. Constants with names ending with 64 are used in the 64-bit version of Cintcode. For more details, see the description of loadseg on page 68. tickspersecond CIN:y, POS:y, NAT:n This constant no longer exists since time is now measured in milli-seconds (and dates in days).
44 CHAPTER 3. THE LIBRARY CIN:n, POS:y, NAT:n mainco busy This is a variable used in the implementation of gomultievent under Cintpos. CIN:n, POS:y, NAT:n multi count This is a variable used in the implementation of gomultievent under Cintpos. pktlist CIN:n, POS:y, NAT:n Under Cintpos when running in multi-event mode, pktlist contains mapping from packets to their corresponding coroutines. randseed CIN:n, POS:y, NAT:n This is the seed used by the random number generator randno.
3.3. GLOBAL FUNCTIONS 45 defined in the standard resident library. Most of these are defined in BCPL in the files: sysb/klib.b, sysb/blib.b and sysb/dlib.b, one library (cin/syscin/syslib) is in hand written Cintcode since it contains instructions that cannot be generated by the BCPL compiler. The functions defined in syslib are sys, changeco and muldiv. The standard library functions are described in alphabetical order.
46 CHAPTER 3. THE LIBRARY ch := capitalch(ch) CIN:y, POS:y, NAT:y This function converts lowercase letters to uppercase, leaving other characters unchanged. res := changeco(val, cptr) CIN:y, POS:y, NAT:y This function is only used in the functions that implement the coroutine mechanism, namely: createco, callco, resumeco and cowait. It causes the current coroutine to become suspended and gives control to the coroutine specified by cptr.
47 3.3. GLOBAL FUNCTIONS Decimal range 0 < dd < 127 128 < xxyy < 9494 GB2312 bytes
- res := compch(ch1, ch2) CIN:y, POS:y, NAT:y This function compares two characters ignoring case. It yields -1 (+1) if ch1 is earlier (later) in the collating sequence than ch2, and 0 if they are equal. res := compstring(s1, s2) CIN:y, POS:y, NAT:y This function compares two strings ignoring case.
48 CHAPTER 3. THE LIBRARY next resumes execution. The parent link points to the coroutine that called this one, or is zero if the coroutine not active. The outermost coroutine (or root coroutine) is marked by the special value -1 in its parent link. As a debugging aid, all coroutines are chained together in a list held in the global colist. The values fn and sz hold the main function of the coroutine and its stack size, and c is a private variable used by the coroutine mechanism.
49 3.3. GLOBAL FUNCTIONS The definition of createco is in blib.b and is as follows.
50 CHAPTER 3. THE LIBRARY createco stack frame P2 L2 changeco stack frame fn sz c P1 L1 PC coroutine chain 0 c LP5 K9G 24 LP3 K6 SP5 J -7 { cowait(c) fn( ... ) c := ... } REPEAT fn sz c colist currco P The new coroutine Figure 3.3: The state just after changeco(0,c) in createco devid := createdev(dcb) CIN:n, POS:y, NAT:n This Cintpos function creates a device using the first available slot in devtab.
3.3. GLOBAL FUNCTIONS 51 This call causes the time stamp in datv to be converted to three strings v, v+5 and v+10. The string at v is set to the date in the form dd-mmm-yyyy. The string at v+5 is set to the the current time in the form hh:mm:ss, and the string at v+10 is set to the day of the week. The upper bound of v should be at least 14 to be safe.
52 CHAPTER 3. THE LIBRARY block (TCB) is unlinked from the priority chain and removed from tasktab. Finally its segment list and the TCB itself returned to free store. It returns a non zero value if successful. On failure, it returns zero with result2 set to 101 if taskid is invalid, or to 108 if the task is not deletable. res := dqpkt(id, pkt) CIN:n, POS:y, NAT:n This Cintpos function attempts to dequeue the given packet from the task or device specified by id.
3.3. GLOBAL FUNCTIONS 53 name is the string "*" then it opens the standard output stream which is normally to the screen. If the file name is relative and the prefix string is set, it is prepended to the name before attempting to open the stream. If the stream cannot be opened the result is zero. If the stream cannot be opened, the result is zero. See Section 3.3.2 for information about the treatment of filenames.
54 CHAPTER 3. THE LIBRARY cptr := initco(fn, size,a,b,c,d,e,f,g,h,i,j,k) CIN:y, POS:y, NAT:y This function provides a convenient method of creating and initialising coroutines. It definition is as follows: LET initco(fn, size, a, b, c, d, e, f, g, h, i, j, k) = VALOF { LET cptr = createco(fn, size) result2 := 0 IF cptr DO result2 := callco(cptr, @a) RESULTIS cptr } A coroutine with main function fn and given size is created and, if successful, it is initialised by callco(cptr, @a).
3.3. GLOBAL FUNCTIONS 55 within the current function or routine can be performed using the GOTO command, so level and longjump are only needed for non local jumps. obj := mkobj(upb,fns,a,b,c,d,e,f,g,h,i,j,k) CIN:y, POS:y, NAT:y This function creates and initialises an object.
56 CHAPTER 3. THE LIBRARY newline() CIN:y, POS:y, NAT:y This simply outputs the newline character (’*n’) to the currently selected output stream. newpage() CIN:y, POS:y, NAT:y This simply outputs the newline character (’*p’) to the currently selected output stream. res := note(scb, posv) CIN:y, POS:y, NAT:y If scr is a file stream, this function sets posv!0 and posv!1 to the current block number and position within that block.
3.3. GLOBAL FUNCTIONS 57 destination task or device (specified by pkt id!pkt). If this field is positive it refers to a task, if it is -1 it refers to the clock device and other negative values refer to other devices. If the packet is queued successfully this field is updated to hold the current task’s identifier and the result is non zero, otherwise the result is zero with result2 set to 101 if the destination id is invalid, and to 111 if pkt link was not equal to notinuse (=-1).
58 CHAPTER 3. THE LIBRARY where the decoded integer is stored. If a /N was not specified, the setting will be a BCPL string with its characters packed into argv. Note that an argument should not have both /N and /S specified. Command arguments are read from the currently selected input stream using a decoding mechanism that permits both positional and keyed arguments to be freely mixed.
59 3.3. GLOBAL FUNCTIONS ch := rdch() CIN:y, POS:y, NAT:y This call reads the next character from the currently selected input stream. If the stream is exhausted, it returns the special value endstreamch. Input from the keyboard is buffered until the ENTER (or RETURN) key is pressed to allow simple line editing in which the backspace key may be used to delete the most recent character typed. See Section 3.3.1 for more detailed information.
60 CHAPTER 3. THE LIBRARY res := release(taskid) CIN:n, POS:y, NAT:n This Cintpos function will clear the HOLD bit in the specified task thus making it potentially runnable. It returns a non zero value if successful. If the specified task does not exist it returns zero with 101 in result2. If the released task has higher priority and is runnable it gaids control leaving the current task suspended in RUN state.
3.3. GLOBAL FUNCTIONS 61 selectoutput(scb) CIN:y, POS:y, NAT:y This routine selects scb as the currently selected output stream. It aborts (with code 187) if scb is not an output stream. res := setbit(bitno, bitvec, state) CIN:y, POS:y, NAT:y This function sets the specified bit in bitvec to 1 or 0 depending on whether state is TRUE or FALSE, respectively. It returns a non-zero value if and only if the previous setting of the bit was a one. See testbit below.
62 CHAPTER 3. THE LIBRARY cli returncode and cli result2 where they can be inspected by commands such as if and why. n := str2numb(str) CIN:y, POS:y, NAT:y This function converts the string str into an integer. Characters other than 0 to 9 and - are ignored. The result is negative or zero if str%1=’-’. This function is no longer recommended, string to number should be used instead. CIN:y, POS:y, NAT:y n := string to number(str) This attempts to set result2 to the integer represented by the string str.
3.3. GLOBAL FUNCTIONS 63 CIN:y, POS:y, NAT:y res := sys(Sys callc, c name2port, a1) The name or decimals of a port is given in a1 and the result is its IP address or -1 if there is an error. CIN:y, POS:y, NAT:y res := sys(Sys callc, c newsocket) The result is the file descriptor of a new socket or -1 if there is an error. res := sys(Sys callc, c reuseaddr, a1, a2) CIN:y, POS:y, NAT:y The file descriptor of a socket is given in a1. Id a2=1 the specified socket may be reused.
64 CHAPTER 3. THE LIBRARY res := sys(Sys callc, c fd select, a1, a2, a3, a4, a5) CIN:y, POS:y, NAT:y This inspects bit a1 in the bit vector a2. The result is 1 if the bit was set and 0 otherwise. The number of the bits to test is in a1. The bit vector identifying read sockets of interest is in a2, The bit vector identifying write sockets of interest is in a3, The bit vector identifying other sockets of interest is in a4. A pointer to two words holding the timeout in seconds and microseconds is in a5.
3.3. GLOBAL FUNCTIONS 65 time of the last modification of the file given by name returning TRUE if successful. The first element datv!0 holds the number of days since 1 January 1970, datv!1 is the number of milli-seconds since midnight and datv!2=-1 indicating that the new date format is being used. If the file does not exist the call returns FALSE and setting the three elements of datv to 0, 0 and -1, respectively.
66 CHAPTER 3. THE LIBRARY the negated value of a where a is a floating point number. The last four calls perform floating point multiplication, division, addition and subtraction on their arguments. res res res res res res := sys(Sys flt, fl eq, a, b) := sys(Sys flt, fl ne, a, b) := sys(Sys flt, fl ls, a, b) := sys(Sys flt, fl gr, a, b) := sys(Sys flt, fl le, a, b) CIN:y, POS:y, NAT:y := sys(Sys flt, fl ge, a, b) These six calls return TRUE if the corresponding floating point comparisons are satisfied.
3.3. GLOBAL FUNCTIONS 67 res := sys(Sys flt, fl modf, a) res := sys(Sys flt, fl fmod, x, y) CIN:y, POS:y, NAT:y The first call returns the fractional part (f ) of a storing the integer part (i) as a floating-point number in result2. The sign of both f and i is the same as the sign of a and a will equal i + f . The second call returns f such that f has the same sign as x, the absolute value of f is less than the absolute value of y, and there exists and integer k such that k × y + f equals x.
68 CHAPTER 3. THE LIBRARY CIN:y, POS:y, NAT:y str := sys(Sys getprefix) This returns a pointer to prefix string which is in space allocated when Cintsys aor Cintpos was started.. See sys(Sys setprefix,...) on page 73. CIN:y, POS:y, NAT:y res := sys(Sys getsysval, addr) This function return the contents of the machine memory location whose address is addr. res := sys(Sys gettrval, count) CIN:y, POS:y, NAT:n This returns a value from the low level trace buffer. See Sys trpush for more details.
3.3. GLOBAL FUNCTIONS 69 directory. If a valid module is not found there and name is a relative file name, it searches through the directories specified by the environment variable whose name is in the rtn pathvar element of the rootnode. This name is normally BCPLPATH under Cintsys and POSPATH under Cintpos. See Section 3.6 for more information about environment variables. If loading is successful, loadseg returns the list of loaded program sections, otherwise it returns zero.
70 CHAPTER 3. THE LIBRARY that needs to be modified by the addition of the base address of the hunk. The code t bhunk is similar to t hunk only the data words (not the length field) are provided in binary rather than hex characters. Such hunks are thus about half the size of character based ones. The code t end marks the end of an object module, but end-of-file has the same effect. Those codes containing the characters 64 provide equivalent facilities for 64-bit versions of BCPL.
3.3. GLOBAL FUNCTIONS 71 otherwise it returns pollingch (=-3). If the input stream is exhausted it returns endstreamch (=-1). Unlike sardch, the character is not echoed to the standard output stream. CIN:y, POS:y, NAT:n res := sys(Sys putsysval, addr, val) This function set the contents of the machine memory location whose address is addr to val returning its previous setting.
72 CHAPTER 3. THE LIBRARY CIN:y, POS:y, NAT:n oldcount := sys(Sys setcount, newcount) One of the Cintcode registers is called count which is inspected just before the interpreter processes the next instruction. If count>0 it is decremented and the instruction processed. If count=0 the interpreter returns to the calling (C) program with error code 3. The Cintcode System normally has two resident interpreters.
3.3.
74 CHAPTER 3. THE LIBRARY the specified value returning it previous setting. Setting it to a negative value disables the tracing mechanism. See Sys trpush for more details. CIN:y, POS:y, NAT:y res := sys(Sys sound, fno, a1, a2 ...) This calls sound(args, g) where sound is a C function defined in sysc/sound.c. The argument args points to memory locations holding fno, a1, a2, etc., and g points to the base of the global vector.
3.3. GLOBAL FUNCTIONS res := sys(Sys sound, snd waveOutClose, a1) This closes sound wave output device a1. 75 CIN:y, POS:y, NAT:y CIN:y, POS:y, NAT:y res := sys(Sys sound, snd midiInOpen, a1) This opens MIDI device for input specified by a1 which is typically "/dev/midi", "/dev/dmmidi1" or a small integer. The result is the file (or device) descriptor of the opened device or -1 if error.
76 CHAPTER 3. THE LIBRARY CIN:y, POS:y, NAT:n sys(Sys tally, val) This call provides a profiling facility that uses a globally accessible tally vector to hold frequency counts of Cintcode instructions executed. When val is TRUE the tally vector is cleared and tallying is enabled. When val is FALSE tallying is disabled. When tallying is active, the ith element of the tally vector is incremented every time the instruction at location i of the Cintcode memory is executed.
3.3. GLOBAL FUNCTIONS 77 CIN:y, POS:y, NAT:y res := sys(Sys usleep, usecs) Under cintsys, this call causes the system to sleep for usecs micro-seconds. Under cintpos, it causes the current task to sleep for usecs micro-seconds. CIN:n, POS:y, NAT:n sys(Sys waitirq, msecs) This call is typically only made from the body of the Cintpos Idle task. It suspends the interpreter until either some Cintpos device issues an interrupt request or the specified timeout occurs.
78 CHAPTER 3. THE LIBRARY returns TRUE if successful, and FALSE otherwise. A call of unrdch will always succeeds the first time after a call of rdch. It is useful in functions such as readn where single character lookahead is necessary. See Section 3.3.1 for more detailed information. wrch(ch) CIN:y, POS:y, NAT:y This routine writes the character ch to the currently selected output stream. If output is to the screen, ch is transmitted immediately. It aborts (with code 189) if there is a write failure.
3.3. GLOBAL FUNCTIONS Item 79 Substitution Write the next argument as a string using writes. Write the next argument as a left justified string in a field width of n characters using writet. %c Write the next argument as a character using wrch. %# Write the next argument as an extended in UTF-8 or GB2312 format using codewrch. %bn Write the next argument as a binary number in a field width of n characters using writebin.
80 CHAPTER 3. THE LIBRARY FOR count = 0 TO 2 DO writef("There %p\ is\are\ %-%n thing%-%ps.*n", count) outputs: There are 0 things. There is 1 thing. There are 2 things. The implementation of writef (in sysb/blib.b) is a good example of how a variadic function can be defined. 3.3.1 Streams BCPL uses streams as a convenient method of obtaining device independent input and output.
3.3. GLOBAL FUNCTIONS 81 AND rdch() = VALOF { LET pos = cis!scb_pos // Position of next byte, if any UNLESS cis DO abort(186) IF pos
82 CHAPTER 3. THE LIBRARY AND wrch(ch) = VALOF { LET pos = cos!scb_pos IF pos >= cos!scb_bufend DO { // The buffer is full UNLESS deplete(cos) RESULTIS FALSE UNLESS cos!scb_buf RESULTIS TRUE // Must be writing to NIL: pos := cos!scb_pos } // Pack the character and advance pos. cos!scb_buf%pos := ch pos := pos+1 cos!scb_pos := pos // Advance end of valid data pointer, if necessary IF cos!scb_end < pos DO cos!scb_end := pos cos!scb_write := TRUE // Set flag to indicate the buffer has changed.
3.4. RANDOM ACCESS 3.4 83 Random Access Disk files can be regarded as potentially huge vectors of bytes with the first byte being at position zero of the file. An opened stream to or from a file has a file position pointer that holds the position relative to the start of where the next byte will be transferred. For any such stream this position can be read using note(scb, posv) or updated using point(scb, posv). For read-write streams it is possible to read or write data at any position in the file.
84 CHAPTER 3. THE LIBRARY ble to commands such as bcpl, c and setroot via the rootnode fields rtn rootvar, rtn pathvar, rtn hdrsvar and rtn scriptsvar. When Cintsys (or Cintpos) starts up it requires a valid setting of rtn pathvar in order to locate Cintcode modules such as BOOT and BLIB.
3.7. COROUTINE EXAMPLES 3.7.1 85 A square wave generator The following function is the main function of a coroutine that generates square wave samples. LET squarefn(args) = VALOF { LET freq, amplitude, rate = args!0, args!1, args!2 LET x = 0 cowait(@freq) // Return a pointer -> [freq, amplitude, rate] { // freq is a scaled fixed point value with // three digits after the decimal point.
86 CHAPTER 3. THE LIBRARY w w BUF1 c c w TEE1 w c BUF2 c TEE2 w w BUF3 w c w c c X2 X3 X5 w w c w c w c MER1 c MER2 w c c MAIN Figure 3.10: Coroutine data flow This problem is attributed to R.W.Hamming. The solution given here shows how data can flow round a network of coroutines. It is illustrated in figure 3.10 in which each box represents a coroutine and the edges represent callco/cowait connections.
3.7. COROUTINE EXAMPLES LET tee(args) BE // Body of TEE1 and TEE2 { LET in, out = args!0, args!1 cowait() // End of initialisation. { LET val = callco(in, 0) callco(out, val) cowait(val) } REPEAT } AND mul(args) BE // Body of X2, X3 and X5 { LET k, in = args!0, args!1 cowait() // End of initialisation.
88 3.7.3 CHAPTER 3. THE LIBRARY A Discrete Event Simulator This is a benchmark test for a discrete event simulator using coroutines. It simulates a network of n nodes which each receive, queue, process and transmit messages to other nodes. The nodes are uniformly spaced on a straight line and the network delay is assumed to be proportional to the linear distance between the source and the destination.
3.7. COROUTINE EXAMPLES 89 // ################### Random number generator ####################### // The following random number generator is based on one give // in Knuth: The art of programming, vol 2, p 26.
90 CHAPTER 3.
3.7. COROUTINE EXAMPLES 91 AND qitem(node) BE // The message has reached this node // It currently not busy, mark it as busy and return to process // the message, other append it to the end of the work queue // for this node.
92 CHAPTER 3.
93 3.7.
94 CHAPTER 3. THE LIBRARY 3.8 The Graphics Library The graphics library provides facilities for drawing pictures and outputing them to file. This library is designed to generate .bmp files representing potentially large images using 8-bit pixels. It should not be confused with the SDL and GL libraries (described later) used to generate images on the display screen. This library uses a rectangular canvas of 8-bit pixels with a predefined mapping from 8-bit values to RGB colours.
3.8. THE GRAPHICS LIBRARY 3.8.3 95 The Graphics Functions opengraphics(xsize, ysize) CIN:y, POS:y, NAT:y This function opens the graphics library. It allocates a canvas of 8-bit pixels of specified size and creates a prefined colour map. closegraphics() CIN:y, POS:y, NAT:y This function closes the graphics library returning the canvas to freestore. wrpixel(x, y, col) CIN:y, POS:y, NAT:y This function places a pixel of given colour at position (x, y) on the canvas.
96 CHAPTER 3. THE LIBRARY fillrect(x0, y0, x1, y1) CIN:y, POS:y, NAT:y This function draws the rectangle (x0, y0), (x1, y0), ((x1, y1), (x1, y0) filled with plotcolour. plotx and ploty are set to x1 and y1, respectively. fillrndrect(x0, y0, x1, y1, radius) CIN:y, POS:y, NAT:y This function draws the rectangle (x0, y0), (x1, y0), ((x1, y1), (x1, y0) with rounded corners of given radius filled with plotcolour.
3.10. THE GL GRAPHICS LIBRARY GET "libhdr" MANIFEST { g_sdlbase=nnn 97 } // Only used if the default setting of 450 in // libhdr is not suitable. GET "sdl.h" This library is currently described in Chapter 4 of bcpl4raspi.pdf available from my home page. 3.10 The GL Graphics Library This library is still under development OpenGL is a sophisticated graphics library allowing 3D images to be drawn on the screen efficiently using the full power of the graphics hardware available on most machines.
98 3.11 CHAPTER 3. THE LIBRARY The Sound Library This library is under development The sound library uses the sys(Sys sound,...) functions to provide facilities for reading, writing and analysing sound data. There is a sound header file (g/sound.h) declaring various constants and globals available in the sound library. The sound library itself is in g/sound.b and can be inserted into a program by the following statements. GET "libhdr" MANIFEST { g_sndbase=nnn GET "sound.h" GET "sound.
Chapter 4 The Command Language The Command Language Interpreter (CLI) is a simple interactive interface between the user and the system. It loads and executes previously compiled programs that are held either in the current directory or one of the directories specified by the shell environment variable (typically BCPLPATH or POSPATH) whose name is in rootnode!rtn path. These commands are described in Section 4.3 and their source code can be found in the com directory.
100 CHAPTER 4. THE COMMAND LANGUAGE no return link has been stored into the stack, this call of start must not attempt to return in the normal way; however, its execution can still be terminated using sys(Sys quit,0). The global vector and stack shown in figure 4.1 are used by start and form the running environment both during initialization and while running the debugger.
4.2. BOOTSTRAPPING CINTPOS 101 hold the dumped Cintcode registers. A result of zero, signifying successful completion, causes execution of Cintsys to terminate; however, if a non zero result is returned, the debugger in entered by means of the call debug(res). Note that the Cintcode registers are available to the debugger since regs is a global variable. When debug returns, the REPEAT-loop ensures that the command language interpreter is re-entered. The debugger is briefly described in the Chapter 7.
102 CHAPTER 4. THE COMMAND LANGUAGE All console input and output within BOOT and the standalone debugger is done using the standalone version of rdch and wrch, so these globals are updated appropriately. BOOT next initialises the variables used by the standalone debugger.
4.2. BOOTSTRAPPING CINTPOS 103 startroot is entered by the recursive call of interpret from BOOT with a new stack and a different global vector from that used by BOOT. If the interpreter subsequently detects a fault it returns to BOOT’s running environment giving control to the interactive debugger allowing the user to inspect the stack and global vector that were current at the time the fault.
104 CHAPTER 4. THE COMMAND LANGUAGE It always starts execution at the start of the function irqrtn with Cintcode register ST set to 3 to indicate that an interrupt is being serviced. The interrupt sevice routine may return control to the interrupted task or it may enter the scheduler if another task desrves to gain control. Before creating the resident tasks, startroot initialises a few more rootnode fields.
4.3. COMMANDS 105 or global vector. There are thus 16 posible states a task can have of which only six indicate that it is runnable, they are as follows. #b0000 This task is runnable but has no packet on its work queue. It is either the current task or it gave up control voluntarily by for instance sending a packet to a higher priority task. When it next gains control it will immediately return from the function that caused it to give up control.
106 CHAPTER 4. THE COMMAND LANGUAGE adjclock OFFSET CIN:y, POS:y, NAT:y The syntax of the OFFSET argument is [-][h][:m], that is: an optional minus sign, followed by an optional number of hours, possibly followed by :m to specify a number of minutes. The offset is converted into a signed integer representing the number of minutes to be added to the time of day as supplied by the system. If adjclock is not given an argument, it just outputs the current offset.
4.3. COMMANDS 107 causes a line to be output by the compiler for each non local identifier occurring in the program. A typical such line is as follows: all G:201 LG queens.b[9] all&~(ld|col|rd) It shows that the variable all was declared as global variable 201 and its was loaded in the compilation of statements on line 9 of the program queens.b and the context of its use was: all&~(ld|col|rd). These lines can be filtered and sorted to form a cross reference listing of a program.
108 CHAPTER 4. THE COMMAND LANGUAGE The HARD options causes both syntax and translation phase errors to call abort(100). This is useful in commands such as: c compall hard allowing each error in a long sequence of compilations to be inspected separately. The arguments T32 and T64 specify whether the target architecture is for 32 or 64 bit BCPL.
4.3. COMMANDS 109 bgpm FROM,TO/K,UPB/K CIN:y, POS:y, NAT:y This is an implementation of Christopher Strachey’s GPM macrogenerator. It takes input from the FROM file if specified, otherwise it reads from the standard input stream. The TO argument specifies the file to receive the macrogenerated result, otherwise this is sent to the standard output stream. The UPB argument specified the amount of memory that bgpm may use.
110 CHAPTER 4. THE COMMAND LANGUAGE bin-hex FROM/A,TO/K CIN:y, POS:y, NAT:y This outputs the bytes of the FROM in hex. For instance, if the file xxx was ABCDEFGH 12345678 Then the command bin-hex xxx would generate 41 42 43 44 45 46 47 48 0A 31 32 33 34 35 36 37 38 0A Unless TO is specified output is sent to the terminal.. bin-x8 FROM/A,TO/K CIN:y, POS:y, NAT:y This outputs the words of the FROM in hex.
111 4.3. COMMANDS % [ ! # ] { } Comment - skip all characters until a non white space character on a later input line. Start of a new macro call. Argument separator in macro calls. Argument item prefix. End of macro argument list. Open quote character. Close quote character.
112 CHAPTER 4. THE COMMAND LANGUAGE bounce CIN:n, POS:y, NAT:n This command is part of the bounce demonstration that is only available under Cintpos. It is normally invoked by the command: run bounce which creates a new CLI task and then enters the bounce program whose main loop is: qpkt(taskwait()) REPEAT which repeatedly suspends the task until a packet is received then immediately returns it to the sender. Packets are normally sent to the bounce task using the send command, described below.
4.3. COMMANDS 113 casech FROM/A,TO/A,DICT/K,U/S,L/S,A/S CIN:y, POS:y, NAT:y This command systematically converts all reserved words of a BCPL program to upper case and changing all identifiers to upper case (U), lower case (L, or in the form given by a specified dictionary (DICT). The A switch causes all letters including those in strings to be converted to upper case.
114 CHAPTER 4. THE COMMAND LANGUAGE wise it is sent to the standard output stream. The MSECS options causes the time to have higher precision. Typical output is as follows: Monday 23-Apr-2010 14:04:12 Monday 23-Apr-2010 14:04:14.392 date TO/K CIN:y, POS:y, NAT:y This commands output the current date to the TO file, if specified, otherwise it is sent to the standard output stream.
115 4.3. COMMANDS endcli CIN:n, POS:y, NAT:n This Cintpos command causes a CLI task to commit suicide. enlarge /A,TO/K CIN:y, POS:y, NAT:y This command output a large version of its first argument either to file or to standard output.
116 CHAPTER 4. THE COMMAND LANGUAGE hexdump FROM/A,N,P,RL/K,RLB/K,TO/K CIN:y, POS:y, NAT:y This program dumps a file specified by FROM in a combination of hex and character forms. If either RL or RLB is given the file is treated as a sequence of records. RL gives the record length in BCPL words and RLB gives it in bytes. The P and N give the number of the first record to dump and N specifies how many to dump.
4.3. COMMANDS 117 input TO/A,TERM/K CIN:y, POS:y, NAT:y This command will copy text from the current input sending it the the file specified by the AS argument. The input is terminated by a line starting with /* or the value of the TERM argument if given. interpreter FAST/S,SLOW/S| CIN:y, POS:y, NAT:y This command allows the user to select the fast (cintasm) or the slow (cinterp) version of the interpreter. If no arguments are given the fast one is selected.
118 CHAPTER 4. THE COMMAND LANGUAGE keyword. BLOCKS outputs a list of all blocks whether allocated or free in the block chain used by getvec. CODE outputs a list of all code sections currently in memory. MAPSTORE output the code sections and function entry points currently in memory, and PIC outputs a picture of what memory is currently allocated. mbxcli MBXNAME CIN:n, POS:y, NAT:n This command creates a new CLI task taking input from the specified mailbox, typically MBX:name.
4.3. COMMANDS 119 mkjunk NAME,SIZE/N CIN:y, POS:y, NAT:y This creates a file as described in the mkdata command and then tests random access to this file by overwriting some of its bytes. newcli This Cintpos command creates a new CLI task.
120 CHAPTER 4. THE COMMAND LANGUAGE prmcode CIN:y, POS:y, NAT:y This command converts an MCODE (intermediate code for MCPL) file specified by FROM to a more readable form. If FROM is missing it reads from the file MCODE. If the TO argument is missing it send the result to the screen. The file MCODE is a byproduct of the mcpl command, see mcpl above. procode FROM,TO/K CIN:y, POS:y, NAT:y This command converts an OCODE (intermediate code for BCPL) file specified by FROM to a more readable form.
4.3. COMMANDS 121 This is command differs from fail since it terminates the execution of a complete command-command while fail allows a command-command to continue run. rast2ps FROM,SCALE,TO/K,ML,MH,MG,FL,FH,FG, DPI/K,INCL/K,A4/S,A3/S,A2/S,A1/S,A0/S CIN:y, POS:y, NAT:y This commands converts a raster data file (written using the raster command described above) into a postscript file suitable for printing. There are parameters to control the region to convert, the output paper size and other parameters.
122 CHAPTER 4. THE COMMAND LANGUAGE The COUNT argument allows the user to specify how many Cintcode instructions to obey for each raster line. The default is 1000. The SCALE argument gives the raster line granularity in bytes per pixel. The default being 12. The TO argument specifies the name of the raster data file to be written. The default file name is RASTER. If raster is called without any arguments, it closes the raster data file.
4.3. COMMANDS 300K OCODE Buffer Figure 4.
124 CHAPTER 4. THE COMMAND LANGUAGE Cintsys and Cintpos logical variables are held in a linked list held in the rootnode element rtn envlist. If both NAME and VALUE are given, the given logical variable name is given the specified value, but if no value is given the specified variable is unset. If setlogname is called without arguments, the names and values of all logical variables are output. A running program can lookup and set logical variables using the functions getlogname and setlogname.
125 4.3. COMMANDS stats TO/K,PROFILE/S,ANALYSIS/S CIN:y, POS:y, NAT:y This command controls the tallying facility which counts the execution of individual Cintcode instructions. If no arguments are given, stats turns on tallying by clearing the tally vector and causing tallying to be enabled for the next command to be executed. Subsequent commands are not tallied, making it possible to process the tally vector while it is in a static state.
126 CHAPTER 4. THE COMMAND LANGUAGE tcpdump CIN:n, POS:y, NAT:n This outputs the list of Cintpos TCP/IP devices that currently exist. The list includes information about sockets, states and associated hosts and port numbers. tcprx HOST,PORT CIN:n, POS:y, NAT:n This is a TCP/IP demonstration program to be used in conjuction with tcptx. It will output data received from a specified host via a specified port. If no host is specified wait for a connection from any host. The default port number is 9000.
127 4.3. COMMANDS vecstats CIN:y, POS:y, NAT:y This command output information about blocks of Cintcode memory that are currently allocated. Typical output (from Cintpos) is the following: 3: 27: 306: 571: 1025: 12 4 2 1 2 4: 28: 316: 597: 1901: 2 1 1 1 1 6: 41: 406: 757: 2422: 1 1 1 1 1 15: 80: 462: 982: 3303: 2 22: 1 200: 1 500: 1 1000: 1 20000: 1 2 1 10 1 23: 291: 506: 1006: 7 1 3 6 This indicates, for instance, that there are currently 7 blocks of requested size 23 allocated.
128 CHAPTER 4. THE COMMAND LANGUAGE resulting file. Either FILE or LIST or both must be supplied. If given FILE is the first filename to be encoded followed by those given in LIST file, if present. If BIN is set, files are read using binrdch so that carriage return characters (’*c’) are not ignored. Each encoded file is preceeded by a separator of the form: #####filename# followed by the encoded file in which all characters with ASCII codes in the range 33 to 126 except for ’#’, ’=’ and ’.
129 4.4. CLI.B AND CLI INIT.B cli faillevel CIN:y, POS:y, NAT:y CIN:y, POS:y, NAT:y cli data This holds CLI data dependant on the context in which the CLI is running.
130 CHAPTER 4. THE COMMAND LANGUAGE clibit noprompt clibit eofdel clibit comcom clibit maincli clibit newcli clibit runcli clibit mbxcli clibit tcpcli clibit endcli Do not output prompts even when not in a commandcommand. Delete this task when EOF is received under Cintpos. This CLI is currently in a command-command executing commands from a temporary file. This CLI is the task 1 CLI under Cintpos or the main CLI under other systems. This CLI was created by the newcli command under Cintpos.
Chapter 5 Console Input and Output When cintsys or cintpos is started a stream is opened to receive input from standard input which is normally the keyboard and a second stream is opened to allow output to standard output which is normally the screen. This combination of keyboard and screen is called the console. The treatment of console streams depends on whether cintsys or cintpos is being used. 5.
132 5.2 CHAPTER 5. CONSOLE INPUT AND OUTPUT Cintpos console streams Under Cintpos interaction with the console is somewhat more complicated since Cintpos can have several tasks all wishing to communicate with the keyboard and screen. This interaction is controlled by a task called the Console Handler (typically task 3). Tasks wishing to read from the keyboard or write to the screen must send request packets to this task where they will be properly scheduled.
5.2. CINTPOS CONSOLE STREAMS Sequence @A @B @C @D @E @F @H @L @Sdd @Tdd @U @Xhh @Y @Z @ddd @@ 5.2.
134 5.2.2 CHAPTER 5.
Chapter 6 Cintpos Devices Cintpos allows asynchronous communication with peripheral devices using the qpkt and taskwait functions. If the pkt id field of packet given to qpkt is negative, the packet is sent to the identified device. It is returned when the device has completed the requested operation. Most devices have device control blocks (DCBs) that contain device related data. There is a device table pointed to by rootnode!rtn_devtab whose upper bound is held in its zeroth element.
136 6.0.5 CHAPTER 6. CINTPOS DEVICES The Keyboard Device This device has identifier -2 and is currently not treated specially, and so it has a DCB, and a device thread that is continually trying to read character from standard input which is normally the keyboard. Packets for this device are placed on the end of the work queue held in the dcb wkq field of the DCB.
137 Tcp rcvbufsz arg1: sock arg2: sz This sets the receive buffer size of the given socket to size bytes. A zero result indicates success. Tcp bind arg1: sock arg2: ipaddr arg3: port This assigns local host and port numbers to the specified socket. A zero result indicates success. Tcp connect arg1: sock arg2: ipaddr arg3: port arg4: timeout This attempts to establish a connection to a remote host via the given socket within the given timeout.
138 CHAPTER 6. CINTPOS DEVICES a specified timeout period. If timeout is greater than zero it is the timeout period in milli-seconds, if it is zero there is no timeout and if it is negative the packet is returned immediately having written as many bytes as are currently possible. A negative result indicates failure with a reason given in the second result, otherwise it is the number of bytes actually sent. Tcp close arg1:sock This closes the specified socket. A zero result indicates success.
Chapter 7 The Debugger Both Cintsys and Cintpos have interactive debuggers but these are slightly different and so will be described separately. 7.1 The Cintsys Debugger When the Cintsys starts up, control first passes to BOOT which initialises the system and creates a running environment for the command language interpreter (CLI). This is run by a recursive invocation of the interpreter and so when faults occur control returns to BOOT which then enters an interactive debugger.
140 CHAPTER 7.
141 7.1.
142 CHAPTER 7. THE DEBUGGER At this point the first instruction of rdargs is about to be executed.
7.2. THE CINTPOS DEBUGGER Command . , ; [ ] 143 Effect Select current coroutine Display next stack frame Select parent coroutine Select first coroutine Select next coroutine Finally, the command Q causes a return from the Cintcode system. 7.2 The Cintpos Debugger Under Cintpos, the interactive debugger can be entered by connecting the console to task 2 (using @s02). This allows debugging to take place while other tasks are running.
144 CHAPTER 7. THE DEBUGGER clock device) interfere with single stepping of Cintcode instructions, the K command is provided to turn clock interrupts on and off. The address of the task control block of the currently selected task is given by W. Thus the first locations of the control block can be printed by the command Wt10. The debugger prompt contains a letter indicating whether the next instruction is toe executed in user mode (a), in kernel mode (k) or within the interrupt service routine (i).
Chapter 8 The Design of OCODE BCPL was designed to be a portable language with a compiler that is easily transferred from machine to machine. To help to achieve this, the compiler is structured as shown in figure 8.1 so that the codegenerator (CG), which is inherently machine dependent, is separated from the rest of the compiler.
146 CHAPTER 8. THE DESIGN OF OCODE example, if the file test.b is the following: GET "libhdr" LET start() BE { LET a, b, c = 1, 0, -1 writef("Answer is %n*n", a+b+c) } then the command: bcpl test.b would write the following text to the file ocode.
8.3. LOADING AND STORING VALUES 147 to S in the description of OCODE statements should be regarded as a specification of S for the subsequent statement. Static variables, tables and string constants are allocated space in the program area and are referenced using labels such as L36 and L92. All global, local and static variables are of the same size and, on most modern implementations, they hold 32 bit values. More recently 64 bit versions of BCPL are becoming more common.
148 CHAPTER 8. THE DESIGN OF OCODE Statement LF Ln LN n FNUM m e TRUE FALSE QUERY LSTR n C1 . . . Cn Meaning P!S := entry point Ln; S := S+1 P!S := n; S := S+1 P!S := (m, e); S := S+1 P!S := TRUE; S := S+1 P!S := FALSE; S := S+1 P!S := ?; S := S+1 P!S := "C1 . . . Cn "; S := S+1 LF Ln loads the entry point of a non global function onto the stack. LN n loads the signed integer constant n onto the stack.
8.5. EXPRESSION OPERATORS 149 but if op is non zero it represents and assignment operator (assop) and the statement is equivalent to: SLCT len:sh:0 OF (P!(S-1)) assop:= P!(S-2); S := S-2 The mapping between op and assop is given by the following table. op 1 2 3 4 5 6 7 8 assop ! #* #/ #+ #* / REM op 9 10 11 12 13 14 15 16 assop + << >> & | EQV NEQV The floating-point assignment operators are only allowed when the specified field is a full word, typically with len and sh both zero.
150 CHAPTER 8.
151 8.6. FUNCTIONS AND ROUTINES ENTRY Li n C1 . . . Cn SAVE s body of function or routine ENDPROC Li is the label allocated for the entry point. As a debugging aid, the length of the function or routine name is given by n and its characters by the C1 . . . Cn . The SAVE statement specifies the initial setting of S, which is just the save space size (=3) plus the number of formal parameters. The state of the stack just after entry is shown in figure 8.3.
152 CHAPTER 8. THE DESIGN OF OCODE Old stack frame New stack frame E1 E2 En E k S P Figure 8.4: The moment of calling E(E1,E2,...En) 8.7 Control The statement LAB Ln set the value of label Ln to the current position in the OCODE program. An unconditional transfer to this label can be performed by the satement JUMP Ln. Conditional jumps inspect the value on the top of the stack P!(S-1). JT Ln will make the jump if it is TRUE, and JF Ln will jump if FALSE.
153 8.9. DISCUSSION Static variables and tables are allocated space in the program area using statements of the form ITEMN n, where n is the initial value of the static cell. The elements of table are placed in consecutive locations by consective ITEMN statements. A label may be set to the address of a static cell by preceding the ITEMN statement by a statement of the form DATALAB Ln. The SECTION and NEEDS directives in a BCPL program translate into SECTION and NEEDS statements of the form: SECTION n C1 .
154 CHAPTER 8.
Chapter 9 The Design of Cintcode The original version of Cintcode was a byte stream interpretive code designed to be both compact and capable of efficient interpretation on small 16 bit machines machines based on 8 bit micro processors such as the Z80 and 6502. Versions that ran on the BBC Microcomputer and under CP/M were marketed by RCP Ltd [2].
156 CHAPTER 9. THE DESIGN OF CINTCODE The registers A and B are used for expression evaluation, and C is used in in byte subscription. P and G are pointers to the current stack frame and the global vector, respectively. ST is used as a status register in the Cintpos version of Cintcode, and PC points to the first byte of the next Cintcode instruction to execute. Count is a register used by the debugger.
157 9.1.
158 CHAPTER 9. THE DESIGN OF CINTCODE LG b B := A; A := G!b LG1 b B := A; A := G!(b+256) LGH h B := A; A := G!h Here, b and h are unsigned 8 and 16 bit values, respectively. 9.1.2 Composite Instructions Compactness can be improved by combining commonly occurring pairs (and triples) of operations into a single instructions. Many such composite instructions occur in Cintcode; for instance, AP3 adds local 3 to the A register, and L1P6 will load v!1 into register A, assuming v is held in local 6.
9.2. THE CINTCODE INSTRUCTION SET 159 command. The use of a 16 bit resolving word places a slight restriction on the maximum size of relative references. Any Cintcode module of less than 64K bytes will have no problem. 9.2 The Cintcode Instruction Set The resulting selection of function codes is shown in Table 9.2 and they are described in the sections that follow. In the remaining sections of this chapter the following conventions hold: Symbol n Ln b h w filler A B C P G PC MW 9.2.
160 CHAPTER 9.
161 9.2. THE CINTCODE INSTRUCTION SET compile code with the opposite endianess to that of the machine on which the compiler is running, see the description of the bcpl command on page 106. 9.2.2 Loading Values The following instructions are used to load constants, variables, the addresses of variables and function entry points. Notice that all loading instructions save the old value of register A in B before updating A. This simplifies the translation of dyadic expression operators.
162 CHAPTER 9. THE DESIGN OF CINTCODE LLP b LLPH h LLPW w LLG b LLG1 b LLGH h LLL Ln LLL$ Ln B B B B B B B B := := := := := := := := A; A; A; A; A; A; A; A; A A A A A A A A := := := := := := := := @P!b @P!h @P!w @G!b @G!(b + 256) @G!h @(variable Ln) @(variable Ln) These instructions load the BCPL pointers to local, global and static variables. 9.2.
163 9.2. THE CINTCODE INSTRUCTION SET These instructions provide for all the normal arithmetic and bit pattern dyadic operators. The instructions DIV and REM generate exception 5 if the divisor is zero. Evaluation of relational operators in non conditional contexts involve conditional jumps and the FHOP instruction, see page 166. Addition is the most frequently used arithmetic operation and so there are various special instructions improve its efficiency.
164 9.2.6 PBYT XPBYT ST STn ST0Pn ST1Pn STPn S0G b S0G1 b S0GH h CHAPTER 9. THE DESIGN OF CINTCODE Indirect Assignment B%A := C A%B := C A!0 := B A!n := B P!n!0 := A P!n!1 := A P!n!A := B G!b!0 := A G!(b+256)!0 := A G!h!0 := A 1≤n≤3 3≤n≤4 3≤n≤4 3≤n≤5 These instructions are used in assignments in which % or ! appear as the leading operator on the left hand side. 9.2.7 Function and Routine Calls At the moment a function or routine is called the state of the stack is as shown in figure 9.3.
9.2. THE CINTCODE INSTRUCTION SET 165 3 ≤ n ≤ 11 Kn K b KH h KW w These instructions call the function or routine whose entry point is in A and whose first argument (if any) is in B. The new stack frame at position k relative to P where k is n, b, h or w depending on which instruction is used.
166 9.2.8 CHAPTER 9. THE DESIGN OF CINTCODE Flow of Control and Relations The following instructions are used in the compilation of conditional and unconditional jumps, and relational expressions. The symbol rel denotes EQ, NE, LS, GR, LE or GE indicating the relation being tested.
9.2. THE CINTCODE INSTRUCTION SET 167 dlab to jump to the default label. See Section 9.1.3 for details on how resolving half words are interpreted. SWB filler n dlab K1 L1 . . . Kn Ln This instruction is used when the range of case constants is too large for SWL to be economical. It performs the jump using a binary chop strategy. The quantities n, dlab, K1 to Kn and L1 to Ln are 16 bit half words aligned on 16 bit boundaries by the option filler byte.
168 CHAPTER 9. THE DESIGN OF CINTCODE These instructions are used move values between register A, B and C. NOP This instruction has no effect. SYS This instruction is used in body of the hand written library routine sys. If A is zero then the interpreter returns with exception code P!4. If A is -1 it set register count to P!4, setting A to the previous value of count. Changing the value of count may change which of the two interpreters is used. For more details see Section 4.3.
9.2. THE CINTCODE INSTRUCTION SET 9.2.11 169 Floating-point Instructions Floating-point operations other than those performed by SELST are provided by the FLTOP instruction. They are as follows.
170 CHAPTER 9. THE DESIGN OF CINTCODE 9.2.14 Corruption of B To improve the efficiency of some hand written machine code interpreters, the following instructions are permitted to corrupt the value held in B: K KH KW Kn KnG KnG1 KnGH SWL SWB MDIV CHGCO All other instructions either set B explicitly or leave its value unchanged. 9.2.15 Exceptions When an exception occurs, the interpreter saves the Cintcode registers in its register vector and yields the exception number as result.
Chapter 10 The Design of Sial Sial is an internal intermediate assembly language designed for BCPL. The first version was called Cial (Compact Internal Assembly Language) was pronounced “seal”. It was essentially an assembly language for Cintcode with the same function code mnemonics and the same abstract machine registers.
172 CHAPTER 10. THE DESIGN OF SIAL This can be converted into something slightly more readable using the command: sial-sasm hello.sial to * giving: This can be translated into Sial using the bcpl2sial command as follows. 0.010> sial-sasm hello.sial to * Converting hello.sial to * MODSTART //Entry to: start ENTRY K5 C115 C116 C97 C114 C116 LAB L1 LSTR M9001 KPG P3 G94 L K0 RTN STRING M9001 K6 C72 C101 C108 C108 C111 C10 GLOBAL K1 G1 L1 G94 MODEND Conversion complete 0.
10.1. THE SIAL SPECIFICATION 173 call *%eax # L K0 xorl %ebx,%ebx # RTN movl 4(%ebp),%eax movl 0(%ebp),%ebp jmp *%eax # STRING M9001 K6 C72 C101 C108 C108 C111 C10 .data .align 4 MA9001: .byte 6 .byte 72 .byte 101 .byte 108 .byte 108 .byte 111 .byte 10 .text # GLOBAL K1 .globl prog .globl _prog prog: _prog: movl 4(%esp),%eax # G1 L1 movl $LA1,4(%eax) # G94 ret # MODEND 0.
174 CHAPTER 10. THE DESIGN OF SIAL F P G K W C L M An opcode or directive A stack offset, 0 to #xFFFFFF A global variable number, 0 to 65535 A 24-bit unsigned constant, often small in value A signed integer, used for static data and large constants A byte in range 0 to 255 A label generated by translation phase A label generated by the Sial codegenerator The instructions are for an abstract machine with the following internal registers.
175 10.1. THE SIAL SPECIFICATION lkp lkg rv rvp rvk st stp stk stkp skg xst Kk Pn Kk Gn k Pn kpg neg not abs Pn Gg Pn Kn Pn Kn Kk Pn Kk Gn a := P!n!k a := G!n!k a := ! a a := P!n!a a := a!k !a := b P!n!a := b a!n := b P!n!k := a G!n!k := a !b := a Call a(b,...) incrementing P by n leaving b in a Call Gg(a,...
176 CHAPTER 10. THE DESIGN OF SIAL lsh rsh and or xor eqv gbyt xgbyt pbyt xpbyt swb swl xch atb atc bta btc atblp atblg atbl Kn Ld K1 L1 ... Kn Ln Kn Ld L1 ...
177 10.1. THE SIAL SPECIFICATION Breakpoint instruction No operation Change coroutine a := muldiv(P!3, P!4, P!5) System function brk nop chgco mdiv sys section modstart modend global string const static mlab lab lstr entry Kn C1 ... Kn Ml Mn Ln Mn Lm Mn Kn Cn G1 L1 ... Kn C1 ... Ww Kk W1 ... C1 ...
178 CHAPTER 10.
10.1.
180 CHAPTER 10. THE DESIGN OF SIAL LF L2 K P4 ATBLP P3 MUL RTN GLOBAL K1 G1 L1 G94 MODEND 10.2 The sial-386 Translator The source of an unoptimised Sial translator that generates Intel 386 assembly language is com/sial-386.b. It is a simple program about 750 lines based on the sial-sasm program. This version was implemented before the floating point instructions were added to Sial.
10.2. THE SIAL-386 TRANSLATOR # SP P9 movl %ebx,36(%ebp) # LP P3 movl 12(%ebp),%ebx # SP P8 movl %ebx,32(%ebp) # LSTR M1 leal MA1,%ebx shrl $2,%ebx # KPG P4 G94 movl 376(%esi),%eax leal 16(%ebp),%edx call *%eax # IKP K1 P3 movl 12(%ebp),%ebx incl %ebx movl %ebx,12(%ebp) # ATBL K5 movl %ebx,%ecx movl $5,%ebx # JLE L4 cmpl %ebx,%ecx jle LA4 # L K0 xorl %ebx,%ebx # RTN movl 4(%ebp),%eax movl 0(%ebp),%ebp jmp *%eax # STRING M1 K15 C102 C97 C99 C116 C40 C37 C110 C41 C32 # C61 C32 C37 C105 C52 C10 .data .
182 LA2: movl %ebp,0(%edx) movl %edx,%ebp popl %edx movl %edx,4(%ebp) movl %eax,8(%ebp) movl %ebx,12(%ebp) # JNE0 L5 orl %ebx,%ebx jne LA5 # L K1 movl $1,%ebx # RTN movl 4(%ebp),%eax movl 0(%ebp),%ebp jmp *%eax # LAB L5 LA5: # LM K1 movl $-1,%ebx # AP P3 addl 12(%ebp),%ebx # ATB movl %ebx,%ecx # LF L2 leal LA2,%ebx # K P4 movl %ebx,%eax movl %ecx,%ebx leal 16(%ebp),%edx call *%eax # ATBLP P3 movl %ebx,%ecx movl 12(%ebp),%ebx # MUL movl %ecx,%eax imul %ebx movl %eax,%ebx # RTN movl 4(%ebp),%eax movl 0(%ebp),
183 10.2. THE SIAL-386 TRANSLATOR When implementing sial-386 it was necessary to decide how the Intel registers were to be used and what the BCPL calling sequence should be.
184 CHAPTER 10. THE DESIGN OF SIAL The call cvfpg("KPG") reads the Sial statement knowing it is of the form: KPG Pk Gn. This outputs the statement as an assembly language comment after placing k and n in pval and gval, respectively. The three writef calls then output the three assembly language instructions for the KPG operation, and ENDCASE transfers control to where the next Sial statement is processed. All the other cases are equally simple.
10.3. COMPACTION OF SIAL 10.3 185 Compaction of Sial In order to transmit program to a device such as a mobile phone or space probe over a slow connection it is useful to have a compact representation of the code. Sial is both target machine independent and can be compacted with ease. This section gives a brief overview of an experimental compaction technique that seems to performs well.
186 CHAPTER 10.
Chapter 11 The MC Package This chapter describes the MC package which provides a machine independent way to generate and execute native machine code at runtime. The work on this package started in January 2008 and is still under development, however, it currently works well enough to run the n-queens problem on i386 machines about 24 times faster than the normal Cintcode interpretive version.
188 CHAPTER 11. THE MC PACKAGE MANIFEST { A=mc_a; B=mc_b; C=mc_c; D=mc_d; E=mc_e; F=mc_f a1=1; a2; a3 } LET start() = VALOF { // Load the dynamic code generation package for i386 machines. LET mcseg, mcb, n = globin(loadseg("mci386")), 0, 0 UNLESS mcseg DO { writef("Trouble with MC package: mci386*n") GOTO fin } // Create an MC instance for 10 functions with a data space // of 100 words and code space of 4000 words.
11.1. MC EXAMPLE 189 // MV A,A1 movl 20(%ebp), %eax 573: 8B 45 14 // ADD A,A2 addl 24(%ebp), %eax 576: 03 45 18 // LAB L1 lab L1 579: L1: // ADD A,A3 addl 28(%ebp), %eax 579: 03 45 1C // DEC A decl %eax 582: 48 // CMP A,$100 cmpl $100, %eax 583: 83 F8 64 // JLT L1 jl L1 586: 7C F7 // DEBUG 3 // RTN // ENDFN // END F1(10, 20, 30) => 117 The result of 117 (= 10+20+(30-1)*3) shows that the body of the loop was correctly executed three times. The header file (mc.
190 CHAPTER 11.
11.2. MC LIBRARY FUNCTIONS mcRK mcAK mcVK mcGK mcMK mcLK mcDK mcDXK mcDXsK mcDXsBK mcKK mcKKK mcPRF 11.
192 CHAPTER 11. THE MC PACKAGE mcRK(mc_mv, A, #x10000000) mcPRF("With D=%8x ", D) mcPRF("A=%8x ", A) mcPRF("B=%8x*n", B) mcR(mc_div, B) mcPRF("the instruction: DIV B*n") mcPRF("gives D=%8x ", D) mcPRF("A=%8x ", A) mcPRF("B=%8x*n", B) This causes the following output: With D= 1234567 the instruction: gives D= 9abcdef A=89abcdef DIV B A=12345678 B=10000000 B=10000000 n := mcNextlab() Allocate the next available label assigning its number to n.
11.3. THE MC LANGUAGE 193 When an MC function is declared it has a specified number of arguments and local variables (see the ENTRY statement below). When a function is called by the CALL instruction, the required number of arguments must have already been pushed onto the stack. On return these arguments will have been automatically popped from the stack. If the wrong number of arguments are given, the effect is undefined. By convention, the result of a function is returned in register A.
194 CHAPTER 11. THE MC PACKAGE ALIGND K Align the next item of data to an address which is a multiple of k which must be 2, 4 or 8. AND RA RV RG RR AR VR GR RK AK VK GK Perform the bit wise AND of the second operand into RM RL RD RDX RDXs RDXsB MR LR DR DXR DXsR DXsBR MK LK DK DXK DXsK DXsBK the first. CALL KK Call the function who number is the first argument with n arguments that have already been pushed onto the stack when n is the second operand.
11.3. THE MC LANGUAGE 195 DEC R A V G M L D DX DXs DXsB Decrement the specified register or memory word by 1, leaving the condition code undefined. DIV K R A V G M L D DX DXs DXsB Divide the double length value in D:A by the specified operand. The result is left in A and the remainder in D. The DIV instruction performs signed arithmetic. DLAB L Set the specified label to the absolute address of the next available byte in the data area. ENDFN This marks the end of the body of the current function.
196 CHAPTER 11. THE MC PACKAGE JLT JS JL JR Jump to the specified location if the first operand of a previous CMP instruction was less than its second operand using signed arithmetic. JMP Unconditionally jump to the specified location. JS JL JR JNE JS JL JR Jump to the specified location if the first operand of a previous CMP instruction was not equal to its second operand. LAB L Set the specified label to the machine address of the current position in the code area.
11.3. THE MC LANGUAGE 197 RK AK VK GK MK LK DK DXK DXsK DXsBK Move the zero extended 16-bit value specified by the second operand into the first. LEA RA RV RG RM RL RD RDX RDXs RDXsB Load the register specified by the first operand with the absolute address of the memory location specified by the second operand. LSH RK RR Shift to the left the value in the register specified by the first operand by the amount specified by the second operand. If the second operand is a register is must be C.
198 CHAPTER 11. THE MC PACKAGE SEQ R Set the specified register to one if the first operand of a previous CMP instruction was equal to its second operand, otherwise set it to zero. SGE R Set the specified register to one if the first operand of a previous CMP instruction was greater than or equal to its second operand using signed arithmetic, otherwise set it to zero.
11.3. THE MC LANGUAGE 199 UJGE JS JL JR Jump to the specified location if the first operand of a previous CMP instruction was greater than or equal to its second operand using unsigned arithmetic. UJGT JS JL JR Jump to the specified location if the first operand of a previous CMP instruction was greater than its second operand using unsigned arithmetic.
200 11.4 CHAPTER 11. THE MC PACKAGE MC Debugging Aids The primary debugging aid is to inspect the generated code and the is controlled by the DEBUG directive which sets the tracing level held in the global variable mcDebug. Assuming bimc are the least significant four bit of mcDebug, if c = 1, print comments compiled by mcComment. If m = 1, print MC instructions and directives. If i = 1, print the corresponding target instruction(s) and if b = 1, print the resulting binary code in hexadecimal.
201 11.5.
202 CHAPTER 11.
203 11.5.
204 CHAPTER 11.
Chapter 12 Installation The implementation of BCPL described in this report is freely available via my Home Page [3] to individuals for private use and to academic institutions. If you install the system, please send me an email (to mr@cl.cam.ac.uk) so I can keep a record of who is interested in it. This implementation is designed to be machine independent being based on an interpreter written in C.
206 CHAPTER 12. INSTALLATION Some web browsers will have already decompressed the .tgz file, so you may have use the following command instead: cd distribution tar xvf bcpl.tgz This step will create and populate the directories BCPL, BCPL/cintcode, BCPL/bcplprogs and BCPL/natbcpl.
12.1. LINUX INSTALLATION 207 to the end of the file .bashrc in your home directory so the the BCPL environment variables are automatically setup whenever you start a bash shell. 4) Now change directory to cintcode and attempt to re-build the parts of the system implemented in C and populate the directory cin with a basic set of compiled commands. cd distribution/BCPL/cintcode make clean make sys If the system is known to work typing just make instead of make sys is more convenient.
208 CHAPTER 12. INSTALLATION c compall 6) The BCPL programs that are part of the system are: boot.b, blib.b, dlib and cli.b. These reside in BCPL/cintcode/sysb and can be compiled by the following commands (in the BCPL Cintcode System). c c c c bs bs bs bs boot blib dlib cli The standard commands are in BCPL/cintcode/com and may be compiled using bc.
12.3. INSTALLATION ON OTHER MACHINES -m n -t n -s -c text -- text -f -v -vv -h 209 Set the Cintcode memory size to n words. Set the tally vector size to n words. Enter the Cintcode system giving the name of this file as the command for the CLI to run. Enter cintsys with standard input setup to read the characters from text followed by an end-of-stream character. Enter cintsys with standard input setup to read the characters in text followed by the characters of the old standard input.
210 CHAPTER 12. INSTALLATION I installed the freely available .NET Framework 3.5 and the corresponding SDK 3.5. This provided amongst many other things a C compiler and all the relevant libraries. I then created a shortcut on the desktop with Target: %SystemRoot%\system32\cmd.exe /q /k os\windows\VC8env.bat and Start in: E:\distribution\BCPL\cintcode Double clicking on this shortcut opens a Shell window with the required environment variable all set up C compilation and the BCPL running environment.
12.6. INSTALLATION FOR WINDOWS CE2.0 12.6 211 Installation for Windows CE2.0 A version of the BCPL Cintcode System is available for handheld machines running Windows CE version 2.0. For installation details see the README file in sysasm/shwince. This system provides a scrollable window for interaction with the CLI. It also provides a simple graphical facilities using a graphics window. The system has only been tested on an HP 620LX handheld machine. 12.
212 CHAPTER 12.
Chapter 13 Example Programs 13.1 Coins The following program prints out how many different ways a sum of money can be composed from coins of various denominations.
214 13.2 CHAPTER 13. EXAMPLE PROGRAMS Primes The following program prints out a table of all primes less than 1000, using the sieve method. GET "libhdr" GLOBAL { count: ug } MANIFEST { upb = 999 } LET start() = VALOF { LET isprime = getvec(upb) count := 0 FOR i = 2 TO upb DO isprime!i := TRUE // Until proved otherwise.
13.4. FRIDAYS 215 LET start() = VALOF { all := 1 FOR i = 1 TO 16 DO { count := 0 try(0, 0, 0) writef("Number of solutions to %i2-queens is %i9*n", i, count) all := 2*all + 1 } RESULTIS 0 } 13.4 Fridays The following program prints a table of how often the 13th day of the month lies on each day of the week over a 400 year period.
216 13.5 CHAPTER 13. EXAMPLE PROGRAMS Lambda Evaluator The following program is a simple parser and evaluator for lambda expressions.
217 13.5. LAMBDA EVALUATOR // *************** // Construct // // // // // // // // // // // a ,.., z dddd x y Y x x * y x / y x + y x - y x = y b -> x, y Li y Syntax analyser *********************** Corresponding Tree --> --> --> --> --> --> --> --> --> --> --> [Id, ’a’] ,..
218 CHAPTER 13.
13.5.
220 CHAPTER 13. EXAMPLE PROGRAMS AND try(expr) BE { LET v = VEC 2000 space := v+2000 writef("Trying %s*n", expr) writef("Answer: %n*n", eval(parse(expr), 0)) } AND start() = VALOF { try("(Lx x+1) 2") try("(Lx x) (Ly y) 99") try("(Ls Lk s k k) (Lf Lg Lx f x (g x)) (Lx Ly x) (Lx x) 1234") try("(Y (Lf Ln n=0->1,n**f(n-1))) 5") RESULTIS 0 } 13.6 Fast Fourier Transform The following program is a simple demonstration of the algorithm for the fast fourier transform.
221 13.6.
222 CHAPTER 13. EXAMPLE PROGRAMS AND reorder(v, n) BE { LET j = 0 FOR i = 0 TO n-2 DO { LET k = n>>1 // j is i with its bits is reverse order IF i
Bibliography [1] D.T. Ross et al. AED-0 programmer’s guide and user kit. Technical report, Electronic Systems Laboratory M.I.T, 1964. [2] C. Jobson and J.M. Richards. BCPL for the BBC Microcomputer. Acornsoft Ltd, Cambridge, 1983. [3] M. Richards. My WWW Home Page. www.cl.cam.ac.uk/users/mr/. [4] M. Richards. The Implementation of CPL-like programming languages. Phd thesis, Cambridge University, 1966. [5] M. Richards, A.R. Aylward, P. Bond, R.D. Evans, and B.J. Knight.
224 BIBLIOGRAPHY
Appendix A BCPL Syntax Diagrams The syntax of standard BCPL is specified using the transition diagrams given in figures A.1, A.2, A.3 and A.4. In extended BCPL the floating point operators have the same precedence as the corresponding integer ones, and the op:= operators are syntactically identical to the := operator. The syntax of the more binding sequencing operator (<>) requires some new diagrams to be drawn. This will be done in due course.
226 APPENDIX A. BCPL SYNTAX DIAGRAMS and not { IF i>10 DO i := i/2 } REPEATUNTIL i<5 A useful property of these diagrams is that, once a test box has been successfully traversed, previous branching decisions need not be reconsidered and so the parser need never backtrack. program . section eof section SECTION string ; NEEDS string ; MANIFEST STATIC name = E0 ; } name : E0 ; } { GLOBAL { AND , LET name ( name = E0 BE C ) Figure A.
227 D MANIFEST STATIC name = E0 ; } name : E0 ; } { GLOBAL { AND , LET name ( = name VEC name E0 BE C E0 , , , = ) = Figure A.
228 APPENDIX A. BCPL SYNTAX DIAGRAMS C BREAK REPEATWHILE LOOP REPEATUNTIL ENDCASE E0 REPEAT RETURN FINISH SKIP GOTO E0 RESULTIS TEST E0 THEN C ELSE C DO FOR name = E0 TO E0 BY E0 THEN C DO IF E0 UNLESS WHILE UNTIL { D SWITCHON E0 ; C INTO { , E0 , , E0 := E0 := E0 is call is name CASE : C E0 DEFAULT Figure A.
229 En , TRUE ( n<9 E0 ) ! n<8 E8 % n<8 OF n<8 * n<6 / n<6 MOD n<6 + n<5 − n<5 = n<4 = n<4 ~= n<4 ~= n<4 < n<4 < n<4 > n<4 > n<4 <= n<4 <= n<4 >= n<4 >= n<4 FALSE ? name number E6 character string ( E0 ! ) E5 E7 @ + E5 − ABS NOT E3 , E4 TABLE E0 VALOF C << n<4 >> n<4 E9 & n<3 E3 : E9 | n<2 E2 EQV n<1 E1 : E9 XOR n<1 −> n<1 SLCT E4 E0 Figure A.
230 APPENDIX A.