home *** CD-ROM | disk | FTP | other *** search
- .\" Copyright (c) 1980 The Regents of the University of California.
- .\" All rights reserved.
- .\"
- .\" Redistribution and use in source and binary forms, with or without
- .\" modification, are permitted provided that the following conditions
- .\" are met:
- .\" 1. Redistributions of source code must retain the above copyright
- .\" notice, this list of conditions and the following disclaimer.
- .\" 2. Redistributions in binary form must reproduce the above copyright
- .\" notice, this list of conditions and the following disclaimer in the
- .\" documentation and/or other materials provided with the distribution.
- .\" 3. All advertising materials mentioning features or use of this software
- .\" must display the following acknowledgement:
- .\" This product includes software developed by the University of
- .\" California, Berkeley and its contributors.
- .\" 4. Neither the name of the University nor the names of its contributors
- .\" may be used to endorse or promote products derived from this software
- .\" without specific prior written permission.
- .\"
- .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- .\" SUCH DAMAGE.
- .\"
- .\" @(#)puman2.n 6.3 (Berkeley) 4/17/91
- .\"
- .if !\n(xx \{\
- .so tmac.p \}
- 'if n 'ND
- .nr H1 1
- .NH
- Basic UNIX Pascal
- .PP
- The following sections
- explain the basics of using
- .UP .
- In examples here we use the text editor
- .I ex
- (1).
- Users of the text editor
- .I ed
- should have little trouble following these examples,
- as
- .I ex
- is similar to
- .I ed .
- We use
- .I ex
- because it
- allows us to make clearer examples.\(dg
- .FS
- \(dg Users with \s-2CRT\s0 terminals should find the editor
- .I vi
- more pleasant to use;
- we do not show its use here because its display oriented nature
- makes it difficult to illustrate.
- .FE
- The new
- .UX
- user will find it helpful to read one of the text editor documents
- described in section 1.4 before continuing with this section.
- .NH 2
- A first program
- .PP
- To prepare a program for
- .UP
- we first need to have an account on
- .UX
- and to `login'
- to the system on this account.
- These procedures are described in the documents
- .I "Communicating with UNIX"
- and
- .I "UNIX for Beginners".
- .PP
- Once we are logged in we need to choose a name for our program;
- let us call it `first' as this is the first example.
- We must also choose a name for the file in which the program will be stored.
- The
- .UP
- system requires that programs reside in files which have names ending with
- the sequence `.p' so we will call our file `first.p'.
- .PP
- A sample editing session to create this file would begin:
- .LS
- % \*bex first.p\fR
- "first.p" [New file]
- :
- .LE
- We didn't expect the file to exist, so the error diagnostic doesn't
- bother us.
- The editor now knows the name of the file we are creating.
- The `:' prompt indicates that it is ready for command input.
- We can add the text for our program using the `append'
- command as follows.
- .LS
- :\*bappend\fR
- .B
- program first(output)
- begin
- writeln('Hello, world!')
- end.
- \&.
- .R
- :
- .LE
- The line containing the single `\*b.\fR' character here indicated
- the end of the appended text.
- The `:' prompt indicates that
- .I ex
- is ready for another command.
- As the editor operates in a temporary work space we must now store the contents
- of this work space in the file `first.p'
- so we can use the Pascal
- translator and executor
- .IX
- on it.
- .LS
- :\*bwrite\fR
- "first.p" [New file] 4 lines, 59 characters
- :\*bquit\fR
- %
- .LE
- We wrote out the file from the edit buffer here with the
- `write'
- command, and
- .I ex
- indicated the number of lines and characters written.
- We then quit the editor, and now have a prompt from the shell.\(dd
- .FS
- \(dd Our examples here assume you are using
- .I csh.
- .FE
- .KS
- .PP
- We are ready to try
- to translate and execute our program.
- .DS
- .tr '\(aa^\(ua
- % \*bpix first.p\fR
- .so firstout
- .tr ''^^
- %
- .DE
- .KE
- .PP
- The translator first printed a syntax error diagnostic.
- The number 2 here indicates that the rest of the line is an image
- of the second line of our program.
- The translator is saying that it expected to find a `;' before the
- keyword
- .B begin
- on this line.
- If we look at the Pascal syntax charts in the Jensen-Wirth
- .I "User Manual" ,
- or at some of the sample programs therein, we will see that
- we have omitted the terminating `;' of the
- .B program
- statement on the first
- line of our program.
- .PP
- One other thing to notice about the error diagnostic is the letter `e'
- at the beginning.
- It stands for `error',
- indicating that our input was not legal Pascal.
- The fact that it is an `e' rather than an `E'
- indicates that the translator managed to recover from this error well
- enough that generation of code and execution could take place.
- Execution is possible whenever no fatal `E' errors
- occur during translation.
- The other classes of diagnostics are `w' warnings,
- which do not necessarily indicate errors in the program,
- but point out inconsistencies which are likely to be due to program bugs,
- and `s' standard-Pascal violations.\*(dg
- .FS
- \*(dgThe standard Pascal warnings occur only when the associated
- .B s
- translator option is enabled.
- The
- .B s
- option is discussed in sections 5.1 and A.6 below.
- Warning diagnostics are discussed at the end of section 3.2,
- the associated
- .B w
- option is described in section 5.2.
- .FE
- .PP
- After completing the translation of the program to interpretive code,
- the Pascal system indicates that execution of the translated program began.
- The output from the execution of the program then appeared.
- At program termination, the Pascal runtime system indicated the
- number of statements executed, and the amount of cpu time
- used, with the resolution of the latter being 1/60'th of a second.
- .PP
- Let us now fix the error in the program and translate it to a permanent
- object code file
- .I obj
- using
- .PI .
- The program
- .PI
- translates Pascal programs but stores the object code instead of executing it\*(dd.
- .FS
- \*(ddThis script indicates some other useful approaches to debugging
- Pascal programs.
- As in
- .I ed
- we can shorten commands in
- .I ex
- to an initial prefix of the command name as we did
- with the
- .I substitute
- command here.
- We have also used the `!' shell escape command here to execute other
- commands with a shell without leaving the editor.
- .FE
- .LS
- % \*bex first.p\fR
- "first.p" 4 lines, 59 characters
- :\*b1 print\fR
- program first(output)
- :\*bs/$/;\fR
- program first(output);
- :\*bwrite\fR
- "first.p" 4 lines, 60 characters
- :\*bquit\fR
- % \*bpi first.p\fR
- %
- .LE
- If we now use the
- .UX
- .I ls
- list files command we can see what files we have:
- .LS
- % \*bls\fR
- first.p
- obj
- %
- .LE
- The file `obj' here contains the Pascal interpreter code.
- We can execute this by typing:
- .LS
- % \*bpx obj\fR
- .so firstobjout
- %
- .LE
- Alternatively, the command:
- .LS
- % \*bobj\fR
- .LE
- will have the same effect.
- Some examples of different ways to execute the program follow.
- .LS
- % \*bpx\fR
- .so firstobjout
- % \*bpi -p first.p\fR
- % \*bpx obj\fR
- .so firstobjout2
- % \*bpix -p first.p\fR
- .so firstobjout2
- %
- .LE
- .PP
- Note that
- .I px
- will assume that `obj' is the file we wish to execute
- if we don't tell it otherwise.
- The last two translations use the
- .B \-p
- no-post-mortem option to eliminate
- execution statistics and
- `Execution begins'
- and
- `Execution terminated'
- messages.
- See section 5.2 for more details.
- If we now look at the files in our directory we will see:
- .LS
- % \*bls\fR
- first.p
- obj
- %
- .LE
- We can give our object program a name other than `obj' by using the move
- command
- .I mv
- (1).
- Thus to name our program `hello':
- .LS
- % \*bmv obj hello\fR
- % \*bhello\fR
- Hello, world!
- % \*bls\fR
- first.p
- hello
- %
- .LE
- Finally we can get rid of the Pascal object code by using the
- .I rm
- (1) remove file command, e.g.:
- .LS
- % \*brm hello\fR
- % \*bls\fR
- first.p
- %
- .LE
- .PP
- For small programs which are being developed
- .IX
- tends to be more convenient to use than
- .PI
- and
- .X .
- Except for absence of the
- .I obj
- file after a
- .IX
- run,
- a
- .IX
- command is equivalent to a
- .PI
- command followed by a
- .X
- command.
- For larger programs,
- where a number of runs testing different parts of the program are
- to be made,
- .PI
- is useful as this
- .I obj
- file can be executed any desired number of times.
- .. >>> INSERT SECTION FOR PC <<<
- .NH 2
- A larger program
- .PP
- Suppose that we have used the editor to put a larger program
- in the file `bigger.p'.
- We can list this program with line numbers by using the program
- .I cat -n
- i.e.:
- .LS
- % \*bcat -n bigger.p\fR
- .so bigger3.p
- %
- .LE
- This program is similar to program 4.9 on page 30 of the
- Jensen-Wirth
- .I "User Manual" .
- A number of problems have been introduced into this example for
- pedagogical reasons.
- .br
- .PP
- If we attempt to translate and execute the program using
- .IX
- we get the following response:
- .LS
- % \*bpix bigger.p\fR
- .so bigout1
- %
- .LE
- .PP
- Since there were fatal `E' errors in our program,
- no code was generated and execution was necessarily suppressed.
- One thing which would be useful at this point is a listing of the
- program with the error messages.
- We can get this by using the command:
- .LS
- % \*bpi -l bigger.p\fR
- .LE
- There is no point in using
- .IX
- here, since we know there are fatal errors in the program.
- This command will produce the output at our terminal.
- If we are at a terminal which does not produce a hard copy
- we may wish to print this
- listing off-line on a line printer.
- We can do this with the command:
- .LS
- % \*bpi -l bigger.p | lpr\fR
- .LE
- .PP
- In the next few sections we will illustrate various aspects of the
- Berkeley
- Pascal system by correcting this program.
- .NH 2
- Correcting the first errors
- .PP
- Most of the errors which occurred in this program were
- .I syntactic
- errors, those in the format and structure of the program rather than
- its content.
- Syntax errors are flagged by printing the offending line, and then a line
- which flags the location at which an error was detected.
- The flag line also gives an explanation
- stating either a possible cause of the error,
- a simple action which can be taken to recover from the error so
- as to be able to continue the analysis,
- a symbol which was expected at the point of error,
- or an indication that the input was `malformed'.
- In the last case, the recovery may skip ahead in the input
- to a point where analysis of the program can continue.
- .PP
- In this example,
- the first error diagnostic indicates that the translator detected
- a comment within a comment.
- While this is not considered an error in `standard'
- Pascal, it usually corresponds to an error in the program which
- is being translated.
- In this case, we have accidentally omitted the trailing `*)' of the comment
- on line 8.
- We can begin an editor session to correct this problem by doing:
- .LS
- % \*bex bigger.p\fR
- "bigger.p" 24 lines, 512 characters
- :\*b8s/$/ *)\fR
- s = 32; (* 32 character width for interval [x, x+1] *)
- :
- .LE
- .PP
- The second diagnostic, given after line 16,
- indicates that the keyword
- .B do
- was expected before the keyword
- .B begin
- in the
- .B for
- statement.
- If we examine the
- .I statement
- syntax chart on page 118 of the
- Jensen-Wirth
- .I "User Manual"
- we will discover that
- .B do
- is a necessary part of the
- .B for
- statement.
- Similarly, we could have referred to section C.3 of the
- Jensen-Wirth
- .I "User Manual"
- to learn about the
- .B for
- statement and gotten the same information there.
- It is often useful to refer to these syntax charts and to the
- relevant sections of this book.
- .PP
- We can correct this problem by first scanning for the keyword
- .B for
- in the file and then substituting the keyword
- .B do
- to appear in front of the keyword
- .B begin
- there.
- Thus:
- .LS
- :\*b/for\fR
- for i := 0 to lim begin
- :\*bs/begin/do &\fR
- for i := 0 to lim do begin
- :
- .LE
- The next error in the program is easy to pinpoint.
- On line 18, we didn't hit the shift key and got a `9'
- instead of a `)'.
- The translator diagnosed that `x9'
- was an undefined variable and, later,
- that a `)' was missing in the statement.
- It should be stressed that
- .PI
- is not suggesting that you should insert a `)' before the `;'.
- It is only indicating that making this change will help it to be able to
- continue analyzing the program so as to be able to diagnose further
- errors.
- You must then determine the true cause of the error and make the
- appropriate correction to the source text.
- .PP
- This error also illustrates the fact that one error in the input may lead
- to multiple error diagnostics.
- .I Pi
- attempts
- to give only one diagnostic for each error,
- but single errors in the input sometimes appear to be more than
- one error.
- It is also the case that
- .PI
- may not detect an error when it occurs, but may detect it later in
- the input.
- This would have happened
- in this example if we had typed `x' instead of `x9'.
- .PP
- The translator next detected, on line 19, that the function
- .I Round
- and the variable
- .I h
- were undefined.
- It does not know about
- .I Round
- because
- .UP
- normally distinguishes between upper and lower case.\*(dg
- .FS
- \*(dgIn ``standard'' Pascal no distinction is made based on case.
- .FE
- On
- .UX
- lower-case is preferred\*(dd,
- .FS
- \*(ddOne good reason for using lower-case is that it is easier to type.
- .FE
- and all keywords and built-in
- .B procedure
- and
- .B function
- names are composed of lower-case letters,
- just as they are in the Jensen-Wirth
- .I "Pascal Report" .
- Thus we need to use the function
- .I round
- here.
- As far as
- .I h
- is concerned,
- we can see why it is undefined if we look back to line 9
- and note that its definition was lost in the non-terminated
- comment.
- This diagnostic need not, therefore, concern us.
- .PP
- The next error which occurred in the program caused the translator
- to insert a `;' before the statement calling
- .I writeln
- on line 23.
- If we examine the program around the point of error we will see
- that the actual error is that the keyword
- .B until
- and an associated expression have been omitted here.
- Note that the diagnostic from the translator does not indicate the actual
- error, and is somewhat misleading.
- The translator made the correction which seemed to be most plausible.
- As the omission of a `;' character is a common mistake,
- the translator chose to indicate this as a possible fix here.
- It later detected that the keyword
- .B until
- was missing, but not until it saw the keyword
- .B end
- on line 24.
- The combination of these diagnostics indicate to us the true problem.
- .PP
- The final syntactic error message indicates that the translator needed an
- .B end
- keyword to match the
- .B begin
- at line 15.
- Since the
- .B end
- at line 24 is supposed to match this
- .B begin ,
- we can infer that another
- .B begin
- must have been mismatched, and have matched this
- .B end .
- Thus we see that we need an
- .B end
- to match the
- .B begin
- at line 16,
- and to appear before the final
- .B end .
- We can make these corrections:
- .LS
- :\*b/x9/s//x)\fR
- y := exp(-x) * sin(i * x);
- :\*b+s/Round/round\fR
- n := round(s * y) + h;
- :\*b/write\fR
- write(' ');
- :\*b/\fR
- writeln('*')
- :\*binsert\fR
- \*buntil n = 0;\fR
- \&\*b.\fR
- :\*b$\fR
- end.
- :\*binsert\fR
- \*bend\fR
- \&\*b.\fR
- :
- .LE
- .PP
- At the end of each
- .B procedure
- or
- .B function
- and the end of the
- .B program
- the translator summarizes references to undefined variables
- and improper usages of variables.
- It also gives
- warnings about potential errors.
- In our program, the summary errors do not indicate any further problems
- but the warning that
- .I c
- is unused is somewhat suspicious.
- Examining the program we see that the constant was intended
- to be used in the expression which is an argument to
- .I sin ,
- so we can correct this expression, and translate the program.
- We have now made a correction for each diagnosed error
- in our program.
- .LS
- :\*b?i ?s//c /\fR
- y := exp(-x) * sin(c * x);
- :\*bwrite\fR
- "bigger.p" 26 lines, 538 characters
- :\*bquit\fR
- % \*bpi bigger.p\fR
- %
- .LE
- It should be noted that the translator suppresses warning
- diagnostics for a particular
- .B procedure ,
- .B function
- or the main
- .B program
- when it finds severe syntax errors in that part of the source
- text.
- This is to prevent possibly confusing and
- incorrect warning diagnostics from being produced.
- Thus these warning diagnostics may not appear in a program with
- bad syntax errors until these errors are corrected.
- .KS
- .PP
- We are now ready to execute our program for the first
- time.
- We will do so in the next section after giving a listing
- of the corrected program for reference purposes.
- .LS
- % \*bcat -n bigger.p\fR
- .so bigger6.p
- %
- .LE
- .NH 2
- Executing the second example
- .PP
- We are now ready to execute the second example.
- The following output was produced by our first run.
- .LS
- % \*bpx\fR
- .so bigout2
- %
- .LE
- Here the interpreter is presenting us with a runtime error diagnostic.
- It detected a `division by zero' at line 17.
- Examining line 17, we see that we have written
- the statement `x := d / i' instead of `x := d * i'.
- We can correct this and rerun the program:
- .LS
- % \*bex bigger.p\fR
- "bigger.p" 26 lines, 538 characters
- :\*b17\fR
- x := d / i
- :\*bs'/'*\fR
- x := d * i
- :\*bwrite\fR
- "bigger.p" 26 lines, 538 characters
- :\*bq\fR
- % \*bpix bigger.p\fR
- .so bigout3
- %
- .LE
- .KS
- .PP
- This appears to be the output we wanted.
- We could now save the output in a file if we wished by using the shell
- to redirect the output:
- .LS
- % \*bpx > graph\fR
- .LE
- .KE
- We can use
- .I cat
- (1) to see the contents of the file graph.
- We can also make a listing of the graph on the line printer without
- putting it into a file, e.g.
- .LS
- % \*bpx | lpr\fR
- .so bigout4
- %
- .LE
- Note here that the statistics lines came out on our terminal.
- The statistics line comes out on the diagnostic output (unit 2.)
- There are two ways to get rid of the statistics line.
- We can redirect the statistics message to the printer using the
- syntax `|\|&' to the shell rather than `|', i.e.:
- .LS
- % \*bpx |\|& lpr\fR
- %
- .LE
- or we can translate the program with the
- .B p
- option disabled on the command line as we did above.
- This will disable all post-mortem dumping including the statistics line,
- thus:
- .LS
- % \*bpi -p bigger.p\fR
- % \*bpx | lpr\fR
- %
- .LE
- This option also disables the statement limit which normally guards
- against infinite looping.
- You should not use it until your program is debugged.
- Also if
- .B p
- is specified and an error occurs, you will
- not get run time diagnostic information to help you
- determine what the problem is.
- .NH 2
- Formatting the program listing
- .PP
- It is possible to use special lines within the source text of a program
- to format the program listing.
- An empty line (one with no characters on it) corresponds to a
- `space' macro in an assembler, leaving a completely blank line
- without a line number.
- A line containing only a control-l (form-feed) character
- will cause a page eject in the listing with the corresponding line number
- suppressed.
- This corresponds to an `eject' pseudo-instruction.
- See also section 5.2 for details on the
- .B n
- and
- .B i
- options of
- .PI .
- .NH 2
- Execution profiling
- .PP
- An execution profile consists of a structured listing of (all or part of)
- a program with information about the number of times each statement in
- the program was executed for a particular run of the program.
- These profiles can be used for several purposes.
- In a program which was abnormally terminated due to excessive looping
- or recursion or by a program fault, the counts can facilitate location
- of the error.
- Zero counts mark portions of the program which were not executed;
- during the early debugging stages they should prompt new test data or
- a re-examination of the program logic.
- The profile is perhaps most valuable, however, in drawing
- attention to the (typically small)
- portions of the program that dominate execution time.
- This information can be used for source level optimization.
- .SH
- An example
- .PP
- A prime number is a number which is divisible only by itself and the
- number one.
- The program
- .I primes ,
- written by Niklaus Wirth,
- determines the first few prime numbers.
- In translating the program we have specified the
- .B z
- option to
- .IX .
- This option causes the translator to generate counters and count instructions
- sufficient in number to determine the number of times each statement in the
- program was executed.\*(dg
- .FS
- \*(dgThe counts
- are completely accurate only in the absence of runtime errors and nonlocal
- .B goto
- statements.
- This is not generally a problem, however, as in structured programs
- nonlocal
- .B goto
- statements occur infrequently,
- and counts are incorrect after abnormal termination only when the
- .I "upward look"
- described below to get a count passes a suspended call point.
- .FE
- When execution of the program completes, either normally or abnormally,
- this count data is written to the file
- .I pmon.out
- in the current directory.\*(dd
- .FS
- \*(dd\c
- .I Pmon.out
- has a name similar to
- .I mon.out
- the monitor file produced by the profiling facility of the C compiler
- .I cc
- (1).
- See
- .I prof
- (1) for a discussion of the C compiler profiling facilities.
- .FE
- It is then possible to prepare an execution profile by giving
- .XP
- the name of the file associated with this data, as was done in the following
- example.
- .LS
- % \*bpix -l -z primes.p\fR
- .so primeout1
- %
- .LE
- .SH
- Discussion
- .PP
- The header lines of the outputs of
- .IX
- and
- .XP
- in this example indicate the version of the translator and execution
- profiler in use at the time this example was prepared.
- The time given with the file name (also on the header line)
- indicates the time of last modification of the program source file.
- This time serves to
- .I "version stamp"
- the input program.
- .I Pxp
- also indicates the time at which the profile data was gathered.
- .LS
- % \*bpxp -z primes.p\fR
- .so primeout2
- %
- .LE
- .KE
- .PP
- To determine the number of times a statement was executed,
- one looks to the left of the statement and finds the corresponding
- vertical bar `|'.
- If this vertical bar is labelled with a count then that count gives the
- number of times the statement was executed.
- If the bar is not labelled, we look up in the listing to find the first
- `|' which directly above the original one which has a count and that
- is the answer.
- Thus, in our example,
- .I k
- was incremented 157 times on line 18,
- while the
- .I write
- procedure call on line 24 was executed 48 times as given by the count
- on the
- .B repeat .
- .PP
- More information on
- .I pxp
- can be found in its manual section
- .XP
- (1)
- and in sections 5.4, 5.5 and 5.10.
-