io.c revision 1.2.4.2 1 1.2.4.2 tls //
2 1.2.4.2 tls // io.c - simple io and input parsing routines
3 1.2.4.2 tls //
4 1.2.4.2 tls // Written by Eryk Vershen
5 1.2.4.2 tls //
6 1.2.4.2 tls
7 1.2.4.2 tls /*
8 1.2.4.2 tls * Copyright 1996,1997,1998 by Apple Computer, Inc.
9 1.2.4.2 tls * All Rights Reserved
10 1.2.4.2 tls *
11 1.2.4.2 tls * Permission to use, copy, modify, and distribute this software and
12 1.2.4.2 tls * its documentation for any purpose and without fee is hereby granted,
13 1.2.4.2 tls * provided that the above copyright notice appears in all copies and
14 1.2.4.2 tls * that both the copyright notice and this permission notice appear in
15 1.2.4.2 tls * supporting documentation.
16 1.2.4.2 tls *
17 1.2.4.2 tls * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
18 1.2.4.2 tls * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 1.2.4.2 tls * FOR A PARTICULAR PURPOSE.
20 1.2.4.2 tls *
21 1.2.4.2 tls * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
22 1.2.4.2 tls * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
23 1.2.4.2 tls * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
24 1.2.4.2 tls * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 1.2.4.2 tls * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 1.2.4.2 tls */
27 1.2.4.2 tls
28 1.2.4.2 tls // for *printf()
29 1.2.4.2 tls #include <stdio.h>
30 1.2.4.2 tls
31 1.2.4.2 tls // for malloc() & free()
32 1.2.4.2 tls #if !defined(__linux__)
33 1.2.4.2 tls #include <stdlib.h>
34 1.2.4.2 tls #else
35 1.2.4.2 tls #include <malloc.h>
36 1.2.4.2 tls #endif
37 1.2.4.2 tls // for strncpy()
38 1.2.4.2 tls #include <string.h>
39 1.2.4.2 tls // for va_start(), etc.
40 1.2.4.2 tls #include <stdarg.h>
41 1.2.4.2 tls // for errno
42 1.2.4.2 tls #include <errno.h>
43 1.2.4.2 tls
44 1.2.4.2 tls #include "io.h"
45 1.2.4.2 tls #include "errors.h"
46 1.2.4.2 tls
47 1.2.4.2 tls
48 1.2.4.2 tls //
49 1.2.4.2 tls // Defines
50 1.2.4.2 tls //
51 1.2.4.2 tls #define BAD_DIGIT 17 /* must be greater than any base */
52 1.2.4.2 tls #define STRING_CHUNK 16
53 1.2.4.2 tls #define UNGET_MAX_COUNT 10
54 1.2.4.2 tls #ifndef __linux__
55 1.2.4.2 tls #ifndef __unix__
56 1.2.4.2 tls #define SCSI_FD 8
57 1.2.4.2 tls #endif
58 1.2.4.2 tls #ifdef NeXT
59 1.2.4.2 tls #define loff_t off_t
60 1.2.4.2 tls #define llseek lseek
61 1.2.4.2 tls #else
62 1.2.4.2 tls #define loff_t long
63 1.2.4.2 tls #define llseek lseek
64 1.2.4.2 tls #endif
65 1.2.4.2 tls #endif
66 1.2.4.2 tls
67 1.2.4.2 tls
68 1.2.4.2 tls //
69 1.2.4.2 tls // Types
70 1.2.4.2 tls //
71 1.2.4.2 tls
72 1.2.4.2 tls
73 1.2.4.2 tls //
74 1.2.4.2 tls // Global Constants
75 1.2.4.2 tls //
76 1.2.4.2 tls const long kDefault = -1;
77 1.2.4.2 tls
78 1.2.4.2 tls
79 1.2.4.2 tls //
80 1.2.4.2 tls // Global Variables
81 1.2.4.2 tls //
82 1.2.4.2 tls short unget_buf[UNGET_MAX_COUNT+1];
83 1.2.4.2 tls int unget_count;
84 1.2.4.2 tls char io_buffer[MAXIOSIZE];
85 1.2.4.2 tls
86 1.2.4.2 tls
87 1.2.4.2 tls //
88 1.2.4.2 tls // Forward declarations
89 1.2.4.2 tls //
90 1.2.4.2 tls long get_number(int first_char);
91 1.2.4.2 tls char* get_string(int eos);
92 1.2.4.2 tls int my_getch(void);
93 1.2.4.2 tls void my_ungetch(int c);
94 1.2.4.2 tls
95 1.2.4.2 tls //
96 1.2.4.2 tls // Routines
97 1.2.4.2 tls //
98 1.2.4.2 tls int
99 1.2.4.2 tls my_getch(void)
100 1.2.4.2 tls {
101 1.2.4.2 tls if (unget_count > 0) {
102 1.2.4.2 tls return (unget_buf[--unget_count]);
103 1.2.4.2 tls } else {
104 1.2.4.2 tls return (getc(stdin));
105 1.2.4.2 tls }
106 1.2.4.2 tls }
107 1.2.4.2 tls
108 1.2.4.2 tls
109 1.2.4.2 tls void
110 1.2.4.2 tls my_ungetch(int c)
111 1.2.4.2 tls {
112 1.2.4.2 tls // In practice there is never more than one character in
113 1.2.4.2 tls // the unget_buf, but what's a little overkill among friends?
114 1.2.4.2 tls
115 1.2.4.2 tls if (unget_count < UNGET_MAX_COUNT) {
116 1.2.4.2 tls unget_buf[unget_count++] = c;
117 1.2.4.2 tls } else {
118 1.2.4.2 tls fatal(-1, "Programmer error in my_ungetch().");
119 1.2.4.2 tls }
120 1.2.4.2 tls }
121 1.2.4.2 tls
122 1.2.4.2 tls
123 1.2.4.2 tls void
124 1.2.4.2 tls flush_to_newline(int keep_newline)
125 1.2.4.2 tls {
126 1.2.4.2 tls int c;
127 1.2.4.2 tls
128 1.2.4.2 tls for (;;) {
129 1.2.4.2 tls c = my_getch();
130 1.2.4.2 tls
131 1.2.4.2 tls if (c <= 0) {
132 1.2.4.2 tls break;
133 1.2.4.2 tls } else if (c == '\n') {
134 1.2.4.2 tls if (keep_newline) {
135 1.2.4.2 tls my_ungetch(c);
136 1.2.4.2 tls }
137 1.2.4.2 tls break;
138 1.2.4.2 tls } else {
139 1.2.4.2 tls // skip
140 1.2.4.2 tls }
141 1.2.4.2 tls }
142 1.2.4.2 tls return;
143 1.2.4.2 tls }
144 1.2.4.2 tls
145 1.2.4.2 tls
146 1.2.4.2 tls int
147 1.2.4.2 tls get_okay(const char *prompt, int default_value)
148 1.2.4.2 tls {
149 1.2.4.2 tls int c;
150 1.2.4.2 tls
151 1.2.4.2 tls flush_to_newline(0);
152 1.2.4.2 tls printf("%s", prompt);
153 1.2.4.2 tls
154 1.2.4.2 tls for (;;) {
155 1.2.4.2 tls c = my_getch();
156 1.2.4.2 tls
157 1.2.4.2 tls if (c <= 0) {
158 1.2.4.2 tls break;
159 1.2.4.2 tls } else if (c == ' ' || c == '\t') {
160 1.2.4.2 tls // skip blanks and tabs
161 1.2.4.2 tls } else if (c == '\n') {
162 1.2.4.2 tls my_ungetch(c);
163 1.2.4.2 tls return default_value;
164 1.2.4.2 tls } else if (c == 'y' || c == 'Y') {
165 1.2.4.2 tls return 1;
166 1.2.4.2 tls } else if (c == 'n' || c == 'N') {
167 1.2.4.2 tls return 0;
168 1.2.4.2 tls } else {
169 1.2.4.2 tls flush_to_newline(0);
170 1.2.4.2 tls printf("%s", prompt);
171 1.2.4.2 tls }
172 1.2.4.2 tls }
173 1.2.4.2 tls return -1;
174 1.2.4.2 tls }
175 1.2.4.2 tls
176 1.2.4.2 tls
177 1.2.4.2 tls int
178 1.2.4.2 tls get_command(const char *prompt, int promptBeforeGet, int *command)
179 1.2.4.2 tls {
180 1.2.4.2 tls int c;
181 1.2.4.2 tls
182 1.2.4.2 tls if (promptBeforeGet) {
183 1.2.4.2 tls printf("%s", prompt);
184 1.2.4.2 tls }
185 1.2.4.2 tls for (;;) {
186 1.2.4.2 tls c = my_getch();
187 1.2.4.2 tls
188 1.2.4.2 tls if (c <= 0) {
189 1.2.4.2 tls break;
190 1.2.4.2 tls } else if (c == ' ' || c == '\t') {
191 1.2.4.2 tls // skip blanks and tabs
192 1.2.4.2 tls } else if (c == '\n') {
193 1.2.4.2 tls printf("%s", prompt);
194 1.2.4.2 tls } else {
195 1.2.4.2 tls *command = c;
196 1.2.4.2 tls return 1;
197 1.2.4.2 tls }
198 1.2.4.2 tls }
199 1.2.4.2 tls return 0;
200 1.2.4.2 tls }
201 1.2.4.2 tls
202 1.2.4.2 tls
203 1.2.4.2 tls int
204 1.2.4.2 tls get_number_argument(const char *prompt, long *number, long default_value)
205 1.2.4.2 tls {
206 1.2.4.2 tls int c;
207 1.2.4.2 tls int result = 0;
208 1.2.4.2 tls
209 1.2.4.2 tls for (;;) {
210 1.2.4.2 tls c = my_getch();
211 1.2.4.2 tls
212 1.2.4.2 tls if (c <= 0) {
213 1.2.4.2 tls break;
214 1.2.4.2 tls } else if (c == ' ' || c == '\t') {
215 1.2.4.2 tls // skip blanks and tabs
216 1.2.4.2 tls } else if (c == '\n') {
217 1.2.4.2 tls if (default_value == kDefault) {
218 1.2.4.2 tls printf("%s", prompt);
219 1.2.4.2 tls } else {
220 1.2.4.2 tls my_ungetch(c);
221 1.2.4.2 tls *number = default_value;
222 1.2.4.2 tls result = 1;
223 1.2.4.2 tls break;
224 1.2.4.2 tls }
225 1.2.4.2 tls } else if ('0' <= c && c <= '9') {
226 1.2.4.2 tls *number = get_number(c);
227 1.2.4.2 tls result = 1;
228 1.2.4.2 tls break;
229 1.2.4.2 tls } else {
230 1.2.4.2 tls my_ungetch(c);
231 1.2.4.2 tls *number = 0;
232 1.2.4.2 tls break;
233 1.2.4.2 tls }
234 1.2.4.2 tls }
235 1.2.4.2 tls return result;
236 1.2.4.2 tls }
237 1.2.4.2 tls
238 1.2.4.2 tls
239 1.2.4.2 tls long
240 1.2.4.2 tls get_number(int first_char)
241 1.2.4.2 tls {
242 1.2.4.2 tls register int c;
243 1.2.4.2 tls int base;
244 1.2.4.2 tls int digit;
245 1.2.4.2 tls int ret_value;
246 1.2.4.2 tls
247 1.2.4.2 tls if (first_char != '0') {
248 1.2.4.2 tls c = first_char;
249 1.2.4.2 tls base = 10;
250 1.2.4.2 tls digit = BAD_DIGIT;
251 1.2.4.2 tls } else if ((c=my_getch()) == 'x' || c == 'X') {
252 1.2.4.2 tls c = my_getch();
253 1.2.4.2 tls base = 16;
254 1.2.4.2 tls digit = BAD_DIGIT;
255 1.2.4.2 tls } else {
256 1.2.4.2 tls my_ungetch(c);
257 1.2.4.2 tls c = first_char;
258 1.2.4.2 tls base = 8;
259 1.2.4.2 tls digit = 0;
260 1.2.4.2 tls }
261 1.2.4.2 tls ret_value = 0;
262 1.2.4.2 tls for (ret_value = 0; ; c = my_getch()) {
263 1.2.4.2 tls if (c >= '0' && c <= '9') {
264 1.2.4.2 tls digit = c - '0';
265 1.2.4.2 tls } else if (c >='A' && c <= 'F') {
266 1.2.4.2 tls digit = 10 + (c - 'A');
267 1.2.4.2 tls } else if (c >='a' && c <= 'f') {
268 1.2.4.2 tls digit = 10 + (c - 'a');
269 1.2.4.2 tls } else {
270 1.2.4.2 tls digit = BAD_DIGIT;
271 1.2.4.2 tls }
272 1.2.4.2 tls if (digit >= base) {
273 1.2.4.2 tls break;
274 1.2.4.2 tls }
275 1.2.4.2 tls ret_value = ret_value * base + digit;
276 1.2.4.2 tls }
277 1.2.4.2 tls my_ungetch(c);
278 1.2.4.2 tls return(ret_value);
279 1.2.4.2 tls }
280 1.2.4.2 tls
281 1.2.4.2 tls
282 1.2.4.2 tls int
283 1.2.4.2 tls get_string_argument(const char *prompt, char **string, int reprompt)
284 1.2.4.2 tls {
285 1.2.4.2 tls int c;
286 1.2.4.2 tls int result = 0;
287 1.2.4.2 tls
288 1.2.4.2 tls for (;;) {
289 1.2.4.2 tls c = my_getch();
290 1.2.4.2 tls
291 1.2.4.2 tls if (c <= 0) {
292 1.2.4.2 tls break;
293 1.2.4.2 tls } else if (c == ' ' || c == '\t') {
294 1.2.4.2 tls // skip blanks and tabs
295 1.2.4.2 tls } else if (c == '\n') {
296 1.2.4.2 tls if (reprompt) {
297 1.2.4.2 tls printf("%s", prompt);
298 1.2.4.2 tls } else {
299 1.2.4.2 tls my_ungetch(c);
300 1.2.4.2 tls *string = NULL;
301 1.2.4.2 tls break;
302 1.2.4.2 tls }
303 1.2.4.2 tls } else if (c == '"' || c == '\'') {
304 1.2.4.2 tls *string = get_string(c);
305 1.2.4.2 tls result = 1;
306 1.2.4.2 tls break;
307 1.2.4.2 tls } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
308 1.2.4.2 tls || (c == '-' || c == '/' || c == '.' || c == ':')) {
309 1.2.4.2 tls my_ungetch(c);
310 1.2.4.2 tls *string = get_string(' ');
311 1.2.4.2 tls result = 1;
312 1.2.4.2 tls break;
313 1.2.4.2 tls } else {
314 1.2.4.2 tls my_ungetch(c);
315 1.2.4.2 tls *string = NULL;
316 1.2.4.2 tls break;
317 1.2.4.2 tls }
318 1.2.4.2 tls }
319 1.2.4.2 tls return result;
320 1.2.4.2 tls }
321 1.2.4.2 tls
322 1.2.4.2 tls
323 1.2.4.2 tls char *
324 1.2.4.2 tls get_string(int eos)
325 1.2.4.2 tls {
326 1.2.4.2 tls int c;
327 1.2.4.2 tls char *s;
328 1.2.4.2 tls char *ret_value;
329 1.2.4.2 tls char *limit;
330 1.2.4.2 tls int length;
331 1.2.4.2 tls
332 1.2.4.2 tls ret_value = (char *) malloc(STRING_CHUNK);
333 1.2.4.2 tls if (ret_value == NULL) {
334 1.2.4.2 tls error(errno, "can't allocate memory for string buffer");
335 1.2.4.2 tls return NULL;
336 1.2.4.2 tls }
337 1.2.4.2 tls length = STRING_CHUNK;
338 1.2.4.2 tls limit = ret_value + length;
339 1.2.4.2 tls
340 1.2.4.2 tls c = my_getch();
341 1.2.4.2 tls for (s = ret_value; ; c = my_getch()) {
342 1.2.4.2 tls if (s >= limit) {
343 1.2.4.2 tls // expand string
344 1.2.4.2 tls limit = (char *) malloc(length+STRING_CHUNK);
345 1.2.4.2 tls if (limit == NULL) {
346 1.2.4.2 tls error(errno, "can't allocate memory for string buffer");
347 1.2.4.2 tls ret_value[length-1] = 0;
348 1.2.4.2 tls break;
349 1.2.4.2 tls }
350 1.2.4.2 tls strncpy(limit, ret_value, length);
351 1.2.4.2 tls free(ret_value);
352 1.2.4.2 tls s = limit + (s - ret_value);
353 1.2.4.2 tls ret_value = limit;
354 1.2.4.2 tls length += STRING_CHUNK;
355 1.2.4.2 tls limit = ret_value + length;
356 1.2.4.2 tls }
357 1.2.4.2 tls if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) {
358 1.2.4.2 tls *s++ = 0;
359 1.2.4.2 tls break;
360 1.2.4.2 tls } else if (c == '\n') {
361 1.2.4.2 tls *s++ = 0;
362 1.2.4.2 tls my_ungetch(c);
363 1.2.4.2 tls break;
364 1.2.4.2 tls } else {
365 1.2.4.2 tls *s++ = c;
366 1.2.4.2 tls }
367 1.2.4.2 tls }
368 1.2.4.2 tls return(ret_value);
369 1.2.4.2 tls }
370 1.2.4.2 tls
371 1.2.4.2 tls
372 1.2.4.2 tls uint32_t
373 1.2.4.2 tls get_multiplier(long divisor)
374 1.2.4.2 tls {
375 1.2.4.2 tls int c;
376 1.2.4.2 tls uint32_t result;
377 1.2.4.2 tls uint32_t extra;
378 1.2.4.2 tls
379 1.2.4.2 tls c = my_getch();
380 1.2.4.2 tls
381 1.2.4.2 tls extra = 1;
382 1.2.4.2 tls if (c <= 0 || divisor <= 0) {
383 1.2.4.2 tls result = 0;
384 1.2.4.2 tls } else if (c == 't' || c == 'T') {
385 1.2.4.2 tls result = 1024*1024;
386 1.2.4.2 tls extra = 1024*1024;
387 1.2.4.2 tls } else if (c == 'g' || c == 'G') {
388 1.2.4.2 tls result = 1024*1024*1024;
389 1.2.4.2 tls } else if (c == 'm' || c == 'M') {
390 1.2.4.2 tls result = 1024*1024;
391 1.2.4.2 tls } else if (c == 'k' || c == 'K') {
392 1.2.4.2 tls result = 1024;
393 1.2.4.2 tls } else {
394 1.2.4.2 tls my_ungetch(c);
395 1.2.4.2 tls result = 1;
396 1.2.4.2 tls }
397 1.2.4.2 tls if (result > 1) {
398 1.2.4.2 tls if (extra > 1) {
399 1.2.4.2 tls result /= divisor;
400 1.2.4.2 tls if (result >= 4096) {
401 1.2.4.2 tls /* overflow -> 20bits + >12bits */
402 1.2.4.2 tls result = 0;
403 1.2.4.2 tls } else {
404 1.2.4.2 tls result *= extra;
405 1.2.4.2 tls }
406 1.2.4.2 tls } else if ((long long)result >= divisor) {
407 1.2.4.2 tls result /= divisor;
408 1.2.4.2 tls } else {
409 1.2.4.2 tls result = 1;
410 1.2.4.2 tls }
411 1.2.4.2 tls }
412 1.2.4.2 tls return result;
413 1.2.4.2 tls }
414 1.2.4.2 tls
415 1.2.4.2 tls
416 1.2.4.2 tls int
417 1.2.4.2 tls get_partition_modifier(void)
418 1.2.4.2 tls {
419 1.2.4.2 tls int c;
420 1.2.4.2 tls int result;
421 1.2.4.2 tls
422 1.2.4.2 tls result = 0;
423 1.2.4.2 tls
424 1.2.4.2 tls c = my_getch();
425 1.2.4.2 tls
426 1.2.4.2 tls if (c == 'p' || c == 'P') {
427 1.2.4.2 tls result = 1;
428 1.2.4.2 tls } else if (c > 0) {
429 1.2.4.2 tls my_ungetch(c);
430 1.2.4.2 tls }
431 1.2.4.2 tls return result;
432 1.2.4.2 tls }
433 1.2.4.2 tls
434 1.2.4.2 tls
435 1.2.4.2 tls int
436 1.2.4.2 tls number_of_digits(uint32_t value)
437 1.2.4.2 tls {
438 1.2.4.2 tls int j;
439 1.2.4.2 tls
440 1.2.4.2 tls j = 1;
441 1.2.4.2 tls while (value > 9) {
442 1.2.4.2 tls j++;
443 1.2.4.2 tls value = value / 10;
444 1.2.4.2 tls }
445 1.2.4.2 tls return j;
446 1.2.4.2 tls }
447 1.2.4.2 tls
448 1.2.4.2 tls
449 1.2.4.2 tls //
450 1.2.4.2 tls // Print a message on standard error & flush the input.
451 1.2.4.2 tls //
452 1.2.4.2 tls void
453 1.2.4.2 tls bad_input(const char *fmt, ...)
454 1.2.4.2 tls {
455 1.2.4.2 tls va_list ap;
456 1.2.4.2 tls
457 1.2.4.2 tls va_start(ap, fmt);
458 1.2.4.2 tls vfprintf(stderr, fmt, ap);
459 1.2.4.2 tls va_end(ap);
460 1.2.4.2 tls fprintf(stderr, "\n");
461 1.2.4.2 tls flush_to_newline(1);
462 1.2.4.2 tls }
463