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