[9] | 1 | (*
|
---|
| 2 | (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
---|
| 3 | See the copyright notice in the ACK home directory, in the file "Copyright".
|
---|
| 4 | *)
|
---|
| 5 |
|
---|
| 6 | (*$R-*)
|
---|
| 7 | IMPLEMENTATION MODULE InOut ;
|
---|
| 8 | (*
|
---|
| 9 | Module: Wirth's Input/Output module
|
---|
| 10 | Author: Ceriel J.H. Jacobs
|
---|
| 11 | Version: $Header: /cvsup/minix/src/lib/ack/libm2/InOut.mod,v 1.1 2005/10/10 15:27:46 beng Exp $
|
---|
| 12 | *)
|
---|
| 13 |
|
---|
| 14 | IMPORT Streams;
|
---|
| 15 | FROM Conversions IMPORT
|
---|
| 16 | ConvertCardinal, ConvertInteger,
|
---|
| 17 | ConvertOctal, ConvertHex;
|
---|
| 18 | FROM Traps IMPORT Message;
|
---|
| 19 |
|
---|
| 20 | CONST TAB = 11C;
|
---|
| 21 |
|
---|
| 22 | TYPE numbuf = ARRAY[0..255] OF CHAR;
|
---|
| 23 |
|
---|
| 24 | VAR unread: BOOLEAN;
|
---|
| 25 | unreadch: CHAR;
|
---|
| 26 | CurrIn, CurrOut: Streams.Stream;
|
---|
| 27 | result: Streams.StreamResult;
|
---|
| 28 |
|
---|
| 29 | PROCEDURE Read(VAR c : CHAR);
|
---|
| 30 |
|
---|
| 31 | BEGIN
|
---|
| 32 | IF unread THEN
|
---|
| 33 | unread := FALSE;
|
---|
| 34 | c := unreadch;
|
---|
| 35 | Done := TRUE;
|
---|
| 36 | ELSE
|
---|
| 37 | Streams.Read(CurrIn, c, result);
|
---|
| 38 | Done := result = Streams.succeeded;
|
---|
| 39 | END;
|
---|
| 40 | END Read;
|
---|
| 41 |
|
---|
| 42 | PROCEDURE UnRead(ch: CHAR);
|
---|
| 43 | BEGIN
|
---|
| 44 | unread := TRUE;
|
---|
| 45 | unreadch := ch;
|
---|
| 46 | END UnRead;
|
---|
| 47 |
|
---|
| 48 | PROCEDURE Write(c: CHAR);
|
---|
| 49 | BEGIN
|
---|
| 50 | Streams.Write(CurrOut, c, result);
|
---|
| 51 | END Write;
|
---|
| 52 |
|
---|
| 53 | PROCEDURE OpenInput(defext: ARRAY OF CHAR);
|
---|
| 54 | VAR namebuf : ARRAY [1..128] OF CHAR;
|
---|
| 55 | BEGIN
|
---|
| 56 | IF CurrIn # Streams.InputStream THEN
|
---|
| 57 | Streams.CloseStream(CurrIn, result);
|
---|
| 58 | END;
|
---|
| 59 | MakeFileName("Name of input file: ", defext, namebuf);
|
---|
| 60 | IF NOT Done THEN RETURN; END;
|
---|
| 61 | openinput(namebuf);
|
---|
| 62 | END OpenInput;
|
---|
| 63 |
|
---|
| 64 | PROCEDURE OpenInputFile(filename: ARRAY OF CHAR);
|
---|
| 65 | BEGIN
|
---|
| 66 | IF CurrIn # Streams.InputStream THEN
|
---|
| 67 | Streams.CloseStream(CurrIn, result);
|
---|
| 68 | END;
|
---|
| 69 | openinput(filename);
|
---|
| 70 | END OpenInputFile;
|
---|
| 71 |
|
---|
| 72 | PROCEDURE openinput(namebuf: ARRAY OF CHAR);
|
---|
| 73 | BEGIN
|
---|
| 74 | IF (namebuf[0] = '-') AND (namebuf[1] = 0C) THEN
|
---|
| 75 | CurrIn := Streams.InputStream;
|
---|
| 76 | Done := TRUE;
|
---|
| 77 | ELSE
|
---|
| 78 | Streams.OpenStream(CurrIn, namebuf, Streams.text,
|
---|
| 79 | Streams.reading, result);
|
---|
| 80 | Done := result = Streams.succeeded;
|
---|
| 81 | END;
|
---|
| 82 | END openinput;
|
---|
| 83 |
|
---|
| 84 | PROCEDURE CloseInput;
|
---|
| 85 | BEGIN
|
---|
| 86 | IF CurrIn # Streams.InputStream THEN
|
---|
| 87 | Streams.CloseStream(CurrIn, result);
|
---|
| 88 | END;
|
---|
| 89 | CurrIn := Streams.InputStream;
|
---|
| 90 | END CloseInput;
|
---|
| 91 |
|
---|
| 92 | PROCEDURE OpenOutput(defext: ARRAY OF CHAR);
|
---|
| 93 | VAR namebuf : ARRAY [1..128] OF CHAR;
|
---|
| 94 | BEGIN
|
---|
| 95 | IF CurrOut # Streams.OutputStream THEN
|
---|
| 96 | Streams.CloseStream(CurrOut, result);
|
---|
| 97 | END;
|
---|
| 98 | MakeFileName("Name of output file: ", defext, namebuf);
|
---|
| 99 | IF NOT Done THEN RETURN; END;
|
---|
| 100 | openoutput(namebuf);
|
---|
| 101 | END OpenOutput;
|
---|
| 102 |
|
---|
| 103 | PROCEDURE OpenOutputFile(filename: ARRAY OF CHAR);
|
---|
| 104 | BEGIN
|
---|
| 105 | IF CurrOut # Streams.OutputStream THEN
|
---|
| 106 | Streams.CloseStream(CurrOut, result);
|
---|
| 107 | END;
|
---|
| 108 | openoutput(filename);
|
---|
| 109 | END OpenOutputFile;
|
---|
| 110 |
|
---|
| 111 | PROCEDURE openoutput(namebuf: ARRAY OF CHAR);
|
---|
| 112 | BEGIN
|
---|
| 113 | IF (namebuf[1] = '-') AND (namebuf[2] = 0C) THEN
|
---|
| 114 | CurrOut := Streams.OutputStream;
|
---|
| 115 | Done := TRUE;
|
---|
| 116 | ELSE
|
---|
| 117 | Streams.OpenStream(CurrOut, namebuf, Streams.text,
|
---|
| 118 | Streams.writing, result);
|
---|
| 119 | Done := result = Streams.succeeded;
|
---|
| 120 | END;
|
---|
| 121 | END openoutput;
|
---|
| 122 |
|
---|
| 123 | PROCEDURE CloseOutput;
|
---|
| 124 | BEGIN
|
---|
| 125 | IF CurrOut # Streams.OutputStream THEN
|
---|
| 126 | Streams.CloseStream(CurrOut, result);
|
---|
| 127 | END;
|
---|
| 128 | CurrOut := Streams.OutputStream;
|
---|
| 129 | END CloseOutput;
|
---|
| 130 |
|
---|
| 131 | PROCEDURE MakeFileName(prompt, defext : ARRAY OF CHAR;
|
---|
| 132 | VAR buf : ARRAY OF CHAR);
|
---|
| 133 | VAR i : INTEGER;
|
---|
| 134 | j : CARDINAL;
|
---|
| 135 | BEGIN
|
---|
| 136 | Done := TRUE;
|
---|
| 137 | IF Streams.isatty(Streams.InputStream, result) THEN
|
---|
| 138 | XWriteString(prompt);
|
---|
| 139 | END;
|
---|
| 140 | XReadString(buf);
|
---|
| 141 | i := 0;
|
---|
| 142 | WHILE buf[i] # 0C DO i := i + 1 END;
|
---|
| 143 | IF i # 0 THEN
|
---|
| 144 | i := i - 1;
|
---|
| 145 | IF buf[i] = '.' THEN
|
---|
| 146 | FOR j := 0 TO HIGH(defext) DO
|
---|
| 147 | i := i + 1;
|
---|
| 148 | buf[i] := defext[j];
|
---|
| 149 | END;
|
---|
| 150 | buf[i+1] := 0C;
|
---|
| 151 | END;
|
---|
| 152 | RETURN;
|
---|
| 153 | END;
|
---|
| 154 | Done := FALSE;
|
---|
| 155 | END MakeFileName;
|
---|
| 156 |
|
---|
| 157 | PROCEDURE ReadInt(VAR integ : INTEGER);
|
---|
| 158 | CONST
|
---|
| 159 | SAFELIMITDIV10 = MAX(INTEGER) DIV 10;
|
---|
| 160 | SAFELIMITREM10 = MAX(INTEGER) MOD 10;
|
---|
| 161 | TYPE
|
---|
| 162 | itype = [0..31];
|
---|
| 163 | ibuf = ARRAY itype OF CHAR;
|
---|
| 164 | VAR
|
---|
| 165 | int : INTEGER;
|
---|
| 166 | neg : BOOLEAN;
|
---|
| 167 | safedigit: [0 .. 9];
|
---|
| 168 | chvalue: CARDINAL;
|
---|
| 169 | buf : ibuf;
|
---|
| 170 | index : itype;
|
---|
| 171 | BEGIN
|
---|
| 172 | ReadString(buf);
|
---|
| 173 | IF NOT Done THEN
|
---|
| 174 | RETURN
|
---|
| 175 | END;
|
---|
| 176 | index := 0;
|
---|
| 177 | IF buf[index] = '-' THEN
|
---|
| 178 | neg := TRUE;
|
---|
| 179 | INC(index);
|
---|
| 180 | ELSIF buf[index] = '+' THEN
|
---|
| 181 | neg := FALSE;
|
---|
| 182 | INC(index);
|
---|
| 183 | ELSE
|
---|
| 184 | neg := FALSE
|
---|
| 185 | END;
|
---|
| 186 |
|
---|
| 187 | safedigit := SAFELIMITREM10;
|
---|
| 188 | IF neg THEN safedigit := safedigit + 1 END;
|
---|
| 189 | int := 0;
|
---|
| 190 | WHILE (buf[index] >= '0') & (buf[index] <= '9') DO
|
---|
| 191 | chvalue := ORD(buf[index]) - ORD('0');
|
---|
| 192 | IF (int > SAFELIMITDIV10) OR
|
---|
| 193 | ( (int = SAFELIMITDIV10) AND
|
---|
| 194 | (chvalue > safedigit)) THEN
|
---|
| 195 | Message("integer too large");
|
---|
| 196 | HALT;
|
---|
| 197 | ELSE
|
---|
| 198 | int := 10*int + VAL(INTEGER, chvalue);
|
---|
| 199 | INC(index)
|
---|
| 200 | END;
|
---|
| 201 | END;
|
---|
| 202 | IF neg THEN
|
---|
| 203 | integ := -int
|
---|
| 204 | ELSE
|
---|
| 205 | integ := int
|
---|
| 206 | END;
|
---|
| 207 | IF buf[index] > " " THEN
|
---|
| 208 | Message("illegal integer");
|
---|
| 209 | HALT;
|
---|
| 210 | END;
|
---|
| 211 | Done := TRUE;
|
---|
| 212 | END ReadInt;
|
---|
| 213 |
|
---|
| 214 | PROCEDURE ReadCard(VAR card : CARDINAL);
|
---|
| 215 | CONST
|
---|
| 216 | SAFELIMITDIV10 = MAX(CARDINAL) DIV 10;
|
---|
| 217 | SAFELIMITREM10 = MAX(CARDINAL) MOD 10;
|
---|
| 218 |
|
---|
| 219 | TYPE
|
---|
| 220 | itype = [0..31];
|
---|
| 221 | ibuf = ARRAY itype OF CHAR;
|
---|
| 222 |
|
---|
| 223 | VAR
|
---|
| 224 | int : CARDINAL;
|
---|
| 225 | index : itype;
|
---|
| 226 | buf : ibuf;
|
---|
| 227 | safedigit: [0 .. 9];
|
---|
| 228 | chvalue: CARDINAL;
|
---|
| 229 | BEGIN
|
---|
| 230 | ReadString(buf);
|
---|
| 231 | IF NOT Done THEN RETURN; END;
|
---|
| 232 | index := 0;
|
---|
| 233 | safedigit := SAFELIMITREM10;
|
---|
| 234 | int := 0;
|
---|
| 235 | WHILE (buf[index] >= '0') & (buf[index] <= '9') DO
|
---|
| 236 | chvalue := ORD(buf[index]) - ORD('0');
|
---|
| 237 | IF (int > SAFELIMITDIV10) OR
|
---|
| 238 | ( (int = SAFELIMITDIV10) AND
|
---|
| 239 | (chvalue > safedigit)) THEN
|
---|
| 240 | Message("cardinal too large");
|
---|
| 241 | HALT;
|
---|
| 242 | ELSE
|
---|
| 243 | int := 10*int + chvalue;
|
---|
| 244 | INC(index);
|
---|
| 245 | END;
|
---|
| 246 | END;
|
---|
| 247 | IF buf[index] > " " THEN
|
---|
| 248 | Message("illegal cardinal");
|
---|
| 249 | HALT;
|
---|
| 250 | END;
|
---|
| 251 | card := int;
|
---|
| 252 | Done := TRUE;
|
---|
| 253 | END ReadCard;
|
---|
| 254 |
|
---|
| 255 | PROCEDURE ReadString(VAR s : ARRAY OF CHAR);
|
---|
| 256 | TYPE charset = SET OF CHAR;
|
---|
| 257 | VAR i : CARDINAL;
|
---|
| 258 | ch : CHAR;
|
---|
| 259 |
|
---|
| 260 | BEGIN
|
---|
| 261 | i := 0;
|
---|
| 262 | REPEAT
|
---|
| 263 | Read(ch);
|
---|
| 264 | UNTIL NOT (ch IN charset{' ', TAB, 12C, 15C});
|
---|
| 265 | IF NOT Done THEN
|
---|
| 266 | RETURN;
|
---|
| 267 | END;
|
---|
| 268 | UnRead(ch);
|
---|
| 269 | REPEAT
|
---|
| 270 | Read(ch);
|
---|
| 271 | termCH := ch;
|
---|
| 272 | IF i <= HIGH(s) THEN
|
---|
| 273 | s[i] := ch;
|
---|
| 274 | IF (NOT Done) OR (ch <= " ") THEN
|
---|
| 275 | s[i] := 0C;
|
---|
| 276 | END;
|
---|
| 277 | END;
|
---|
| 278 | INC(i);
|
---|
| 279 | UNTIL (NOT Done) OR (ch <= " ");
|
---|
| 280 | IF Done THEN UnRead(ch); END;
|
---|
| 281 | END ReadString;
|
---|
| 282 |
|
---|
| 283 | PROCEDURE XReadString(VAR s : ARRAY OF CHAR);
|
---|
| 284 | VAR j : CARDINAL;
|
---|
| 285 | ch : CHAR;
|
---|
| 286 |
|
---|
| 287 | BEGIN
|
---|
| 288 | j := 0;
|
---|
| 289 | LOOP
|
---|
| 290 | Streams.Read(Streams.InputStream, ch, result);
|
---|
| 291 | IF result # Streams.succeeded THEN
|
---|
| 292 | EXIT;
|
---|
| 293 | END;
|
---|
| 294 | IF ch <= " " THEN
|
---|
| 295 | s[j] := 0C;
|
---|
| 296 | EXIT;
|
---|
| 297 | END;
|
---|
| 298 | IF j < HIGH(s) THEN
|
---|
| 299 | s[j] := ch;
|
---|
| 300 | INC(j);
|
---|
| 301 | END;
|
---|
| 302 | END;
|
---|
| 303 | END XReadString;
|
---|
| 304 |
|
---|
| 305 | PROCEDURE XWriteString(s: ARRAY OF CHAR);
|
---|
| 306 | VAR i: CARDINAL;
|
---|
| 307 | BEGIN
|
---|
| 308 | i := 0;
|
---|
| 309 | LOOP
|
---|
| 310 | IF (i <= HIGH(s)) AND (s[i] # 0C) THEN
|
---|
| 311 | Streams.Write(Streams.OutputStream, s[i], result);
|
---|
| 312 | INC(i);
|
---|
| 313 | ELSE
|
---|
| 314 | EXIT;
|
---|
| 315 | END;
|
---|
| 316 | END;
|
---|
| 317 | END XWriteString;
|
---|
| 318 |
|
---|
| 319 | PROCEDURE WriteCard(card, width : CARDINAL);
|
---|
| 320 | VAR
|
---|
| 321 | buf : numbuf;
|
---|
| 322 | BEGIN
|
---|
| 323 | ConvertCardinal(card, width, buf);
|
---|
| 324 | WriteString(buf);
|
---|
| 325 | END WriteCard;
|
---|
| 326 |
|
---|
| 327 | PROCEDURE WriteInt(int : INTEGER; width : CARDINAL);
|
---|
| 328 | VAR
|
---|
| 329 | buf : numbuf;
|
---|
| 330 | BEGIN
|
---|
| 331 | ConvertInteger(int, width, buf);
|
---|
| 332 | WriteString(buf);
|
---|
| 333 | END WriteInt;
|
---|
| 334 |
|
---|
| 335 | PROCEDURE WriteHex(card, width : CARDINAL);
|
---|
| 336 | VAR
|
---|
| 337 | buf : numbuf;
|
---|
| 338 | BEGIN
|
---|
| 339 | ConvertHex(card, width, buf);
|
---|
| 340 | WriteString(buf);
|
---|
| 341 | END WriteHex;
|
---|
| 342 |
|
---|
| 343 | PROCEDURE WriteLn;
|
---|
| 344 | BEGIN
|
---|
| 345 | Write(EOL)
|
---|
| 346 | END WriteLn;
|
---|
| 347 |
|
---|
| 348 | PROCEDURE WriteOct(card, width : CARDINAL);
|
---|
| 349 | VAR
|
---|
| 350 | buf : numbuf;
|
---|
| 351 | BEGIN
|
---|
| 352 | ConvertOctal(card, width, buf);
|
---|
| 353 | WriteString(buf);
|
---|
| 354 | END WriteOct;
|
---|
| 355 |
|
---|
| 356 | PROCEDURE WriteString(str : ARRAY OF CHAR);
|
---|
| 357 | VAR
|
---|
| 358 | nbytes : CARDINAL;
|
---|
| 359 | BEGIN
|
---|
| 360 | nbytes := 0;
|
---|
| 361 | WHILE (nbytes <= HIGH(str)) AND (str[nbytes] # 0C) DO
|
---|
| 362 | Write(str[nbytes]);
|
---|
| 363 | INC(nbytes)
|
---|
| 364 | END;
|
---|
| 365 | END WriteString;
|
---|
| 366 |
|
---|
| 367 | BEGIN (* InOut initialization *)
|
---|
| 368 | CurrIn := Streams.InputStream;
|
---|
| 369 | CurrOut := Streams.OutputStream;
|
---|
| 370 | unread := FALSE;
|
---|
| 371 | END InOut.
|
---|