Reduce amount of macro magic. Use the same special characters as nroff
[netbsd-mini2440.git] / dist / pdisk / io.c
blobdce3b5e47b3c5253e674e61545f6f05cde71d33a
1 //
2 // io.c - simple io and input parsing routines
3 //
4 // Written by Eryk Vershen
5 //
7 /*
8 * Copyright 1996,1997,1998 by Apple Computer, Inc.
9 * All Rights Reserved
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.
28 // for *printf()
29 #include <stdio.h>
31 // for malloc() & free()
32 #if !defined(__linux__)
33 #include <stdlib.h>
34 #else
35 #include <malloc.h>
36 #endif
37 // for strncpy()
38 #include <string.h>
39 // for va_start(), etc.
40 #include <stdarg.h>
41 // for errno
42 #include <errno.h>
44 #include "io.h"
45 #include "errors.h"
49 // Defines
51 #define BAD_DIGIT 17 /* must be greater than any base */
52 #define STRING_CHUNK 16
53 #define UNGET_MAX_COUNT 10
54 #ifndef __linux__
55 #ifndef __unix__
56 #define SCSI_FD 8
57 #endif
58 #ifdef NeXT
59 #define loff_t off_t
60 #define llseek lseek
61 #else
62 #define loff_t long
63 #define llseek lseek
64 #endif
65 #endif
69 // Types
74 // Global Constants
76 const long kDefault = -1;
80 // Global Variables
82 short unget_buf[UNGET_MAX_COUNT+1];
83 int unget_count;
84 char io_buffer[MAXIOSIZE];
88 // Forward declarations
90 long get_number(int first_char);
91 char* get_string(int eos);
92 int my_getch(void);
93 void my_ungetch(int c);
97 // Routines
99 int
100 my_getch()
102 if (unget_count > 0) {
103 return (unget_buf[--unget_count]);
104 } else {
105 return (getc(stdin));
110 void
111 my_ungetch(int c)
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;
118 } else {
119 fatal(-1, "Programmer error in my_ungetch().");
124 void
125 flush_to_newline(int keep_newline)
127 int c;
129 for (;;) {
130 c = my_getch();
132 if (c <= 0) {
133 break;
134 } else if (c == '\n') {
135 if (keep_newline) {
136 my_ungetch(c);
138 break;
139 } else {
140 // skip
143 return;
148 get_okay(const char *prompt, int default_value)
150 int c;
152 flush_to_newline(0);
153 printf(prompt);
155 for (;;) {
156 c = my_getch();
158 if (c <= 0) {
159 break;
160 } else if (c == ' ' || c == '\t') {
161 // skip blanks and tabs
162 } else if (c == '\n') {
163 my_ungetch(c);
164 return default_value;
165 } else if (c == 'y' || c == 'Y') {
166 return 1;
167 } else if (c == 'n' || c == 'N') {
168 return 0;
169 } else {
170 flush_to_newline(0);
171 printf(prompt);
174 return -1;
179 get_command(const char *prompt, int promptBeforeGet, int *command)
181 int c;
183 if (promptBeforeGet) {
184 printf(prompt);
186 for (;;) {
187 c = my_getch();
189 if (c <= 0) {
190 break;
191 } else if (c == ' ' || c == '\t') {
192 // skip blanks and tabs
193 } else if (c == '\n') {
194 printf(prompt);
195 } else {
196 *command = c;
197 return 1;
200 return 0;
205 get_number_argument(const char *prompt, long *number, long default_value)
207 int c;
208 int result = 0;
210 for (;;) {
211 c = my_getch();
213 if (c <= 0) {
214 break;
215 } else if (c == ' ' || c == '\t') {
216 // skip blanks and tabs
217 } else if (c == '\n') {
218 if (default_value == kDefault) {
219 printf(prompt);
220 } else {
221 my_ungetch(c);
222 *number = default_value;
223 result = 1;
224 break;
226 } else if ('0' <= c && c <= '9') {
227 *number = get_number(c);
228 result = 1;
229 break;
230 } else {
231 my_ungetch(c);
232 *number = 0;
233 break;
236 return result;
240 long
241 get_number(int first_char)
243 register int c;
244 int base;
245 int digit;
246 int ret_value;
248 if (first_char != '0') {
249 c = first_char;
250 base = 10;
251 digit = BAD_DIGIT;
252 } else if ((c=my_getch()) == 'x' || c == 'X') {
253 c = my_getch();
254 base = 16;
255 digit = BAD_DIGIT;
256 } else {
257 my_ungetch(c);
258 c = first_char;
259 base = 8;
260 digit = 0;
262 ret_value = 0;
263 for (ret_value = 0; ; c = my_getch()) {
264 if (c >= '0' && c <= '9') {
265 digit = c - '0';
266 } else if (c >='A' && c <= 'F') {
267 digit = 10 + (c - 'A');
268 } else if (c >='a' && c <= 'f') {
269 digit = 10 + (c - 'a');
270 } else {
271 digit = BAD_DIGIT;
273 if (digit >= base) {
274 break;
276 ret_value = ret_value * base + digit;
278 my_ungetch(c);
279 return(ret_value);
284 get_string_argument(const char *prompt, char **string, int reprompt)
286 int c;
287 int result = 0;
289 for (;;) {
290 c = my_getch();
292 if (c <= 0) {
293 break;
294 } else if (c == ' ' || c == '\t') {
295 // skip blanks and tabs
296 } else if (c == '\n') {
297 if (reprompt) {
298 printf(prompt);
299 } else {
300 my_ungetch(c);
301 *string = NULL;
302 break;
304 } else if (c == '"' || c == '\'') {
305 *string = get_string(c);
306 result = 1;
307 break;
308 } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
309 || (c == '-' || c == '/' || c == '.' || c == ':')) {
310 my_ungetch(c);
311 *string = get_string(' ');
312 result = 1;
313 break;
314 } else {
315 my_ungetch(c);
316 *string = NULL;
317 break;
320 return result;
324 char *
325 get_string(int eos)
327 int c;
328 char *s;
329 char *ret_value;
330 char *limit;
331 int length;
333 ret_value = (char *) malloc(STRING_CHUNK);
334 if (ret_value == NULL) {
335 error(errno, "can't allocate memory for string buffer");
336 return NULL;
338 length = STRING_CHUNK;
339 limit = ret_value + length;
341 c = my_getch();
342 for (s = ret_value; ; c = my_getch()) {
343 if (s >= limit) {
344 // expand string
345 limit = (char *) malloc(length+STRING_CHUNK);
346 if (limit == NULL) {
347 error(errno, "can't allocate memory for string buffer");
348 ret_value[length-1] = 0;
349 break;
351 strncpy(limit, ret_value, length);
352 free(ret_value);
353 s = limit + (s - ret_value);
354 ret_value = limit;
355 length += STRING_CHUNK;
356 limit = ret_value + length;
358 if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) {
359 *s++ = 0;
360 break;
361 } else if (c == '\n') {
362 *s++ = 0;
363 my_ungetch(c);
364 break;
365 } else {
366 *s++ = c;
369 return(ret_value);
373 unsigned long
374 get_multiplier(long divisor)
376 int c;
377 unsigned long result;
378 unsigned long extra;
380 c = my_getch();
382 extra = 1;
383 if (c <= 0 || divisor <= 0) {
384 result = 0;
385 } else if (c == 't' || c == 'T') {
386 result = 1024*1024;
387 extra = 1024*1024;
388 } else if (c == 'g' || c == 'G') {
389 result = 1024*1024*1024;
390 } else if (c == 'm' || c == 'M') {
391 result = 1024*1024;
392 } else if (c == 'k' || c == 'K') {
393 result = 1024;
394 } else {
395 my_ungetch(c);
396 result = 1;
398 if (result > 1) {
399 if (extra > 1) {
400 result /= divisor;
401 if (result >= 4096) {
402 /* overflow -> 20bits + >12bits */
403 result = 0;
404 } else {
405 result *= extra;
407 } else if ((long long)result >= divisor) {
408 result /= divisor;
409 } else {
410 result = 1;
413 return result;
418 get_partition_modifier(void)
420 int c;
421 int result;
423 result = 0;
425 c = my_getch();
427 if (c == 'p' || c == 'P') {
428 result = 1;
429 } else if (c > 0) {
430 my_ungetch(c);
432 return result;
437 number_of_digits(unsigned long value)
439 int j;
441 j = 1;
442 while (value > 9) {
443 j++;
444 value = value / 10;
446 return j;
451 // Print a message on standard error & flush the input.
453 void
454 bad_input(const char *fmt, ...)
456 va_list ap;
458 va_start(ap, fmt);
459 vfprintf(stderr, fmt, ap);
460 va_end(ap);
461 fprintf(stderr, "\n");
462 flush_to_newline(1);