]>
Commit | Line | Data |
---|---|---|
6a161fa9 | 1 | /* misc.c - definitions of misc functions */ |
2 | /* | |
3 | * PUPA -- Preliminary Universal Programming Architecture for GRUB | |
4 | * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. | |
5 | * Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org> | |
a35eed7c | 6 | * Copyright (C) 2003 Marco Gerards <metgerards@student.han.nl> |
6a161fa9 | 7 | * |
8 | * PUPA is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with PUPA; if not, write to the Free Software | |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 | */ | |
22 | ||
23 | #include <pupa/misc.h> | |
24 | #include <pupa/err.h> | |
25 | #include <pupa/mm.h> | |
26 | #include <stdarg.h> | |
27 | #include <pupa/term.h> | |
28 | ||
29 | void * | |
a5ffe966 | 30 | pupa_memmove (void *dest, const void *src, pupa_size_t n) |
6a161fa9 | 31 | { |
32 | char *d = (char *) dest; | |
a5ffe966 | 33 | const char *s = (const char *) src; |
34 | ||
35 | if (d < s) | |
36 | while (n--) | |
37 | *d++ = *s++; | |
38 | else | |
39 | { | |
40 | d += n; | |
41 | s += n; | |
42 | ||
43 | while (n--) | |
44 | *--d = *--s; | |
45 | } | |
6a161fa9 | 46 | |
47 | return dest; | |
48 | } | |
49 | ||
a5ffe966 | 50 | char * |
51 | pupa_strcpy (char *dest, const char *src) | |
52 | { | |
53 | char *p = dest; | |
54 | ||
55 | while ((*p++ = *src++) != '\0') | |
56 | ; | |
57 | ||
58 | return dest; | |
59 | } | |
60 | ||
a35eed7c | 61 | char * |
62 | pupa_strncpy (char *dest, const char *src, int c) | |
63 | { | |
64 | char *p = dest; | |
65 | int pos = 0; | |
66 | ||
67 | while ((*p++ = *src++) != '\0' && c > pos) | |
68 | pos++; | |
69 | ||
70 | return dest; | |
71 | } | |
72 | ||
a5ffe966 | 73 | char * |
74 | pupa_strcat (char *dest, const char *src) | |
75 | { | |
76 | char *p = dest; | |
77 | ||
78 | while (*p) | |
79 | p++; | |
80 | ||
81 | while ((*p++ = *src++) != '\0') | |
82 | ; | |
83 | ||
84 | return dest; | |
85 | } | |
a5ffe966 | 86 | |
6a161fa9 | 87 | int |
88 | pupa_printf (const char *fmt, ...) | |
89 | { | |
90 | va_list ap; | |
91 | int ret; | |
92 | ||
93 | va_start (ap, fmt); | |
94 | ret = pupa_vprintf (fmt, ap); | |
95 | va_end (ap); | |
96 | ||
97 | return ret; | |
98 | } | |
99 | ||
100 | int | |
101 | pupa_vprintf (const char *fmt, va_list args) | |
102 | { | |
103 | return pupa_vsprintf (0, fmt, args); | |
104 | } | |
105 | ||
106 | int | |
107 | pupa_memcmp (const void *s1, const void *s2, pupa_size_t n) | |
108 | { | |
109 | const char *t1 = s1; | |
110 | const char *t2 = s2; | |
111 | ||
112 | while (n--) | |
113 | { | |
114 | if (*t1 != *t2) | |
115 | return (int) *t1 - (int) *t2; | |
116 | ||
117 | t1++; | |
118 | t2++; | |
119 | } | |
120 | ||
121 | return 0; | |
122 | } | |
123 | ||
124 | int | |
125 | pupa_strcmp (const char *s1, const char *s2) | |
126 | { | |
127 | while (*s1 && *s2) | |
128 | { | |
129 | if (*s1 != *s2) | |
130 | return (int) *s1 - (int) *s2; | |
131 | ||
132 | s1++; | |
133 | s2++; | |
134 | } | |
135 | ||
136 | return (int) *s1 - (int) *s2; | |
137 | } | |
138 | ||
a35eed7c | 139 | int |
140 | pupa_strncmp (const char *s1, const char *s2, int c) | |
141 | { | |
142 | int p = 1; | |
143 | ||
144 | while (*s1 && *s2 && p < c) | |
145 | { | |
146 | if (*s1 != *s2) | |
147 | return (int) *s1 - (int) *s2; | |
148 | ||
149 | s1++; | |
150 | s2++; | |
151 | p++; | |
152 | } | |
153 | ||
154 | return (int) *s1 - (int) *s2; | |
155 | } | |
156 | ||
6a161fa9 | 157 | char * |
158 | pupa_strchr (const char *s, int c) | |
159 | { | |
160 | while (*s) | |
161 | { | |
162 | if (*s == c) | |
163 | return (char *) s; | |
164 | s++; | |
165 | } | |
166 | ||
167 | return 0; | |
168 | } | |
169 | ||
170 | char * | |
171 | pupa_strrchr (const char *s, int c) | |
172 | { | |
173 | char *p = 0; | |
174 | ||
175 | while (*s) | |
176 | { | |
177 | if (*s == c) | |
178 | p = (char *) s; | |
179 | s++; | |
180 | } | |
181 | ||
182 | return p; | |
183 | } | |
184 | ||
185 | int | |
186 | pupa_isspace (int c) | |
187 | { | |
188 | return (c == '\n' || c == '\r' || c == ' ' || c == '\t'); | |
189 | } | |
190 | ||
191 | int | |
192 | pupa_isprint (int c) | |
193 | { | |
194 | return (c >= ' ' && c <= '~'); | |
195 | } | |
196 | ||
197 | int | |
198 | pupa_isalpha (int c) | |
199 | { | |
200 | return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); | |
201 | } | |
202 | ||
203 | int | |
204 | pupa_tolower (int c) | |
205 | { | |
206 | if (c >= 'A' && c <= 'Z') | |
207 | return c - 'A' + 'a'; | |
208 | ||
209 | return c; | |
210 | } | |
211 | ||
212 | unsigned long | |
213 | pupa_strtoul (const char *str, char **end, int base) | |
214 | { | |
215 | unsigned long num = 0; | |
216 | int found = 0; | |
217 | ||
218 | /* Skip white spaces. */ | |
219 | while (*str && pupa_isspace (*str)) | |
220 | str++; | |
221 | ||
222 | /* Guess the base, if not specified. The prefix `0x' means 16, and | |
223 | the prefix `0' means 8. */ | |
224 | if (str[0] == '0') | |
225 | { | |
226 | if (str[1] == 'x') | |
227 | { | |
228 | if (base == 0 || base == 16) | |
229 | { | |
230 | base = 16; | |
231 | str += 2; | |
232 | } | |
233 | } | |
234 | else if (str[1] >= '0' && str[1] <= '7') | |
235 | base = 8; | |
236 | } | |
237 | ||
238 | if (base == 0) | |
239 | base = 10; | |
240 | ||
241 | while (*str) | |
242 | { | |
243 | unsigned long digit; | |
244 | ||
245 | digit = pupa_tolower (*str) - '0'; | |
246 | if (digit > 9) | |
247 | { | |
248 | digit += '0' - 'a' + 10; | |
249 | if (digit >= (unsigned long) base) | |
250 | break; | |
251 | } | |
252 | ||
253 | found = 1; | |
254 | ||
255 | if (num > (~0UL - digit) / base) | |
256 | { | |
257 | pupa_error (PUPA_ERR_OUT_OF_RANGE, "overflow is detected"); | |
258 | return 0; | |
259 | } | |
260 | ||
261 | num += num * base + digit; | |
262 | str++; | |
263 | } | |
264 | ||
265 | if (! found) | |
266 | { | |
267 | pupa_error (PUPA_ERR_BAD_NUMBER, "unrecognized number"); | |
268 | return 0; | |
269 | } | |
270 | ||
271 | if (end) | |
272 | *end = (char *) str; | |
273 | ||
274 | return num; | |
275 | } | |
276 | ||
277 | char * | |
278 | pupa_strdup (const char *s) | |
279 | { | |
280 | pupa_size_t len; | |
281 | char *p; | |
282 | ||
283 | len = pupa_strlen (s) + 1; | |
284 | p = (char *) pupa_malloc (len); | |
285 | if (! p) | |
286 | return 0; | |
287 | ||
288 | return pupa_memcpy (p, s, len); | |
289 | } | |
290 | ||
291 | void * | |
292 | pupa_memset (void *s, int c, pupa_size_t n) | |
293 | { | |
294 | unsigned char *p = (unsigned char *) s; | |
295 | ||
296 | while (n--) | |
297 | *p++ = (unsigned char) c; | |
298 | ||
299 | return s; | |
300 | } | |
301 | ||
302 | pupa_size_t | |
303 | pupa_strlen (const char *s) | |
304 | { | |
a5ffe966 | 305 | const char *p = s; |
6a161fa9 | 306 | |
307 | while (*p) | |
308 | p++; | |
309 | ||
310 | return p - s; | |
311 | } | |
312 | ||
313 | static inline void | |
314 | pupa_reverse (char *str) | |
315 | { | |
316 | char *p = str + pupa_strlen (str) - 1; | |
317 | ||
318 | while (str < p) | |
319 | { | |
320 | char tmp; | |
321 | ||
322 | tmp = *str; | |
323 | *str = *p; | |
324 | *p = tmp; | |
325 | str++; | |
326 | p--; | |
327 | } | |
328 | } | |
329 | ||
a5ffe966 | 330 | static char * |
6a161fa9 | 331 | pupa_itoa (char *str, int c, unsigned n) |
332 | { | |
333 | unsigned base = (c == 'x') ? 16 : 10; | |
334 | char *p; | |
335 | ||
336 | if ((int) n < 0 && c == 'd') | |
337 | { | |
338 | n = (unsigned) (-((int) n)); | |
339 | *str++ = '-'; | |
340 | } | |
341 | ||
342 | p = str; | |
343 | do | |
344 | { | |
345 | unsigned d = n % base; | |
346 | *p++ = (d > 9) ? d + 'a' - 10 : d + '0'; | |
347 | } | |
348 | while (n /= base); | |
349 | *p = 0; | |
350 | ||
351 | pupa_reverse (str); | |
352 | return p; | |
353 | } | |
354 | ||
355 | int | |
356 | pupa_vsprintf (char *str, const char *fmt, va_list args) | |
357 | { | |
358 | char c; | |
359 | int count = 0; | |
18d9c7cd | 360 | auto void write_char (unsigned char ch); |
6a161fa9 | 361 | auto void write_str (const char *s); |
362 | ||
18d9c7cd | 363 | void write_char (unsigned char ch) |
6a161fa9 | 364 | { |
365 | if (str) | |
a5ffe966 | 366 | *str++ = ch; |
6a161fa9 | 367 | else |
a5ffe966 | 368 | pupa_putchar (ch); |
6a161fa9 | 369 | |
370 | count++; | |
371 | } | |
372 | ||
373 | void write_str (const char *s) | |
374 | { | |
375 | while (*s) | |
376 | write_char (*s++); | |
377 | } | |
378 | ||
379 | while ((c = *fmt++) != 0) | |
380 | { | |
381 | if (c != '%') | |
382 | write_char (c); | |
383 | else | |
384 | { | |
385 | char tmp[16]; | |
386 | char *p; | |
387 | int n; | |
388 | ||
389 | c = *fmt++; | |
390 | ||
391 | switch (c) | |
392 | { | |
393 | case 'p': | |
394 | write_str ("0x"); | |
395 | c = 'x'; | |
396 | /* fall through */ | |
397 | case 'x': | |
398 | case 'u': | |
399 | case 'd': | |
400 | n = va_arg (args, int); | |
401 | pupa_itoa (tmp, c, n); | |
402 | write_str (tmp); | |
403 | break; | |
404 | ||
405 | case 'c': | |
406 | n = va_arg (args, int); | |
18d9c7cd | 407 | write_char (n & 0xff); |
408 | break; | |
409 | ||
410 | case 'C': | |
411 | { | |
412 | pupa_uint32_t code = va_arg (args, pupa_uint32_t); | |
413 | int shift; | |
414 | unsigned mask; | |
415 | ||
416 | if (code <= 0x7f) | |
417 | { | |
418 | shift = 0; | |
419 | mask = 0; | |
420 | } | |
421 | else if (code <= 0x7ff) | |
422 | { | |
423 | shift = 6; | |
424 | mask = 0xc0; | |
425 | } | |
426 | else if (code <= 0xffff) | |
427 | { | |
428 | shift = 12; | |
429 | mask = 0xe0; | |
430 | } | |
431 | else if (code <= 0x1fffff) | |
432 | { | |
433 | shift = 18; | |
434 | mask = 0xf0; | |
435 | } | |
436 | else if (code <= 0x3ffffff) | |
437 | { | |
438 | shift = 24; | |
439 | mask = 0xf8; | |
440 | } | |
441 | else if (code <= 0x7fffffff) | |
442 | { | |
443 | shift = 30; | |
444 | mask = 0xfc; | |
445 | } | |
446 | else | |
447 | { | |
448 | code = '?'; | |
449 | shift = 0; | |
450 | mask = 0; | |
451 | } | |
452 | ||
453 | write_char (mask | (code >> shift)); | |
454 | ||
455 | for (shift -= 6; shift >= 0; shift -= 6) | |
456 | write_char (0x80 | (0x3f & (code >> shift))); | |
457 | } | |
6a161fa9 | 458 | break; |
459 | ||
460 | case 's': | |
461 | p = va_arg (args, char *); | |
462 | if (p) | |
463 | write_str (p); | |
464 | else | |
465 | write_str ("(null)"); | |
466 | break; | |
467 | ||
468 | default: | |
469 | write_char (c); | |
470 | break; | |
471 | } | |
472 | } | |
473 | } | |
474 | ||
475 | if (str) | |
476 | *str = '\0'; | |
477 | ||
478 | return count; | |
479 | } | |
480 | ||
481 | int | |
482 | pupa_sprintf (char *str, const char *fmt, ...) | |
483 | { | |
484 | va_list ap; | |
485 | int ret; | |
486 | ||
487 | va_start (ap, fmt); | |
488 | ret = pupa_vsprintf (str, fmt, ap); | |
489 | va_end (ap); | |
490 | ||
491 | return ret; | |
492 | } |