2 // io.c - simple io and input parsing routines
4 // Written by Eryk Vershen
8 * Copyright 1996,1997,1998 by Apple Computer, Inc.
11 * Permission to use, copy, modify, and distribute this software and
12 * its documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appears in all copies and
14 * that both the copyright notice and this permission notice appear in
15 * supporting documentation.
17 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE.
21 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
23 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
24 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 // for malloc() & free()
32 #if !defined(__linux__)
39 // for va_start(), etc.
51 #define BAD_DIGIT 17 /* must be greater than any base */
52 #define STRING_CHUNK 16
53 #define UNGET_MAX_COUNT 10
76 const long kDefault
= -1;
82 short unget_buf
[UNGET_MAX_COUNT
+1];
84 char io_buffer
[MAXIOSIZE
];
88 // Forward declarations
90 long get_number(int first_char
);
91 char* get_string(int eos
);
93 void my_ungetch(int c
);
102 if (unget_count
> 0) {
103 return (unget_buf
[--unget_count
]);
105 return (getc(stdin
));
113 // In practice there is never more than one character in
114 // the unget_buf, but what's a little overkill among friends?
116 if (unget_count
< UNGET_MAX_COUNT
) {
117 unget_buf
[unget_count
++] = c
;
119 fatal(-1, "Programmer error in my_ungetch().");
125 flush_to_newline(int keep_newline
)
134 } else if (c
== '\n') {
148 get_okay(const char *prompt
, int default_value
)
160 } else if (c
== ' ' || c
== '\t') {
161 // skip blanks and tabs
162 } else if (c
== '\n') {
164 return default_value
;
165 } else if (c
== 'y' || c
== 'Y') {
167 } else if (c
== 'n' || c
== 'N') {
179 get_command(const char *prompt
, int promptBeforeGet
, int *command
)
183 if (promptBeforeGet
) {
191 } else if (c
== ' ' || c
== '\t') {
192 // skip blanks and tabs
193 } else if (c
== '\n') {
205 get_number_argument(const char *prompt
, long *number
, long default_value
)
215 } else if (c
== ' ' || c
== '\t') {
216 // skip blanks and tabs
217 } else if (c
== '\n') {
218 if (default_value
== kDefault
) {
222 *number
= default_value
;
226 } else if ('0' <= c
&& c
<= '9') {
227 *number
= get_number(c
);
241 get_number(int first_char
)
248 if (first_char
!= '0') {
252 } else if ((c
=my_getch()) == 'x' || c
== 'X') {
263 for (ret_value
= 0; ; c
= my_getch()) {
264 if (c
>= '0' && c
<= '9') {
266 } else if (c
>='A' && c
<= 'F') {
267 digit
= 10 + (c
- 'A');
268 } else if (c
>='a' && c
<= 'f') {
269 digit
= 10 + (c
- 'a');
276 ret_value
= ret_value
* base
+ digit
;
284 get_string_argument(const char *prompt
, char **string
, int reprompt
)
294 } else if (c
== ' ' || c
== '\t') {
295 // skip blanks and tabs
296 } else if (c
== '\n') {
304 } else if (c
== '"' || c
== '\'') {
305 *string
= get_string(c
);
308 } else if (('a' <= c
&& c
<= 'z') || ('A' <= c
&& c
<= 'Z')
309 || (c
== '-' || c
== '/' || c
== '.' || c
== ':')) {
311 *string
= get_string(' ');
333 ret_value
= (char *) malloc(STRING_CHUNK
);
334 if (ret_value
== NULL
) {
335 error(errno
, "can't allocate memory for string buffer");
338 length
= STRING_CHUNK
;
339 limit
= ret_value
+ length
;
342 for (s
= ret_value
; ; c
= my_getch()) {
345 limit
= (char *) malloc(length
+STRING_CHUNK
);
347 error(errno
, "can't allocate memory for string buffer");
348 ret_value
[length
-1] = 0;
351 strncpy(limit
, ret_value
, length
);
353 s
= limit
+ (s
- ret_value
);
355 length
+= STRING_CHUNK
;
356 limit
= ret_value
+ length
;
358 if (c
<= 0 || c
== eos
|| (eos
== ' ' && c
== '\t')) {
361 } else if (c
== '\n') {
374 get_multiplier(long divisor
)
377 unsigned long result
;
383 if (c
<= 0 || divisor
<= 0) {
385 } else if (c
== 't' || c
== 'T') {
388 } else if (c
== 'g' || c
== 'G') {
389 result
= 1024*1024*1024;
390 } else if (c
== 'm' || c
== 'M') {
392 } else if (c
== 'k' || c
== 'K') {
401 if (result
>= 4096) {
402 /* overflow -> 20bits + >12bits */
407 } else if ((long long)result
>= divisor
) {
418 get_partition_modifier(void)
427 if (c
== 'p' || c
== 'P') {
437 number_of_digits(unsigned long value
)
451 // Print a message on standard error & flush the input.
454 bad_input(const char *fmt
, ...)
459 vfprintf(stderr
, fmt
, ap
);
461 fprintf(stderr
, "\n");