BSD 1 development
[unix-history] / puman / puman4.n
CommitLineData
5bd13011
BJ
1.if \n(xx .bp
2.if !\n(xx \{\
3.so tmac.p \}
4.nr H1 3
5.if n 'ND
6.NH
7Input/output
8.PP
9This section describes features of the Pascal input/output environment,
10with special consideration of the features peculiar to an
11interactive implementation.
12.NH 2
13Introduction
14.PP
15Our first sample programs, in section 2, used the file
16.I output .
17We gave examples there of redirecting the output to a file and to the line
18printer using the shell.
19Similarly, we can read the input from a file or another program.
20Consider the following Pascal program which is similar to the program
21.I cat
22(I).
23.LS
24% \*bpix -l kat.p <primes\fR
25.so katout
26%
27.LE
28Here we have used the shell's syntax to redirect the program input from
29a file in
30.I primes
31in which we had placed the output of our prime number program of section 2.6.
32It is also possible to
33`pipe' input to this program much as we piped input
34to the line printer daemon
35.I lpr
36(I)
37before.
38Thus, the same output as above would be produced by
39.LS
40% \*bcat primes | pix -l kat.p\fR
41.LE
42.PP
43All of these examples use the shell to control the input and output
44from files.
45One very simple way to associate Pascal files with named
46.UX
47files is to place the file name in the
48.B program
49statement.
50For example, suppose we have previously created the file
51.I data.
52We then use it as input to another version of a listing program.
53.LS
54% \*bcat data\fR
55.so data
56% \*bpix -l copydata.p\fR
57.so copydataout
58%
59.LE
60By mentioning the file
61.I data
62in the
63.B program
64statement, we have indicated that we wish it
65to correspond to the
66.UX
67file
68.I data .
69Then, when we
70`reset(data)',
71the Pascal system opens our file `data' for reading.
72More sophisticated, but less portable, examples of using
73.UX
74files will be given in sections 4.5 and 4.6.
75There is a portability problem even with this simple example.
76Some Pascal systems attach meaning to the ordering of the file in the
77.B program
78statement file list.
79.UP
80does not do so.
81.NH 2
82Eof and eoln
83.PP
84An extremely common problem encountered by new users of Pascal, especially
85in the interactive environment offered by
86.UX ,
87relates to the definitions of
88.I eof
89and
90.I eoln .
91These functions are supposed to be defined at the beginning of execution of
92a Pascal program, indicating whether the input device is at the end of a
93line or the end of a file.
94Setting
95.I eof
96or
97.I eoln
98actually corresponds to an implicit read in which the input is
99inspected, but no input is ``used up''.
100In fact, there is no way the system can know whether the input is
101at the end-of-file or the end-of-line unless it attempts to read a line from it.
102If the input is from a previously created file,
103then this reading can take place without run-time action by the user.
104However, if the input is from a terminal, then the input
105is what the user types.\*(dg
106If the system were to do an initial read
107automatically at the beginning of program execution,
108and if the input were a terminal,
109the user would have to type some input before execution could begin.
110.FS
111\*(dgIt is not possible, in practice, to determine whether the input is
112a terminal, as the input may appear to be a file but actually be a
113.I pipe,
114the output of a program which is reading from the terminal.
115.FE
116This would make it impossible for the program to begin by prompting
117for input or printing a herald.
118.PP
119.UP
120has been designed so that an initial read is not necessary.
121At any given time, the Pascal system may or may not know whether the
122end-of-file or end-of-line conditions are true.
123Thus, internally, these functions can have three values \-
124true, false, and ``I don't know yet; if you ask me I'll have to
125find out''.
126All files remain in this last, indeterminate state until the Pascal
127program requires a value for
128.I eof
129or
130.I eoln
131either explicitly or implicitly, e.g. in a call to
132.I read .
133The important point to note here is that if you force the Pascal
134system to determine whether the input is at the end-of-file or the end-of-line,
135it will be necessary for it to attempt to read from the input.
136.PP
137Thus consider the following example code
138.LS
139\*bwhile not\fP eof \*bdo\fP \*bbegin\fP
140 write('number, please? ');
141 read(i);
142 writeln('that was a ', i: 2)
143\*bend\fP
144.LE
145At first glance, this may be appear to be a correct program
146for requesting, reading and echoing numbers.
147Notice, however, that the
148.B while
149loop asks whether
150.I eof
151is true
152.I before
153the request is printed.
154This will force the Pascal system to decide whether the input is at the
155end-of-file.
156The Pascal system will give no messages;
157it will simply wait for the user to type a line.
158By producing the desired prompting before testing
159.I eof,
160the following code avoids this problem:
161.LS
162write('number, please ?');
163\*bwhile not\fP eof \*bdo\fP \*bbegin\fP
164 read(i);
165 writeln('that was a ', i:2);
166 write('number, please ?')
167\*bend\fP
168.LE
169The user must still type a line before the
170.B while
171test is completed, but the prompt will ask for it.
172This example, however, is still not correct.
173To understand why, it is first necessary to know, as we will discuss below,
174that there is a blank character at the end of each line in a Pascal text
175file.
176The
177.I read
178procedure, when reading integers or real numbers,
179is defined so that,
180if there are only blanks left in the file,
181it will return a zero value and set the end-of-file condition.
182If, however, there is a number remaining in the file, the end-of-file
183condition will not be set even if it is the last number, as
184.I read
185never reads the blanks after the number, and there is always at least
186one blank.
187Thus the modified code will still put out a spurious
188.LS
189that was a 0
190.LE
191at the end of a session with it when the end-of-file is reached.
192The simplest way to correct the problem in this example is to use the procedure
193.I readln
194instead of
195.I read
196here.
197In general, unless we test the end-of-file condition both before and
198after calls to
199.I read
200or
201.I readln ,
202there will be inputs for which our program will attempt
203to read past end-of-file.
204.NH 2
205More about eoln
206.PP
207To have a good understanding of when
208.I eoln
209will be true it is necessary to know that in any file
210there is a special character indicating end-of-line,
211and that, in effect, the Pascal system always reads one character ahead of the
212Pascal
213.I read
214commands.\*(dg
215.FS
216\*(dgIn Pascal terms,
217`read(ch)'
218corresponds to
219`ch := input^; get(input)'
220.FE
221For instance,
222in response to `read(ch)',
223the system sets
224.I ch
225to the current input character and gets the next input character.
226If the current input character is the last character of the line,
227then the next input character from the file is the new-line character,
228the normal
229.UX
230line separator.
231When the read routine gets the new-line character,
232it replaces that character by a blank
233(causing every line to end with a blank)
234and sets
235.I eoln
236to true.
237.I Eoln
238will be true as soon as we read the last character of the line and
239.B before
240we read the blank character corresponding to the end of line.
241Thus it is almost always a mistake to write a program which deals with
242input in the following way:
243.LS
244read(ch);
245\*bif\fP eoln \*bthen\fP
246 \fIDone with line\fP
247\*belse\fP
248 \fINormal processing\fP
249.LE
250as this will almost surely have the effect of ignoring the last character
251in the line.
252The `read(ch)' belongs as part of the normal processing.
253.PP
254Given this framework, it is not hard to explain the function of a
255.I readln
256call, which is defined as:
257.LS
258\*bwhile not\fP eoln \*bdo\fP
259 get(input);
260get(input);
261.LE
262This advances the file until the blank corresponding to the end-of-line
263is the current input symbol and then discards this blank.
264The next character available from
265.I read
266will therefore be the first character of the next line,
267if one exists.
268.NH 2
269Output buffering
270.PP
271A final point about Pascal input-output must be noted here.
272This concerns the buffering of the file
273.I output .
274It is extremely inefficient for the Pascal system to send each character
275to the user's terminal as the program generates it for output;
276even less efficient if the output is the input of another
277program such as the line printer daemon
278.I lpr
279(I).
280To gain efficiency, the Pascal system ``buffers'' the output characters
281(i.e. it saves them in memory until the buffer is full and then emits
282the entire buffer in one system interaction.)
283However, to allow interactive prompting to work as in the example given
284above, this prompt must be printed before the Pascal system waits for a
285response.
286For this reason, Pascal normally prints all the output which has
287been generated for the file
288.I output
289whenever
290.HP
291.RS
292.IP 1)
293A
294.I writeln
295occurs, or
296.IP 2)
297The program reads from the terminal, or
298.IP 3)
299The procedure
300.I message
301or
302.I flush
303is called.
304.RE
305.LP
306Thus, in the code sequence
307.LS
308\*bfor\fP i := 1 to 5 \*bdo begin\fP
309 write(i: 2);
310 \fICompute a lot with no output\fP
311\*bend;\fP
312writeln
313.LE
314the output integers will not print until the
315.I writeln
316occurs.
317The delay can be somewhat disconcerting, and you should be aware
318that it will occur.
319By setting the
320.B b
321option to 0 before the
322.B program
323statement by inserting a comment of the form
324.LS
325(*$b0*)
326.LE
327we can cause
328.I output
329to be completely unbuffered, with a corresponding horrendous degradation
330in program efficiency.
331Option control in comments is discussed in section 5.
332.NH 2
333Files, reset, and rewrite
334.PP
335It is possible to use extended forms of the built-in functions
336.I reset
337and
338.I rewrite
339to get more general associations of
340.UX
341file names with Pascal file variables.
342When a file other than
343.I input
344or
345.I output
346is to be read or written, then the reading or writing must be preceded
347by a
348.I reset
349or
350.I rewrite
351call.
352In general, if the Pascal file variable has never been used before,
353there will be no
354.UX
355filename associated with it.
356As we saw in section 2.9,
357by mentioning the file in the
358.B program
359statement,
360we could cause a
361.UX
362file with the same name as the Pascal variable to be associated with it.
363If we do not mention a file in the
364.B program
365statement and use it for the first time with the statement
366.LS
367reset(f)
368.LE
369or
370.LS
371rewrite(f)
372.LE
373then the Pascal system will generate a temporary name of the form
374`tmp.x'
375for some character `x',
376and associate this
377.UX
378file name name with the Pascal file.
379The first such generated name will be `tmp.1'
380and the names continue by incrementing their last character through the
381.SM ASCII
382set.
383The advantage of using such temporary files is that they are automatically
384.I remove d
385by the Pascal system as soon as they become inaccessible.
386They are not removed, however, if a runtime error causes termination
387while they are in scope.
388.PP
389To cause a particular
390.UX
391pathname to be associated with a Pascal file variable
392we can give that name in the
393.I reset
394or
395.I rewrite
396call, e.g. we could have associated the Pascal file
397.I data
398with the file
399`primes'
400in our example in section 3.1 by doing:
401.LS
402reset(data, 'primes')
403.LE
404instead of a simple
405.LS
406reset(data)
407.LE
408In this case it is not essential to mention `data'
409in the program statement, but it is still a good idea
410because is serves as an aid to program documentation.
411The second parameter to
412.I reset
413and
414.I rewrite
415may be any string value, including a variable.
416Thus the names of
417.UX
418files to be associated with Pascal file variables can be read
419in at run time.
420Full details on file name/file variable associations are given in
421section A.3.
422.NH 2
423Argc and argv\*(dg
424.PP
425.FS
426\*(dgSections 4.6 and 4.7 deal with more advanced and system related
427issues that may not be of general interest.
428.FE
429Each
430.UX
431process receives a variable
432length sequence of arguments each of which is a variable length
433character string.
434The built-in function
435.I argc
436and the built-in procedure
437.I argv
438can be used to access and process these arguments.
439The value of the function
440.I argc
441is the number of arguments to the process.
442By convention,
443the arguments are treated as an array,
444and indexed from 0 to
445.I argc \-1,
446with the zeroth argument being the name of the program being executed.
447The rest of the
448arguments are those passed to the command on the command line.
449Thus, the command
450.LS
451% \*bobj /etc/motd /usr/dict/words hello\fR
452.LE
453will invoke the program in the file
454.I obj
455with
456.I argc
457having a value of 4.
458The zeroth element accessed by
459.I argv
460will be `obj', the first `/etc/motd', etc.
461.PP
462Pascal does not provide variable size arrays, nor does it allow
463character strings of varying length.
464For this reason,
465.I argv
466is a procedure and has the syntax
467.LS
468argv(i, a)
469.LE
470where
471.I i
472is an integer and
473.I a
474is a string variable.
475This procedure call assigns the (possibly truncated or blank padded)
476.I i \|'th
477argument of the current process to the string variable
478.I a .
479The file manipulation routines
480.I reset
481and
482.I rewrite
483will strip trailing blanks from their optional second arguments
484so that this blank padding is not a problem in the usual case
485where the arguments are file names.
486.PP
487We are now ready to give a
488.UX
489Pascal program `kat',
490based on that given in section 3.1 above,
491which can be used with the same syntax as the
492.UX
493system program
494.I cat
495(I).
496.LS .ID
497% \*bcat kat.p\fR
498.so kat3.p
499%
500.LE
501Note that the
502.I reset
503call to the file
504.I input
505here, which is necessary for a clear program,
506may be disallowed on other systems.
507As this program deals mostly with
508.I argc
509and
510.I argv
511and
512.UX
513system dependent considerations,
514portability is of little concern.
515.PP
516If this program is in the file `kat.p', then we can do
517.LS .ID
518% \*bpi kat.p\fR
519% \*bmv obj kat\fR
520% \*bkat primes\fR
521.so kat2out
522% \*bkat\fR
523.so katscript
524%
525.LE
526Thus we see that, if it is given arguments, `kat' will,
527like
528.I cat,
529copy each one in turn.
530If no arguments are given, it copies from the standard input.
531Thus it will work as it did before, with
532.LS
533% \*bkat < primes\fR
534.LE
535now equivalent to
536.LS
537% \*bkat primes\fR
538.LE
539although the mechanisms are quite different in the two cases.
540Note that if `kat' is given a bad file name, for example:
541.LS
542% \*bkat xxxxqqq\fR
543.so xxxxqqqout
544%
545.LE
546it will give a diagnostic and a post-mortem control flow backtrace
547for debugging.
548If we were going to use `kat', we might want to translate it
549differently, e.g.:
550.LS
551% \*bpi -pb kat.p\fR
552% \*bmv obj kat\fR
553.LE
554Here we have disabled the post-mortem statistics printing, so
555as not to get the statistics or the traceback on error.
556The
557.B b
558option will cause the system to block buffer the input/output so that
559the program will run more efficiently on large files.
560We could have also specified the
561.B t
562option to turn off runtime tests if that was felt to be a speed hindrance
563to the program.
564Thus we can try the last examples again:
565.LS
566% \*bkat xxxxqqq\fR
567.so xxxxqqqout2
568% \*bkat primes\fR
569.so primes-d
570%
571.LE
572.PP
573The interested reader may wish to try writing a program which
574accepts command line arguments like
575.PI
576does, using
577.I argc
578and
579.I argv
580to process them.