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