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