| 1 | .if \n(xx .bp |
| 2 | .if !\n(xx \{\ |
| 3 | .so tmac.p \} |
| 4 | 'if n 'ND |
| 5 | .nr H1 1 |
| 6 | .NH |
| 7 | Basic UNIX Pascal |
| 8 | .PP |
| 9 | The following sections |
| 10 | explain the basics of using |
| 11 | .UP . |
| 12 | In examples here we use the text editor |
| 13 | .I ex |
| 14 | (6). |
| 15 | Users of the text editor |
| 16 | .I ed |
| 17 | should have little trouble following these examples, |
| 18 | as |
| 19 | .I ex |
| 20 | is similar to |
| 21 | .I ed . |
| 22 | We use |
| 23 | .I ex |
| 24 | because it |
| 25 | allows us to make clearer examples.\(dg |
| 26 | .FS |
| 27 | \(dg Users with \s-2CRT\s0 terminals should find the editor |
| 28 | .I vi |
| 29 | more pleasant to use; |
| 30 | we do not show its use here because its display oriented nature |
| 31 | makes it difficult to illustrate. |
| 32 | .FE |
| 33 | The new |
| 34 | .UX |
| 35 | user will find it helpful to read one of the text editor documents |
| 36 | described in section 1.4 before continuing with this section. |
| 37 | .NH 2 |
| 38 | A first program |
| 39 | .PP |
| 40 | To prepare a program for |
| 41 | .UP |
| 42 | we first need to have an account on |
| 43 | .UX |
| 44 | and to `login' |
| 45 | to the system on this account. |
| 46 | These procedures are described in the documents |
| 47 | .I "Communicating with UNIX" |
| 48 | and |
| 49 | .I "UNIX for Beginners". |
| 50 | .PP |
| 51 | Once we are logged in we need to choose a name for our program; |
| 52 | let us call it `first' as this is the first example. |
| 53 | We must also choose a name for the file in which the program will be stored. |
| 54 | The |
| 55 | .UP |
| 56 | system requires that programs reside in files which have names ending with |
| 57 | the sequence `.p' so we will call our file `first.p'. |
| 58 | .PP |
| 59 | A sample editing session to create this file would begin: |
| 60 | .LS |
| 61 | % \*bex first.p\fR |
| 62 | "first.p" No such file or directory |
| 63 | : |
| 64 | .LE |
| 65 | We didn't expect the file to exist, so the error diagnostic doesn't |
| 66 | bother us. |
| 67 | The editor now knows the name of the file we are creating. |
| 68 | The `:' prompt indicates that it is ready for command input. |
| 69 | We can add the text for our program using the `append' |
| 70 | command as follows. |
| 71 | .LS |
| 72 | :\*bappend\fR |
| 73 | .B |
| 74 | program first(output) |
| 75 | begin |
| 76 | writeln('Hello, world!') |
| 77 | end. |
| 78 | \&. |
| 79 | .R |
| 80 | : |
| 81 | .LE |
| 82 | The line containing the single `\*b.\fR' character here indicated |
| 83 | the end of the appended text. |
| 84 | The `:' prompt indicates that |
| 85 | .I ex |
| 86 | is ready for another command. |
| 87 | As the editor operates in a temporary work space we must now store the contents |
| 88 | of this work space in the file `first.p' |
| 89 | so we can use the Pascal |
| 90 | translator and executor |
| 91 | .IX |
| 92 | on it. |
| 93 | .LS |
| 94 | :\*bwrite\fR |
| 95 | "first.p" 4 lines, 59 characters |
| 96 | :\*bquit\fR |
| 97 | % |
| 98 | .LE |
| 99 | We wrote out the file from the edit buffer here with the |
| 100 | `write' |
| 101 | command, and |
| 102 | .I ex |
| 103 | indicated the number of lines and characters written. |
| 104 | We then quit the editor, and now have a prompt from the shell.\(dd |
| 105 | .FS |
| 106 | \(dd Our examples here assume you are using |
| 107 | .I csh. |
| 108 | .FE |
| 109 | .KS |
| 110 | .PP |
| 111 | We are ready to try |
| 112 | to translate and execute our program. |
| 113 | .DS |
| 114 | .tr '\(aa^\(ua |
| 115 | % \*bpix first.p\fR |
| 116 | .so firstout |
| 117 | .tr ''^^ |
| 118 | % |
| 119 | .DE |
| 120 | .KE |
| 121 | .PP |
| 122 | The translator first printed a syntax error diagnostic. |
| 123 | The number 2 here indicates that the rest of the line is an image |
| 124 | of the second line of our program. |
| 125 | The translator is saying that it expected to find a `;' before the |
| 126 | keyword |
| 127 | .B begin |
| 128 | on this line. |
| 129 | If we look at the Pascal syntax charts in the Jensen-Wirth |
| 130 | .I "User Manual" , |
| 131 | or at some of the sample programs therein, we will see that |
| 132 | we have omitted the terminating `;' of the |
| 133 | .B program |
| 134 | statement on the first |
| 135 | line of our program. |
| 136 | .PP |
| 137 | One other thing to notice about the error diagnostic is the letter `e' |
| 138 | at the beginning. |
| 139 | It stands for `error', |
| 140 | indicating that our input was not legal Pascal. |
| 141 | The fact that it is an `e' rather than an `E' |
| 142 | indicates that the translator managed to recover from this error well |
| 143 | enough that generation of code and execution could take place. |
| 144 | Execution is possible whenever no fatal `E' errors |
| 145 | occur during translation. |
| 146 | The other classes of diagnostics are `w' warnings, |
| 147 | which do not necessarily indicate errors in the program, |
| 148 | but point out inconsistencies which are likely to be due to program bugs, |
| 149 | and `s' standard-Pascal violations.\*(dg |
| 150 | .FS |
| 151 | \*(dgThe standard Pascal warnings occur only when the associated |
| 152 | .B s |
| 153 | translator option is enabled. |
| 154 | The |
| 155 | .B s |
| 156 | option is discussed in sections 5.1 and A.6 below. |
| 157 | Warning diagnostics are discussed at the end of section 3.2, |
| 158 | the associated |
| 159 | .B w |
| 160 | option is described in section 5.2. |
| 161 | .FE |
| 162 | .PP |
| 163 | After completing the translation of the program to interpretive code, |
| 164 | the Pascal system indicates that execution of the translated program began. |
| 165 | The output from the execution of the program then appeared. |
| 166 | At program termination, the Pascal runtime system indicated the |
| 167 | number of statements executed, and the amount of cpu time |
| 168 | used, with the resolution of the latter being 1/60'th of a second. |
| 169 | .PP |
| 170 | Let us now fix the error in the program and translate it to a permanent |
| 171 | object code file |
| 172 | .I obj |
| 173 | using |
| 174 | .PI . |
| 175 | The program |
| 176 | .PI |
| 177 | translates Pascal programs but stores the object code instead of executing it\*(dd. |
| 178 | .FS |
| 179 | \*(ddThis script indicates some other useful approaches to debugging |
| 180 | Pascal programs. |
| 181 | As in |
| 182 | .I ed |
| 183 | we can shorten commands in |
| 184 | .I ex |
| 185 | to an initial prefix of the command name as we did |
| 186 | with the |
| 187 | .I substitute |
| 188 | command here. |
| 189 | We have also used the `!' shell escape command here to execute other |
| 190 | commands with a shell without leaving the editor. |
| 191 | .FE |
| 192 | .LS |
| 193 | % \*bex first.p\fR |
| 194 | "first.p" 4 lines, 59 characters |
| 195 | :\*b1 print\fR |
| 196 | program first(output) |
| 197 | :\*bs/$/;\fR |
| 198 | program first(output); |
| 199 | :\*bwrite\fR |
| 200 | "first.p" 4 lines, 60 characters |
| 201 | :\*b!pi %\fR |
| 202 | !pi first.p |
| 203 | ! |
| 204 | :\*bquit\fR |
| 205 | % |
| 206 | .LE |
| 207 | The first command issued from |
| 208 | .I ex |
| 209 | with the `!' |
| 210 | involved the use of the `%' character which stands in this command for |
| 211 | the file we are editing. |
| 212 | .I Ex |
| 213 | made this substitution, and then echoed back the expanded line |
| 214 | before executing the command. |
| 215 | When the command finished, the editor echoed the character `!' |
| 216 | so that we would know it was done. |
| 217 | .PP |
| 218 | If we now use the |
| 219 | .UX |
| 220 | .I ls |
| 221 | list files command we can see what files we have: |
| 222 | .LS |
| 223 | % \*bls\fR |
| 224 | first.p |
| 225 | obj |
| 226 | % |
| 227 | .LE |
| 228 | The file `obj' here contains the Pascal interpreter code. |
| 229 | We can execute this by typing: |
| 230 | .LS |
| 231 | % \*bpx obj\fR |
| 232 | .so firstobjout |
| 233 | % |
| 234 | .LE |
| 235 | Alternatively, the command: |
| 236 | .LS |
| 237 | % \*bobj\fR |
| 238 | .LE |
| 239 | will have the same effect. |
| 240 | Some examples of different ways to execute the program follow. |
| 241 | .LS |
| 242 | % \*bpx\fR |
| 243 | .so firstobjout |
| 244 | % \*bpi -p first.p\fR |
| 245 | % \*bpx obj\fR |
| 246 | .so firstobjout2 |
| 247 | % \*bpix -p first.p\fR |
| 248 | .so firstobjout2 |
| 249 | % |
| 250 | .LE |
| 251 | .PP |
| 252 | Note that |
| 253 | .I px |
| 254 | will assume that `obj' is the file we wish to execute |
| 255 | if we don't tell it otherwise. |
| 256 | The last two translations use the |
| 257 | .B \-p |
| 258 | no-post-mortem option to eliminate |
| 259 | execution statistics and |
| 260 | `Execution begins' |
| 261 | and |
| 262 | `Execution terminated' |
| 263 | messages. |
| 264 | See section 5.2 for more details. |
| 265 | If we now look at the files in our directory we will see: |
| 266 | .LS |
| 267 | % \*bls\fR |
| 268 | first.p |
| 269 | obj |
| 270 | % |
| 271 | .LE |
| 272 | We can give our object program a name other than `obj' by using the move |
| 273 | command |
| 274 | .I mv |
| 275 | (1). |
| 276 | Thus to name our program `hello': |
| 277 | .LS |
| 278 | % \*bmv obj hello\fR |
| 279 | % \*bhello\fR |
| 280 | Hello, world! |
| 281 | % \*bls\fR |
| 282 | first.p |
| 283 | hello |
| 284 | % |
| 285 | .LE |
| 286 | .KS |
| 287 | Finally we can get rid of the Pascal object code by using the |
| 288 | .I rm |
| 289 | (1) remove file command, e.g.: |
| 290 | .LS |
| 291 | % \*brm hello\fR |
| 292 | % \*bls\fR |
| 293 | first.p |
| 294 | % |
| 295 | .LE |
| 296 | .KE |
| 297 | .PP |
| 298 | For small programs which are being developed |
| 299 | .IX |
| 300 | tends to be more convenient to use than |
| 301 | .PI |
| 302 | and |
| 303 | .X . |
| 304 | Except for absence of the |
| 305 | .I obj |
| 306 | file after a |
| 307 | .IX |
| 308 | run, |
| 309 | a |
| 310 | .IX |
| 311 | command is equivalent to a |
| 312 | .PI |
| 313 | command followed by a |
| 314 | .X |
| 315 | command. |
| 316 | For larger programs, |
| 317 | where a number of runs testing different parts of the program are |
| 318 | to be made, |
| 319 | .PI |
| 320 | is useful as this |
| 321 | .I obj |
| 322 | file can be executed any desired number of times. |
| 323 | .NH 2 |
| 324 | A larger program |
| 325 | .PP |
| 326 | Suppose that we have used the editor to put a larger program |
| 327 | in the file `bigger.p'. |
| 328 | We can list this program with line numbers by using the program |
| 329 | .I num |
| 330 | i.e.: |
| 331 | .LS |
| 332 | % \*bnum bigger.p\fR |
| 333 | .so bigger3.p |
| 334 | % |
| 335 | .LE |
| 336 | This program is similar to program 4.9 on page 30 of the |
| 337 | Jensen-Wirth |
| 338 | .I "User Manual" . |
| 339 | A number of problems have been introduced into this example for |
| 340 | pedagogical reasons. |
| 341 | .br |
| 342 | .ne 8 |
| 343 | .PP |
| 344 | If we attempt to translate and execute the program using |
| 345 | .IX |
| 346 | we get the following response: |
| 347 | .LS |
| 348 | % \*bpix bigger.p\fR |
| 349 | .so bigout1 |
| 350 | % |
| 351 | .LE |
| 352 | .PP |
| 353 | Since there were fatal `E' errors in our program, |
| 354 | no code was generated and execution was necessarily suppressed. |
| 355 | One thing which would be useful at this point is a listing of the |
| 356 | program with the error messages. |
| 357 | We can get this by using the command: |
| 358 | .LS |
| 359 | % \*bpi -l bigger.p\fR |
| 360 | .LE |
| 361 | There is no point in using |
| 362 | .IX |
| 363 | here, since we know there are fatal errors in the program. |
| 364 | This command will produce the output at our terminal. |
| 365 | If we are at a terminal which does not produce a hard copy |
| 366 | we may wish to print this |
| 367 | listing off-line on a line printer\*(dg. |
| 368 | .FS |
| 369 | \*(dgAt Berkeley, the line printer for the Cory Hall system is in Room 199B. |
| 370 | The line printers for the Computer Center |
| 371 | systems are in the basement of Evans Hall. |
| 372 | .FE |
| 373 | We can do this with the command: |
| 374 | .LS |
| 375 | % \*bpi -l bigger.p | lpr\fR |
| 376 | .LE |
| 377 | .PP |
| 378 | In the next few sections we will illustrate various aspects of the |
| 379 | Berkeley |
| 380 | Pascal system by correcting this program. |
| 381 | .NH 2 |
| 382 | Correcting the first errors |
| 383 | .PP |
| 384 | Most of the errors which occurred in this program were |
| 385 | .I syntactic |
| 386 | errors, those in the format and structure of the program rather than |
| 387 | its content. |
| 388 | Syntax errors are flagged by printing the offending line, and then a line |
| 389 | which flags the location at which an error was detected. |
| 390 | The flag line also gives an explanation |
| 391 | stating either a possible cause of the error, |
| 392 | a simple action which can be taken to recover from the error so |
| 393 | as to be able to continue the analysis, |
| 394 | a symbol which was expected at the point of error, |
| 395 | or an indication that the input was `malformed'. |
| 396 | In the last case, the recovery may skip ahead in the input |
| 397 | to a point where analysis of the program can continue. |
| 398 | .PP |
| 399 | In this example, |
| 400 | the first error diagnostic indicates that the translator detected |
| 401 | a comment within a comment. |
| 402 | While this is not considered an error in `standard' |
| 403 | Pascal, it usually corresponds to an error in the program which |
| 404 | is being translated. |
| 405 | In this case, we have accidentally omitted the trailing `*)' of the comment |
| 406 | on line 8. |
| 407 | We can begin an editor session to correct this problem by doing: |
| 408 | .LS |
| 409 | % \*bex bigger.p\fR |
| 410 | "bigger.p" 24 lines, 512 characters |
| 411 | :\*b8s/$/ *)\fR |
| 412 | s = 32; (* 32 character width for interval [x, x+1] *) |
| 413 | : |
| 414 | .LE |
| 415 | .PP |
| 416 | The second diagnostic, given after line 16, |
| 417 | indicates that the keyword |
| 418 | .B do |
| 419 | was expected before the keyword |
| 420 | .B begin |
| 421 | in the |
| 422 | .B for |
| 423 | statement. |
| 424 | If we examine the |
| 425 | .I statement |
| 426 | syntax chart on page 118 of the |
| 427 | Jensen-Wirth |
| 428 | .I "User Manual" |
| 429 | we will discover that |
| 430 | .B do |
| 431 | is a necessary part of the |
| 432 | .B for |
| 433 | statement. |
| 434 | Similarly, we could have referred to section C.3 of the |
| 435 | Jensen-Wirth |
| 436 | .I "User Manual" |
| 437 | to learn about the |
| 438 | .B for |
| 439 | statement and gotten the same information there. |
| 440 | It is often useful to refer to these syntax charts and to the |
| 441 | relevant sections of this book. |
| 442 | .PP |
| 443 | We can correct this problem by first scanning for the keyword |
| 444 | .B for |
| 445 | in the file and then substituting the keyword |
| 446 | .B do |
| 447 | to appear in front of the keyword |
| 448 | .B begin |
| 449 | there. |
| 450 | Thus: |
| 451 | .LS |
| 452 | :\*b/for\fR |
| 453 | for i := 0 to lim begin |
| 454 | :\*bs/begin/do &\fR |
| 455 | for i := 0 to lim do begin |
| 456 | : |
| 457 | .LE |
| 458 | The next error in the program is easy to pinpoint. |
| 459 | On line 18, we didn't hit the shift key and got a `9' |
| 460 | instead of a `)'. |
| 461 | The translator diagnosed that `x9' |
| 462 | was an undefined variable and, later, |
| 463 | that a `)' was missing in the statement. |
| 464 | It should be stressed that |
| 465 | .PI |
| 466 | is not suggesting that you should insert a `)' before the `;'. |
| 467 | It is only indicating that making this change will help it to be able to |
| 468 | continue analyzing the program so as to be able to diagnose further |
| 469 | errors. |
| 470 | You must then determine the true cause of the error and make the |
| 471 | appropriate correction to the source text. |
| 472 | .PP |
| 473 | This error also illustrates the fact that one error in the input may lead |
| 474 | to multiple error diagnostics. |
| 475 | .I Pi |
| 476 | attempts |
| 477 | to give only one diagnostic for each error, |
| 478 | but single errors in the input sometimes appear to be more than |
| 479 | one error. |
| 480 | It is also the case that |
| 481 | .PI |
| 482 | may not detect an error when it occurs, but may detect it later in |
| 483 | the input. |
| 484 | This would have happened |
| 485 | in this example if we had typed `x' instead of `x9'. |
| 486 | .PP |
| 487 | The translator next detected, on line 19, that the function |
| 488 | .I Round |
| 489 | and the variable |
| 490 | .I h |
| 491 | were undefined. |
| 492 | It does not know about |
| 493 | .I Round |
| 494 | because |
| 495 | .UP |
| 496 | normally distinguishes between upper- and lower-case. |
| 497 | On |
| 498 | .UX |
| 499 | lower-case is preferred\*(dg, |
| 500 | .FS |
| 501 | \*(dgOne good reason for using lower-case is that it is easier to type. |
| 502 | .FE |
| 503 | and all keywords and built-in |
| 504 | .B procedure |
| 505 | and |
| 506 | .B function |
| 507 | names are composed of lower-case letters, |
| 508 | just as they are in the Jensen-Wirth |
| 509 | .I "Pascal Report" . |
| 510 | Thus we need to use the function |
| 511 | .I round |
| 512 | here. |
| 513 | As far as |
| 514 | .I h |
| 515 | is concerned, |
| 516 | we can see why it is undefined if we look back to line 9 |
| 517 | and note that its definition was lost in the non-terminated |
| 518 | comment. |
| 519 | This diagnostic need not, therefore, concern us. |
| 520 | .PP |
| 521 | The next error which occurred in the program caused the translator |
| 522 | to insert a `;' before the statement calling |
| 523 | .I writeln |
| 524 | on line 23. |
| 525 | If we examine the program around the point of error we will see |
| 526 | that the actual error is that the keyword |
| 527 | .B until |
| 528 | and an associated expression have been omitted here. |
| 529 | Note that the diagnostic from the translator does not indicate the actual |
| 530 | error, and is somewhat misleading. |
| 531 | The translator made the correction which seemed to be most plausible. |
| 532 | As the omission of a `;' character is a common mistake, |
| 533 | the translator chose to indicate this as a possible fix here. |
| 534 | It later detected that the keyword |
| 535 | .B until |
| 536 | was missing, but not until it saw the keyword |
| 537 | .B end |
| 538 | on line 24. |
| 539 | The combination of these diagnostics indicate to us the true problem. |
| 540 | .PP |
| 541 | The final syntactic error message indicates that the translator needed an |
| 542 | .B end |
| 543 | keyword to match the |
| 544 | .B begin |
| 545 | at line 15. |
| 546 | Since the |
| 547 | .B end |
| 548 | at line 24 is supposed to match this |
| 549 | .B begin , |
| 550 | we can infer that another |
| 551 | .B begin |
| 552 | must have been mismatched, and have matched this |
| 553 | .B end . |
| 554 | Thus we see that we need an |
| 555 | .B end |
| 556 | to match the |
| 557 | .B begin |
| 558 | at line 16, |
| 559 | and to appear before the final |
| 560 | .B end . |
| 561 | We can make these corrections: |
| 562 | .LS |
| 563 | :\*b/x9/s//x)\fR |
| 564 | y := exp(-x) * sin(i * x); |
| 565 | :\*b+s/Round/round\fR |
| 566 | n := round(s * y) + h; |
| 567 | :\*b/write\fR |
| 568 | write(' '); |
| 569 | :\*b/\fR |
| 570 | writeln('*') |
| 571 | :\*binsert\fR |
| 572 | \*buntil n = 0;\fR |
| 573 | \&\*b.\fR |
| 574 | :\*b$\fR |
| 575 | end. |
| 576 | :\*binsert\fR |
| 577 | \*bend\fR |
| 578 | \&\*b.\fR |
| 579 | : |
| 580 | .LE |
| 581 | .PP |
| 582 | At the end of each |
| 583 | .B procedure |
| 584 | or |
| 585 | .B function |
| 586 | and the end of the |
| 587 | .B program |
| 588 | the translator summarizes references to undefined variables |
| 589 | and improper usages of variables. |
| 590 | It also gives |
| 591 | warnings about potential errors. |
| 592 | In our program, the summary errors do not indicate any further problems |
| 593 | but the warning that |
| 594 | .I c |
| 595 | is unused is somewhat suspicious. |
| 596 | Examining the program we see that the constant was intended |
| 597 | to be used in the expression which is an argument to |
| 598 | .I sin , |
| 599 | so we can correct this expression, and translate the program. |
| 600 | We have now made a correction for each diagnosed error |
| 601 | in our program. |
| 602 | .LS |
| 603 | :\*b?i ?s//c /\fR |
| 604 | y := exp(-x) * sin(c * x); |
| 605 | :\*bwrite\fR |
| 606 | "bigger.p" 26 lines, 538 characters |
| 607 | :\*b!pi %\fR |
| 608 | !pi bigger.p |
| 609 | ! |
| 610 | :\*bquit\fR |
| 611 | % |
| 612 | .LE |
| 613 | It should be noted that the translator suppresses warning |
| 614 | diagnostics for a particular |
| 615 | .B procedure , |
| 616 | .B function |
| 617 | or the main |
| 618 | .B program |
| 619 | when it finds severe syntax errors in that part of the source |
| 620 | text. |
| 621 | This is to prevent possibly confusing and |
| 622 | incorrect warning diagnostics from being produced. |
| 623 | Thus these warning diagnostics may not appear in a program with |
| 624 | bad syntax errors until these errors are corrected. |
| 625 | .KS |
| 626 | .PP |
| 627 | We are now ready to execute our program for the first |
| 628 | time. |
| 629 | We will do so in the next section after giving a listing |
| 630 | of the corrected program for reference purposes. |
| 631 | .ne 15 |
| 632 | .LS |
| 633 | % \*bnumber bigger.p\fR |
| 634 | .so bigger6.p |
| 635 | % |
| 636 | .LE |
| 637 | .NH 2 |
| 638 | Executing the second example |
| 639 | .PP |
| 640 | We are now ready to execute the second example. |
| 641 | The following output was produced by our first run. |
| 642 | .LS |
| 643 | % \*bpx\fR |
| 644 | .so bigout2 |
| 645 | % |
| 646 | .LE |
| 647 | Here the interpreter is presenting us with a runtime error diagnostic. |
| 648 | It detected a `division by zero' at line 17. |
| 649 | Examining line 17, we see that we have written |
| 650 | the statement `x := d / i' instead of `x := d * i'. |
| 651 | We can correct this and rerun the program: |
| 652 | .ne 10 |
| 653 | .LS |
| 654 | % \*bex bigger.p\fR |
| 655 | "bigger.p" 26 lines, 538 characters |
| 656 | :\*b17\fR |
| 657 | x := d / i |
| 658 | :\*bs'/'*\fR |
| 659 | x := d * i |
| 660 | :\*bwrite\fR |
| 661 | "bigger.p" 26 lines, 538 characters |
| 662 | :\*b!pix %\fR |
| 663 | !pix bigger.p |
| 664 | .so bigout3 |
| 665 | ! |
| 666 | :\*bq\fR |
| 667 | % |
| 668 | .LE |
| 669 | .KS |
| 670 | .PP |
| 671 | This appears to be the output we wanted. |
| 672 | We could now save the output in a file if we wished by using the shell |
| 673 | to redirect the output: |
| 674 | .LS |
| 675 | % \*bpx > graph\fR |
| 676 | .LE |
| 677 | .KE |
| 678 | We can use |
| 679 | .I cat |
| 680 | (1) to see the contents of the file graph. |
| 681 | We can also make a listing of the graph on the line printer without |
| 682 | putting it into a file, e.g. |
| 683 | .LS |
| 684 | % \*bpx | lpr\fR |
| 685 | .so bigout4 |
| 686 | % |
| 687 | .LE |
| 688 | Note here that the statistics lines came out on our terminal. |
| 689 | The statistics line comes out on the diagnostic output (unit 2.) |
| 690 | There are two ways to get rid of the statistics line. |
| 691 | We can redirect the statistics message to the printer using the |
| 692 | syntax `|\|&' to the shell rather than `|', i.e.: |
| 693 | .LS |
| 694 | % \*bpx |\|& lpr\fR |
| 695 | % |
| 696 | .LE |
| 697 | or we can translate the program with the |
| 698 | .B p |
| 699 | option disabled on the command line as we did above. |
| 700 | This will disable all post-mortem dumping including the statistics line, |
| 701 | thus: |
| 702 | .LS |
| 703 | % \*bpi -p bigger.p\fR |
| 704 | % \*bpx | lpr\fR |
| 705 | % |
| 706 | .LE |
| 707 | This option also disables the statement limit which normally guards |
| 708 | against infinite looping. |
| 709 | You should not use it until your program is debugged. |
| 710 | Also if |
| 711 | .B p |
| 712 | is specified and an error occurs, you will |
| 713 | not get run time diagnostic information to help you |
| 714 | determine what the problem is. |
| 715 | .NH 2 |
| 716 | Formatting the program listing |
| 717 | .PP |
| 718 | It is possible to use special lines within the source text of a program |
| 719 | to format the program listing. |
| 720 | An empty line (one with no characters on it) corresponds to a |
| 721 | `space' macro in an assembler, leaving a completely blank line |
| 722 | without a line number. |
| 723 | A line containing only a control-l (form-feed) character |
| 724 | will cause a page eject in the listing with the corresponding line number |
| 725 | suppressed. |
| 726 | This corresponds to an `eject' pseudo-instruction. |
| 727 | See also section 5.2 for details on the |
| 728 | .B n |
| 729 | and |
| 730 | .B i |
| 731 | options of |
| 732 | .PI . |
| 733 | .NH 2 |
| 734 | Execution profiling |
| 735 | .PP |
| 736 | An execution profile consists of a structured listing of (all or part of) |
| 737 | a program with information about the number of times each statement in |
| 738 | the program was executed for a particular run of the program. |
| 739 | These profiles can be used for several purposes. |
| 740 | In a program which was abnormally terminated due to excessive looping |
| 741 | or recursion or by a program fault, the counts can facilitate location |
| 742 | of the error. |
| 743 | Zero counts mark portions of the program which were not executed; |
| 744 | during the early debugging stages they should prompt new test data or |
| 745 | a re-examination of the program logic. |
| 746 | The profile is perhaps most valuable, however, in drawing |
| 747 | attention to the (typically small) |
| 748 | portions of the program that dominate execution time. |
| 749 | This information can be used for source level optimization. |
| 750 | .SH |
| 751 | An example |
| 752 | .PP |
| 753 | A prime number is a number which is divisible only by itself and the |
| 754 | number one. |
| 755 | The program |
| 756 | .I primes , |
| 757 | written by Niklaus Wirth, |
| 758 | determines the first few prime numbers. |
| 759 | In translating the program we have specified the |
| 760 | .B z |
| 761 | option to |
| 762 | .IX . |
| 763 | This option causes the translator to generate counters and count instructions |
| 764 | sufficient in number to determine the number of times each statement in the |
| 765 | program was executed.\*(dg |
| 766 | .FS |
| 767 | \*(dgThe counts |
| 768 | are completely accurate only in the absence of runtime errors and nonlocal |
| 769 | .B goto |
| 770 | statements. |
| 771 | This is not generally a problem, however, as in structured programs |
| 772 | nonlocal |
| 773 | .B goto |
| 774 | statements occur infrequently, |
| 775 | and counts are incorrect after abnormal termination only when the |
| 776 | .I "upward look" |
| 777 | described below to get a count passes a suspended call point. |
| 778 | .FE |
| 779 | When execution of the program completes, either normally or abnormally, |
| 780 | this count data is written to the file |
| 781 | .I pmon.out |
| 782 | in the current directory.\*(dd |
| 783 | .FS |
| 784 | \*(dd\c |
| 785 | .I Pmon.out |
| 786 | has a name similar to |
| 787 | .I mon.out |
| 788 | the monitor file produced by the profiling facility of the C compiler |
| 789 | .I cc |
| 790 | (1). |
| 791 | See |
| 792 | .I prof |
| 793 | (1) for a discussion of the C compiler profiling facilities. |
| 794 | .FE |
| 795 | It is then possible to prepare an execution profile by giving |
| 796 | .XP |
| 797 | the name of the file associated with this data, as was done in the following |
| 798 | example. |
| 799 | .LS |
| 800 | % \*bpix -l -z primes.p\fR |
| 801 | .so primeout1 |
| 802 | % |
| 803 | .LE |
| 804 | .SH |
| 805 | Discussion |
| 806 | .PP |
| 807 | The header lines of the outputs of |
| 808 | .IX |
| 809 | and |
| 810 | .XP |
| 811 | in this example indicate the version of the translator and execution |
| 812 | profiler in use at the time this example was prepared. |
| 813 | The time given with the file name (also on the header line) |
| 814 | indicates the time of last modification of the program source file. |
| 815 | This time serves to |
| 816 | .I "version stamp" |
| 817 | the input program. |
| 818 | .I Pxp |
| 819 | also indicates the time at which the profile data was gathered. |
| 820 | .LS |
| 821 | % \*bpxp -z primes.p\fR |
| 822 | .so primeout2 |
| 823 | % |
| 824 | .LE |
| 825 | .KE |
| 826 | .PP |
| 827 | To determine the number of times a statement was executed, |
| 828 | one looks to the left of the statement and finds the corresponding |
| 829 | vertical bar `|'. |
| 830 | If this vertical bar is labelled with a count then that count gives the |
| 831 | number of times the statement was executed. |
| 832 | If the bar is not labelled, we look up in the listing to find the first |
| 833 | `|' which directly above the original one which has a count and that |
| 834 | is the answer. |
| 835 | Thus, in our example, |
| 836 | .I k |
| 837 | was incremented 157 times on line 18, |
| 838 | while the |
| 839 | .I write |
| 840 | procedure call on line 24 was executed 48 times as given by the count |
| 841 | on the |
| 842 | .B repeat . |
| 843 | .PP |
| 844 | More information on |
| 845 | .I pxp |
| 846 | can be found in its manual section |
| 847 | .XP |
| 848 | (6) |
| 849 | and in sections 5.4, 5.5 and 5.10. |