1*46439007SCharles.Forsyth.TL 2*46439007SCharles.ForsythProgram Development under Inferno 3*46439007SCharles.Forsyth.AU 4*46439007SCharles.ForsythRoger Peppé 5*46439007SCharles.Forsythrog@vitanuova.com 6*46439007SCharles.Forsyth.SH 7*46439007SCharles.ForsythIntroduction 8*46439007SCharles.Forsyth.PP 9*46439007SCharles.ForsythInferno provides a set of programs that, used in 10*46439007SCharles.Forsythcombination, provide a powerful development environment 11*46439007SCharles.Forsythin which to write Limbo programs. 12*46439007SCharles.Forsyth.I Limbo (1) 13*46439007SCharles.Forsythis the compiler for the Limbo language; there 14*46439007SCharles.Forsythare versions that run inside and outside the Inferno 15*46439007SCharles.Forsythenvironment. 16*46439007SCharles.Forsyth.I Acme (1) 17*46439007SCharles.Forsythis an integrated window system and editor, and the 18*46439007SCharles.Forsythpreferred source-code editing tool within Inferno. 19*46439007SCharles.ForsythThe Limbo debugger, 20*46439007SCharles.Forsyth.I wm-debug (1), 21*46439007SCharles.Forsythallows interactive inspection of running Limbo programs. 22*46439007SCharles.Forsyth.I Stack (1) 23*46439007SCharles.Forsythallows a quick inspection of the execution stack of a 24*46439007SCharles.Forsythcurrently running process. 25*46439007SCharles.Forsyth.SH 26*46439007SCharles.ForsythGetting started 27*46439007SCharles.Forsyth.PP 28*46439007SCharles.ForsythThis document assumes that you have already managed 29*46439007SCharles.Forsythto install Inferno and have managed to obtain an Inferno 30*46439007SCharles.Forsythwindow, running the Inferno window manager, 31*46439007SCharles.Forsyth.I wm (1). 32*46439007SCharles.ForsythThe document 33*46439007SCharles.Forsyth\&``Installing Inferno'' in this volume has details on this. 34*46439007SCharles.ForsythIf running within emu, it is worth giving Inferno 35*46439007SCharles.Forsythas large a window as possible, as it cannot be resized later. 36*46439007SCharles.ForsythThis paper assumes that you are using a three-button mouse, as it is 37*46439007SCharles.Forsythnot feasible to use Acme without a three-button mouse. 38*46439007SCharles.Forsyth(if you have a two button mouse with a ``mouse wheel'', 39*46439007SCharles.Forsyththe wheel can be used as the middle button). 40*46439007SCharles.ForsythThe first thing to do is to get Acme going. By clicking 41*46439007SCharles.Forsython the Vita Nuova logo at the bottom left of the window, 42*46439007SCharles.Forsythyou can display a menu naming some preconfigured commands. 43*46439007SCharles.ForsythIf this has an ``Acme'' entry, then just clicking on that entry 44*46439007SCharles.Forsythwill start acme. If not, then click on the ``Shell'' entry, 45*46439007SCharles.Forsythand type 46*46439007SCharles.Forsyth.P1 47*46439007SCharles.Forsythacme 48*46439007SCharles.Forsyth.P2 49*46439007SCharles.Forsythto start it up. The Acme window should then appear, 50*46439007SCharles.Forsythfilling most of the screen (the window manager toolbar 51*46439007SCharles.Forsythshould still be visible). 52*46439007SCharles.Forsyth.SH 53*46439007SCharles.ForsythAcme basics 54*46439007SCharles.Forsyth.PP 55*46439007SCharles.ForsythFor a general overview and the rationale behind Acme, see ``Acme: 56*46439007SCharles.ForsythA User Interface for Programmers'', elsewhere in this volume, 57*46439007SCharles.Forsythand for detailed documentation, see 58*46439007SCharles.Forsyth.I acme (1). 59*46439007SCharles.ForsythThe basics are as follows: 60*46439007SCharles.Forsyth.PP 61*46439007SCharles.ForsythAcme windows are text-only and organised into columns. 62*46439007SCharles.ForsythA distinctive feature of Acme is that there are no graphical 63*46439007SCharles.Forsythtitle bars to windows; instead, each window (and additionally 64*46439007SCharles.Forsytheach column, and the whole Acme window itself) has 65*46439007SCharles.Forsytha textual 66*46439007SCharles.Forsyth.I tag , 67*46439007SCharles.Forsythwhich can be edited at will, and is initially primed to contain 68*46439007SCharles.Forsytha few appropriate commands. 69*46439007SCharles.Forsyth.PP 70*46439007SCharles.ForsythAn Acme command is just represented by text; any textual 71*46439007SCharles.Forsythcommand word may be executed simply by clicking with the middle 72*46439007SCharles.Forsythmouse button on the word. (See ``Acme mouse commands'', below). 73*46439007SCharles.ForsythIf Acme recognizes the word that has been clicked on 74*46439007SCharles.Forsythas one of its internal commands (e.g. Put, Undo), then it will take the appropriate 75*46439007SCharles.Forsythaction; otherwise it will run the text as a shell command. 76*46439007SCharles.Forsyth(See 77*46439007SCharles.Forsyth.I sh (1)). 78*46439007SCharles.Forsyth.SH 79*46439007SCharles.ForsythAcme mouse commands 80*46439007SCharles.Forsyth.PP 81*46439007SCharles.ForsythMouse usage within Acme is somewhat more versatile 82*46439007SCharles.Forsyththan in most other window systems. Each of the three 83*46439007SCharles.Forsythmouse buttons has its own action, and there are also 84*46439007SCharles.Forsythactions bound to 85*46439007SCharles.Forsyth.I chords 86*46439007SCharles.Forsythof mouse buttons (i.e. mouse buttons depressed simultaneously). 87*46439007SCharles.ForsythMouse buttons are numbered from left (1) to right (3). 88*46439007SCharles.ForsythButton 1 follows similar conventions to other window systems - 89*46439007SCharles.Forsythit selects text; a double click will select a line if at the beginning or end 90*46439007SCharles.Forsythof a line, or match brackets if on a bracket character, or select 91*46439007SCharles.Forsytha word otherwise. 92*46439007SCharles.ForsythButton 2, as mentioned above, executes an 93*46439007SCharles.ForsythAcme command; a single click with button 2 will execute 94*46439007SCharles.Forsyththe single word under the click, otherwise the swept text 95*46439007SCharles.Forsythwill be executed. 96*46439007SCharles.ForsythButton 3 is a general ``look'' operator; if the text under the 97*46439007SCharles.Forsythclick represents a filename, then Acme will open a new 98*46439007SCharles.Forsythwindow for the file and read it in, otherwise it will search 99*46439007SCharles.Forsythwithin the current window for the next occurrence of the 100*46439007SCharles.Forsythtext. 101*46439007SCharles.ForsythClicking button 2 or button 3 on some text already selected 102*46439007SCharles.Forsythby button 1 causes the click to refer exactly to the text 103*46439007SCharles.Forsythselected, rather than gathering likely-looking characters 104*46439007SCharles.Forsythfrom around the click as is the default. 105*46439007SCharles.Forsyth.PP 106*46439007SCharles.ForsythThere are two mouse chord sequences which are 107*46439007SCharles.Forsythcommonly used in Acme (and you will find that some 108*46439007SCharles.Forsythother programs in the system also recognise these sequences, 109*46439007SCharles.Forsythe.g. 110*46439007SCharles.Forsyth.I wm-sh (1)). 111*46439007SCharles.ForsythThey are both available once some text 112*46439007SCharles.Forsythhas been selected by dragging the mouse with button 1, 113*46439007SCharles.Forsythbut before the button has been released. At this point, 114*46439007SCharles.Forsythtouching button 2 will delete the selected text and save 115*46439007SCharles.Forsythit in Acme's 116*46439007SCharles.Forsyth.I snarf 117*46439007SCharles.Forsythbuffer; clicking button 3 replaces the selected text with the contents 118*46439007SCharles.Forsythof the snarf buffer. Before button 1 has been released, 119*46439007SCharles.Forsyththese two buttons reverse each other's actions, so, for 120*46439007SCharles.Forsythexample, selecting some text with button 1, keeping button 1 121*46439007SCharles.Forsythheld down, then clicking button 2 and button 3 in succession, 122*46439007SCharles.Forsythwill save the selected text in the snarf buffer while leaving the 123*46439007SCharles.Forsythoriginal intact. 124*46439007SCharles.ForsythThe following table summarises the mouse commands in 125*46439007SCharles.ForsythAcme: 126*46439007SCharles.Forsyth.KS 127*46439007SCharles.Forsyth.TS 128*46439007SCharles.Forsythcenter box; 129*46439007SCharles.Forsythl l . 130*46439007SCharles.ForsythB1 Select text. 131*46439007SCharles.ForsythB2 Execute text. 132*46439007SCharles.ForsythB3 Open file or search for text. 133*46439007SCharles.ForsythB1-B2 Cut text. 134*46439007SCharles.ForsythB1-B3 Paste text. 135*46439007SCharles.ForsythB2-B3 Cancel the pending B2 action. 136*46439007SCharles.ForsythB3-B2 Cancel the pending B3 action. 137*46439007SCharles.Forsyth.TE 138*46439007SCharles.Forsyth.ce 139*46439007SCharles.Forsyth.I "Acme mouse command summary" 140*46439007SCharles.Forsyth.KE 141*46439007SCharles.Forsyth 142*46439007SCharles.Forsyth.SH 143*46439007SCharles.ForsythScrolling and resizing Acme windows 144*46439007SCharles.Forsyth.PP 145*46439007SCharles.ForsythThe scroll bars in Acme are somewhat different from 146*46439007SCharles.Forsythconventional scroll bars (including the scroll bars found 147*46439007SCharles.Forsythin other parts of Inferno). Clicking, or dragging, with 148*46439007SCharles.Forsythbutton-2 on the scrollbar acts the most like the conventional 149*46439007SCharles.Forsythbehaviour, namely that the further down the scroll bar 150*46439007SCharles.Forsythyou click, the further down the file you are shown. 151*46439007SCharles.Forsyth.PP 152*46439007SCharles.ForsythTrue to form, however, Acme doesn't omit to make 153*46439007SCharles.Forsyththe other buttons useful: button-1 and button-3 154*46439007SCharles.Forsythmove backwards and forwards through the file respectively. 155*46439007SCharles.ForsythThe nearer the top of the scrollbar the mouse, the 156*46439007SCharles.Forsythslower the movement. Holding one of these buttons 157*46439007SCharles.Forsythdown on the scrollbar will cause the scrolling motion 158*46439007SCharles.Forsythto auto-repeat, so it is easy to scroll gently through the 159*46439007SCharles.Forsythentire file, for instance. 160*46439007SCharles.Forsyth.PP 161*46439007SCharles.ForsythThe small square at the top left of each Acme window is 162*46439007SCharles.Forsyththe handle for resizing the window. Dragging this square 163*46439007SCharles.Forsythfrom one place to another (within Acme) will move the 164*46439007SCharles.Forsythwindow to the new place. A single button click in this square 165*46439007SCharles.Forsythwill grow the window: button 1 grows it a little bit; button 2 166*46439007SCharles.Forsythgrows it as much as possible without obscuring the other 167*46439007SCharles.Forsythwindow titles in the column; button 3 grows it so it covers 168*46439007SCharles.Forsyththe whole column (all other windows in the column are 169*46439007SCharles.Forsythobscured). 170*46439007SCharles.Forsyth.SH 171*46439007SCharles.ForsythCreating a new file 172*46439007SCharles.Forsyth.PP 173*46439007SCharles.ForsythAll Limbo programs are composed of 174*46439007SCharles.Forsyth.I modules 175*46439007SCharles.Forsythand each module is stored in its own file. To write a Limbo 176*46439007SCharles.Forsythprogram, you need to write at least one module, 177*46439007SCharles.Forsyththe Limbo 178*46439007SCharles.Forsyth.I "source file" , 179*46439007SCharles.Forsythwhich will then be compiled into Dis code which can 180*46439007SCharles.Forsyththen be run by the Inferno Virtual Machine (VM). 181*46439007SCharles.ForsythThe first step is to decide where to store the file. 182*46439007SCharles.ForsythWhen Acme starts up, it creates a new window containing 183*46439007SCharles.Forsytha list of all the files in the directory in which it was started 184*46439007SCharles.Forsyth(usually your home directory). As a consequence of the 185*46439007SCharles.Forsythmouse rules above, a click of button-3 on any of those 186*46439007SCharles.Forsythfilenames in that window will open a new window 187*46439007SCharles.Forsythshowing that file or, if it is a directory, a list of the 188*46439007SCharles.Forsythfiles and directories it contains. 189*46439007SCharles.Forsyth.PP 190*46439007SCharles.ForsythAn important aspect in Acme's mouse commands, is 191*46439007SCharles.Forsyththat the command is interpreted 192*46439007SCharles.Forsyth.I "relative to the window's current directory", 193*46439007SCharles.Forsythwhere the current directory is determined from 194*46439007SCharles.Forsyththe filename in the window's tag. For instance, 195*46439007SCharles.ForsythAcme commands executed in the tag or body of 196*46439007SCharles.Forsytha window on the file 197*46439007SCharles.Forsyth.CW "/usr/joebloggs/myfile.txt" 198*46439007SCharles.Forsythwould run in the directory 199*46439007SCharles.Forsyth.CW /usr/joebloggs . 200*46439007SCharles.Forsyth.PP 201*46439007SCharles.ForsythSo, to create a new file in Acme, first open the 202*46439007SCharles.Forsythdirectory in which to create the file. (If this is 203*46439007SCharles.Forsythyour home directory, then it's probably already on the screen; 204*46439007SCharles.Forsythotherwise, you can just type (anywhere) the name of 205*46439007SCharles.Forsyththe directory, and button-3 click on it. If the directory 206*46439007SCharles.Forsythdoes not exist, then no window will be created. 207*46439007SCharles.ForsythThen, within the directory's window or its tag, 208*46439007SCharles.Forsythchoose a name, 209*46439007SCharles.Forsyth.I filename , 210*46439007SCharles.Forsythfor your file (I'll use 211*46439007SCharles.Forsyth.CW myprog 212*46439007SCharles.Forsythfrom here on, 213*46439007SCharles.Forsythfor explanatory convenience) 214*46439007SCharles.Forsyth, type the text: 215*46439007SCharles.Forsyth.P1 216*46439007SCharles.ForsythNew \fIfilename\fP.b 217*46439007SCharles.Forsyth.P2 218*46439007SCharles.Forsythselect this text (the Escape key can also be used to highlight 219*46439007SCharles.Forsythtext that you have just typed), and button-2 click on it. 220*46439007SCharles.ForsythThis should create a new empty window in which you 221*46439007SCharles.Forsythcan edit your Limbo source file. It will also create a 222*46439007SCharles.Forsythwindow giving a warning that the file does not 223*46439007SCharles.Forsythcurrently exist - you can get rid of this by clicking 224*46439007SCharles.Forsythwith button-2 on the text 225*46439007SCharles.Forsyth.CW Del 226*46439007SCharles.Forsythin the tag of that window. 227*46439007SCharles.Forsyth.SH 228*46439007SCharles.ForsythEditing the source file 229*46439007SCharles.Forsyth.PP 230*46439007SCharles.ForsythYou can now edit text in the new window. 231*46439007SCharles.ForsythType in the following program: 232*46439007SCharles.Forsyth.P1 233*46439007SCharles.Forsythimplement Myprog; 234*46439007SCharles.Forsythinclude "sys.m"; 235*46439007SCharles.Forsyth sys: Sys; 236*46439007SCharles.Forsythinclude "draw.m"; 237*46439007SCharles.Forsyth 238*46439007SCharles.ForsythMyprog: module { 239*46439007SCharles.Forsyth init: fn(nil: ref Draw->Context, argv: list of string); 240*46439007SCharles.Forsyth}; 241*46439007SCharles.Forsyth 242*46439007SCharles.Forsythinit(nil: ref Draw->Context, argv: list of string) 243*46439007SCharles.Forsyth{ 244*46439007SCharles.Forsyth sys = load Sys Sys->PATH; 245*46439007SCharles.Forsyth sys->print("Hello, world\en"); 246*46439007SCharles.Forsyth} 247*46439007SCharles.Forsyth.P2 248*46439007SCharles.ForsythWhen typing it in, note that two new commands have appeared 249*46439007SCharles.Forsythin the tag of the new window: 250*46439007SCharles.Forsyth.CW Put 251*46439007SCharles.Forsythand 252*46439007SCharles.Forsyth.CW Undo . 253*46439007SCharles.Forsyth.CW Put 254*46439007SCharles.Forsythsaves the file; 255*46439007SCharles.Forsyth.CW Undo 256*46439007SCharles.Forsythundoes the last change to the file, and successive 257*46439007SCharles.Forsythexecutions of 258*46439007SCharles.Forsyth.CW Undo 259*46439007SCharles.Forsythwill move further back in time. In case you move 260*46439007SCharles.Forsythtoo far back accidentally, there is also 261*46439007SCharles.Forsyth.CW Redo , 262*46439007SCharles.Forsythwhich redoes a change that you have just undone. 263*46439007SCharles.ForsythChanges in the body of any window in Acme can be undone 264*46439007SCharles.Forsyththis way. 265*46439007SCharles.Forsyth.PP 266*46439007SCharles.ForsythClick with button-2 on the 267*46439007SCharles.Forsyth.CW Put 268*46439007SCharles.Forsythcommand, and the file is now saved and ready to be 269*46439007SCharles.Forsythcompiled. If you have problems at this point (say 270*46439007SCharles.ForsythAcme complains about not being able to write the 271*46439007SCharles.Forsythfile), you have probably chosen an inappropriate 272*46439007SCharles.Forsythdirectory, one in which you do not have write permission, 273*46439007SCharles.Forsythin which to put the file. In this case you can change the 274*46439007SCharles.Forsythname of the file simply by editing its name in the window's 275*46439007SCharles.Forsythtag, and clicking on 276*46439007SCharles.Forsyth.CW Put 277*46439007SCharles.Forsythagain. 278*46439007SCharles.Forsyth.SH 279*46439007SCharles.ForsythCompiling the source file 280*46439007SCharles.Forsyth.PP 281*46439007SCharles.ForsythNow, you are in a position to compile the Limbo program. 282*46439007SCharles.ForsythAlthough you can execute the Limbo compiler directly 283*46439007SCharles.Forsythfrom the tag of the new file's window, it is usually more 284*46439007SCharles.Forsythconvenient to do it from a shell window. To start a shell 285*46439007SCharles.Forsythwindow, type 286*46439007SCharles.Forsyth.CW win '' `` 287*46439007SCharles.Forsythat the right of the tag of the new file's window, select 288*46439007SCharles.Forsythit, and click with button-2 on it. 289*46439007SCharles.ForsythA new window should appear showing a shell prompt (usually 290*46439007SCharles.Forsyth.CW "; " '' `` 291*46439007SCharles.Forsythor 292*46439007SCharles.Forsyth.CW "% " ''). `` 293*46439007SCharles.ForsythAt this, you can type any of the commands mentioned 294*46439007SCharles.Forsythin Section 1 of the Programmer's Manual. 295*46439007SCharles.ForsythNote that, following Acme's usual rule, the shell has 296*46439007SCharles.Forsythstarted up in the same directory as the new file; 297*46439007SCharles.Forsythtyping 298*46439007SCharles.Forsyth.P1 299*46439007SCharles.Forsythlc 300*46439007SCharles.Forsyth.P2 301*46439007SCharles.Forsythat the prompt will show all the files in the directory, 302*46439007SCharles.Forsythincluding hopefully the newly written Limbo file. 303*46439007SCharles.Forsyth.PP 304*46439007SCharles.ForsythType the following command to the shell: 305*46439007SCharles.Forsyth.P1 306*46439007SCharles.Forsythlimbo -g myprog.b 307*46439007SCharles.Forsyth.P2 308*46439007SCharles.ForsythIf you typed in the example program correctly, 309*46439007SCharles.Forsyththen you'll get a short pause, and then another shell 310*46439007SCharles.Forsythprompt. This indicates a successful compilation (no 311*46439007SCharles.Forsythnews is good news), in which case you will now have 312*46439007SCharles.Forsythtwo new files in the current directory, 313*46439007SCharles.Forsyth.CW myprog.sbl 314*46439007SCharles.Forsythand 315*46439007SCharles.Forsyth.CW myprog.dis . 316*46439007SCharles.ForsythThe 317*46439007SCharles.Forsyth.CW -g 318*46439007SCharles.Forsythoption to the 319*46439007SCharles.Forsyth.CW limbo 320*46439007SCharles.Forsythcommand directed it to produce the 321*46439007SCharles.Forsyth.CW myprog.sbl 322*46439007SCharles.Forsythfile, which contains symbolic information 323*46439007SCharles.Forsythrelating the source code to the Dis executable file. 324*46439007SCharles.ForsythThe 325*46439007SCharles.Forsyth.CW myprog.dis 326*46439007SCharles.Forsythfile contains the actual executable file. 327*46439007SCharles.ForsythAt this point, if you type 328*46439007SCharles.Forsyth.CW lc , 329*46439007SCharles.Forsythto get a listing of the files in the current directory, 330*46439007SCharles.Forsythand then click with button-2 on the 331*46439007SCharles.Forsyth.CW myprog.dis 332*46439007SCharles.Forsythfile, and you should see the output ``Hello, world''. 333*46439007SCharles.ForsythYou could also just type 334*46439007SCharles.Forsyth.CW myprog 335*46439007SCharles.Forsythat the shell prompt. 336*46439007SCharles.Forsyth.PP 337*46439007SCharles.ForsythIf you are normal, however, the above compilation 338*46439007SCharles.Forsythprobably failed because of some mistyped characters 339*46439007SCharles.Forsythin the source code; and for larger newly created programs, 340*46439007SCharles.Forsythin my experience, this 341*46439007SCharles.Forsythis almost invariably the case. 342*46439007SCharles.ForsythIf you got no errors in the above 343*46439007SCharles.Forsythcompilation, try changing 344*46439007SCharles.Forsyth.CW sys->print 345*46439007SCharles.Forsythto 346*46439007SCharles.Forsyth.CW print , 347*46439007SCharles.Forsythsaving the file again, 348*46439007SCharles.Forsythand continue with the next section. 349*46439007SCharles.Forsyth.SH 350*46439007SCharles.ForsythFinding compilation errors 351*46439007SCharles.Forsyth.PP 352*46439007SCharles.ForsythWhen the Limbo compiler finds errors, it prints 353*46439007SCharles.Forsyththe errors, one per line, each one looking something 354*46439007SCharles.Forsythlike the following: 355*46439007SCharles.Forsyth.P1 356*46439007SCharles.Forsythmyprog.b:13: print is not declared 357*46439007SCharles.Forsyth.P2 358*46439007SCharles.ForsythThis shows the filename where the error has occurred, 359*46439007SCharles.Forsythits line number in the file, and a description of the error. 360*46439007SCharles.ForsythAcme's button-3 mouse clicking makes it extremely easy 361*46439007SCharles.Forsythto see where in the source code the error has occurred. 362*46439007SCharles.ForsythClick with button-3 anywhere in the filename on the 363*46439007SCharles.Forsythline of the compilation error, and Acme will automatically 364*46439007SCharles.Forsythtake the cursor to the file of that name and highlight 365*46439007SCharles.Forsyththe correct line. 366*46439007SCharles.Forsyth.PP 367*46439007SCharles.ForsythIf there had been no currently appropriate open Acme 368*46439007SCharles.Forsythwindow representing the file, then a new one would 369*46439007SCharles.Forsythbe created, and the appropriate line selected. 370*46439007SCharles.Forsyth.PP 371*46439007SCharles.ForsythEdit 372*46439007SCharles.Forsyth.CW myprog.b 373*46439007SCharles.Forsythuntil you have a program that compiles successfully 374*46439007SCharles.Forsythand produces the ``Hello, world'' output. 375*46439007SCharles.ForsythFor a program as simple as this, that's all there 376*46439007SCharles.Forsythis to it - you now know the essential stages involved in 377*46439007SCharles.Forsythwriting a Limbo program; there's just the small matter 378*46439007SCharles.Forsythof absorbing the Limbo language and familiarising 379*46439007SCharles.Forsythyourself with the libraries (``The Limbo Programming Language'' 380*46439007SCharles.Forsythelsewhere in this volume, 381*46439007SCharles.Forsythand 382*46439007SCharles.Forsyth.I intro (2) 383*46439007SCharles.Forsythare the two essential starting points here). 384*46439007SCharles.Forsyth.SH 385*46439007SCharles.ForsythFinding run-time errors 386*46439007SCharles.Forsyth.PP 387*46439007SCharles.ForsythFor larger programs, there is the problem of programs 388*46439007SCharles.Forsyththat die unexpectedly with a run-time error. This 389*46439007SCharles.Forsythwill happen when, for instance, a Limbo program uses a reference 390*46439007SCharles.Forsyththat has not been initialised, or refers to an out-of-bounds 391*46439007SCharles.Forsytharray element. 392*46439007SCharles.Forsyth.PP 393*46439007SCharles.ForsythWhen a Limbo program dies with a run-time exception, 394*46439007SCharles.Forsythit does not go away completely, but remains hanging 395*46439007SCharles.Forsytharound, dormant, in a 396*46439007SCharles.Forsyth.I broken 397*46439007SCharles.Forsythstate; the state that it was in when it died may 398*46439007SCharles.Forsythnow be examined at leisure. To experiment with this, 399*46439007SCharles.Forsythedit the Myprog module above to delete the line 400*46439007SCharles.Forsyththat loads the 401*46439007SCharles.Forsyth.CW Sys 402*46439007SCharles.Forsythmodule 403*46439007SCharles.Forsyth.CW "sys = load Sys" ...), ( 404*46439007SCharles.Forsythand recompile the program. 405*46439007SCharles.Forsyth.PP 406*46439007SCharles.ForsythThis time when you come to run 407*46439007SCharles.Forsyth.CW myprog , 408*46439007SCharles.Forsythit will die, printing a message like: 409*46439007SCharles.Forsyth.P1 410*46439007SCharles.Forsythsh: 319 "Myprog":module not loaded 411*46439007SCharles.Forsyth.P2 412*46439007SCharles.ForsythThe number 413*46439007SCharles.Forsyth.CW 319 414*46439007SCharles.Forsythis the 415*46439007SCharles.Forsyth.I "process id" 416*46439007SCharles.Forsyth(or just 417*46439007SCharles.Forsyth.I pid ) 418*46439007SCharles.Forsythof the broken process. The command 419*46439007SCharles.Forsyth.CW ps , 420*46439007SCharles.Forsythwhich shows all currently running processes, 421*46439007SCharles.Forsythcan be used at this point - you will see a line like this: 422*46439007SCharles.Forsyth.P1 423*46439007SCharles.Forsyth 319 245 rog broken 64K Myprog 424*46439007SCharles.Forsyth.P2 425*46439007SCharles.ForsythThe first number is the pid of the process; 426*46439007SCharles.Forsyththe second is the 427*46439007SCharles.Forsyth.I "process group" 428*46439007SCharles.Forsythid of the process; the third field gives the 429*46439007SCharles.Forsythowner of the process; the fourth gives its state 430*46439007SCharles.Forsyth(broken, in this case); the fifth shows the current 431*46439007SCharles.Forsythsize of the process, and the last gives the name 432*46439007SCharles.Forsythof the module that the process is currently running. 433*46439007SCharles.Forsyth.PP 434*46439007SCharles.ForsythThe 435*46439007SCharles.Forsyth.CW stack 436*46439007SCharles.Forsythcommand can be used to quickly find the line 437*46439007SCharles.Forsythat which the process has broken; type: 438*46439007SCharles.Forsyth.P1 439*46439007SCharles.Forsyth stack \fIpid\fP 440*46439007SCharles.Forsyth.P2 441*46439007SCharles.Forsythwhere 442*46439007SCharles.Forsyth.I pid 443*46439007SCharles.Forsythis the number mentioned in the ``module not loaded'' 444*46439007SCharles.Forsythmessage (319 in this case). 445*46439007SCharles.ForsythIt produces something like the following output: 446*46439007SCharles.Forsyth.P1 447*46439007SCharles.Forsythinit() myprog.b:12.1, 29 448*46439007SCharles.Forsythunknown fn() Module /dis/sh.dis PC 1706 449*46439007SCharles.Forsyth.P2 450*46439007SCharles.ForsythAs usual, a quick button-3 click on the 451*46439007SCharles.Forsyth.CW myprog.b 452*46439007SCharles.Forsythpart of the first line takes you to the appropriate 453*46439007SCharles.Forsythpart of the source file. The reason that the program 454*46439007SCharles.Forsythhas died here is that, in Limbo, all external modules 455*46439007SCharles.Forsythmust be explicitly loaded before they can be used; to 456*46439007SCharles.Forsythtry to call an uninitialised module is an error 457*46439007SCharles.Forsythand causes an exception. 458*46439007SCharles.Forsyth.SH 459*46439007SCharles.ForsythMore sophisticated debugging 460*46439007SCharles.Forsyth.PP 461*46439007SCharles.Forsyth.CW Stack 462*46439007SCharles.Forsythis fine for getting a quick summary of the state 463*46439007SCharles.Forsythin which a program has died, but there are 464*46439007SCharles.Forsythtimes when such a simple post-mortem analysis 465*46439007SCharles.Forsythis inadequate. The 466*46439007SCharles.Forsyth.CW wm/deb 467*46439007SCharles.Forsyth(see 468*46439007SCharles.Forsyth.I wm-deb\fR(1))\fP 469*46439007SCharles.Forsythcommand provides an interactive windowing 470*46439007SCharles.Forsythdebugger for such occasions. 471*46439007SCharles.ForsythIt runs outside Acme, 472*46439007SCharles.Forsythin the default window system. A convenient way 473*46439007SCharles.Forsythto start debugging an existing process is 474*46439007SCharles.Forsythto raise 475*46439007SCharles.Forsyth.CW wm/task 476*46439007SCharles.Forsyth(``Task Manager'' on the 477*46439007SCharles.Forsythmain menu), select with the mouse the process 478*46439007SCharles.Forsythto debug, and click ``Debug''. This will start 479*46439007SCharles.Forsyth.CW wm/deb 480*46439007SCharles.Forsython that process. Before it can start, the debugger will ask 481*46439007SCharles.Forsythfor the names of any source files that it has not been 482*46439007SCharles.Forsythable to find (usually this includes the source for 483*46439007SCharles.Forsyththe shell, as the module being debugged is often 484*46439007SCharles.Forsythstarted by the shell, and so the top-level function will 485*46439007SCharles.Forsythbe in the shell's module). 486*46439007SCharles.Forsyth.PP 487*46439007SCharles.Forsyth.CW Wm/deb 488*46439007SCharles.Forsythcan be used to debug multiple threads, to inspect 489*46439007SCharles.Forsyththe data structures in a thread, and to interactively 490*46439007SCharles.Forsythstep through the running of a thread (single stepping). 491*46439007SCharles.ForsythSee 492*46439007SCharles.Forsyth.I wm-deb (1) 493*46439007SCharles.Forsythfor details. 494*46439007SCharles.Forsyth 495*46439007SCharles.Forsyth\" further afield? 496*46439007SCharles.Forsyth\" other development tools? 497*46439007SCharles.Forsyth\" tools to come? 498