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