[c1cdaa0] | 1 | /* |
---|
| 2 | * misc.c -- Miscellaneous routines. |
---|
| 3 | * |
---|
[a6b4c0df] | 4 | * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. |
---|
[c1cdaa0] | 5 | * |
---|
| 6 | * See the file "license.txt" for usage and redistribution license requirements |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | /********************************* Includes ***********************************/ |
---|
| 10 | |
---|
| 11 | #if UEMF |
---|
| 12 | #include "uemf.h" |
---|
| 13 | #else |
---|
| 14 | #include "basic/basicInternal.h" |
---|
| 15 | #endif |
---|
| 16 | |
---|
| 17 | /********************************* Defines ************************************/ |
---|
| 18 | /* |
---|
[a6b4c0df] | 19 | * Sprintf buffer structure. Make the increment 64 so that |
---|
[c1cdaa0] | 20 | * a balloc can use a 64 byte block. |
---|
| 21 | */ |
---|
| 22 | |
---|
| 23 | #define STR_REALLOC 0x1 /* Reallocate the buffer as required */ |
---|
[a6b4c0df] | 24 | #define STR_INC 64 /* Growth increment */ |
---|
[c1cdaa0] | 25 | |
---|
| 26 | typedef struct { |
---|
| 27 | char_t *s; /* Pointer to buffer */ |
---|
| 28 | int size; /* Current buffer size */ |
---|
| 29 | int max; /* Maximum buffer size */ |
---|
| 30 | int count; /* Buffer count */ |
---|
| 31 | int flags; /* Allocation flags */ |
---|
| 32 | } strbuf_t; |
---|
| 33 | |
---|
| 34 | /* |
---|
| 35 | * Sprintf formatting flags |
---|
| 36 | */ |
---|
| 37 | enum flag { |
---|
| 38 | flag_none = 0, |
---|
| 39 | flag_minus = 1, |
---|
| 40 | flag_plus = 2, |
---|
| 41 | flag_space = 4, |
---|
| 42 | flag_hash = 8, |
---|
| 43 | flag_zero = 16, |
---|
| 44 | flag_short = 32, |
---|
| 45 | flag_long = 64 |
---|
| 46 | }; |
---|
| 47 | |
---|
| 48 | /************************** Forward Declarations ******************************/ |
---|
| 49 | |
---|
| 50 | static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, |
---|
| 51 | int msize); |
---|
| 52 | static int strnlen(char_t *s, unsigned int n); |
---|
| 53 | static void put_char(strbuf_t *buf, char_t c); |
---|
| 54 | static void put_string(strbuf_t *buf, char_t *s, int len, |
---|
| 55 | int width, int prec, enum flag f); |
---|
| 56 | static void put_ulong(strbuf_t *buf, unsigned long int value, int base, |
---|
| 57 | int upper, char_t *prefix, int width, int prec, enum flag f); |
---|
| 58 | |
---|
| 59 | /************************************ Code ************************************/ |
---|
| 60 | /* |
---|
| 61 | * "basename" returns a pointer to the last component of a pathname |
---|
[a6b4c0df] | 62 | * LINUX and LynxOS have their own basename function |
---|
[c1cdaa0] | 63 | */ |
---|
| 64 | |
---|
[a6b4c0df] | 65 | #if ! LINUX && ! LYNX && ! __rtems__ |
---|
| 66 | char_t *basename(char_t *name) |
---|
[c1cdaa0] | 67 | { |
---|
| 68 | char_t *cp; |
---|
| 69 | |
---|
| 70 | #if NW || WIN |
---|
| 71 | if (((cp = gstrrchr(name, '\\')) == NULL) && |
---|
| 72 | ((cp = gstrrchr(name, '/')) == NULL)) { |
---|
| 73 | return name; |
---|
| 74 | #else |
---|
| 75 | if ((cp = gstrrchr(name, '/')) == NULL) { |
---|
| 76 | return name; |
---|
| 77 | #endif |
---|
| 78 | } else if (*(cp + 1) == '\0' && cp == name) { |
---|
| 79 | return name; |
---|
| 80 | } else if (*(cp + 1) == '\0' && cp != name) { |
---|
| 81 | return T(""); |
---|
| 82 | } else { |
---|
| 83 | return ++cp; |
---|
| 84 | } |
---|
| 85 | } |
---|
[a6b4c0df] | 86 | #endif /* ! LINUX & ! LYNX */ |
---|
[c1cdaa0] | 87 | |
---|
| 88 | /******************************************************************************/ |
---|
| 89 | /* |
---|
| 90 | * Returns a pointer to the directory component of a pathname. bufsize is |
---|
| 91 | * the size of the buffer in BYTES! |
---|
| 92 | */ |
---|
| 93 | |
---|
[a6b4c0df] | 94 | char_t *dirname(char_t *buf, char_t *name, int bufsize) |
---|
[c1cdaa0] | 95 | { |
---|
[a6b4c0df] | 96 | char_t *cp; |
---|
[c1cdaa0] | 97 | int len; |
---|
| 98 | |
---|
| 99 | a_assert(name); |
---|
| 100 | a_assert(buf); |
---|
| 101 | a_assert(bufsize > 0); |
---|
| 102 | |
---|
| 103 | #if WIN || NW |
---|
| 104 | if ((cp = gstrrchr(name, '/')) == NULL && |
---|
| 105 | (cp = gstrrchr(name, '\\')) == NULL) |
---|
| 106 | #else |
---|
| 107 | if ((cp = gstrrchr(name, '/')) == NULL) |
---|
| 108 | #endif |
---|
| 109 | { |
---|
| 110 | gstrcpy(buf, T(".")); |
---|
| 111 | return buf; |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | if ((*(cp + 1) == '\0' && cp == name)) { |
---|
| 115 | gstrncpy(buf, T("."), TSZ(bufsize)); |
---|
| 116 | gstrcpy(buf, T(".")); |
---|
| 117 | return buf; |
---|
| 118 | } |
---|
| 119 | |
---|
| 120 | len = cp - name; |
---|
| 121 | |
---|
| 122 | if (len < bufsize) { |
---|
| 123 | gstrncpy(buf, name, len); |
---|
| 124 | buf[len] = '\0'; |
---|
| 125 | } else { |
---|
| 126 | gstrncpy(buf, name, TSZ(bufsize)); |
---|
| 127 | buf[bufsize - 1] = '\0'; |
---|
| 128 | } |
---|
| 129 | |
---|
| 130 | return buf; |
---|
| 131 | } |
---|
| 132 | |
---|
[a6b4c0df] | 133 | |
---|
[c1cdaa0] | 134 | /******************************************************************************/ |
---|
| 135 | /* |
---|
| 136 | * sprintf and vsprintf are bad, ok. You can easily clobber memory. Use |
---|
[a6b4c0df] | 137 | * fmtAlloc and fmtValloc instead! These functions do _not_ support floating |
---|
[c1cdaa0] | 138 | * point, like %e, %f, %g... |
---|
| 139 | */ |
---|
| 140 | |
---|
[a6b4c0df] | 141 | int fmtAlloc(char_t **s, int n, char_t *fmt, ...) |
---|
[c1cdaa0] | 142 | { |
---|
| 143 | va_list ap; |
---|
| 144 | int result; |
---|
| 145 | |
---|
| 146 | a_assert(s); |
---|
| 147 | a_assert(fmt); |
---|
| 148 | |
---|
| 149 | *s = NULL; |
---|
| 150 | va_start(ap, fmt); |
---|
[a6b4c0df] | 151 | result = dsnprintf(s, n, fmt, ap, 0); |
---|
| 152 | va_end(ap); |
---|
| 153 | return result; |
---|
| 154 | } |
---|
| 155 | |
---|
| 156 | /******************************************************************************/ |
---|
| 157 | /* |
---|
| 158 | * Support a static buffer version for small buffers only! |
---|
| 159 | */ |
---|
| 160 | |
---|
| 161 | int fmtStatic(char_t *s, int n, char_t *fmt, ...) |
---|
| 162 | { |
---|
| 163 | va_list ap; |
---|
| 164 | int result; |
---|
| 165 | |
---|
| 166 | a_assert(s); |
---|
| 167 | a_assert(fmt); |
---|
| 168 | a_assert(n <= 256); |
---|
| 169 | |
---|
| 170 | if (n <= 0) { |
---|
| 171 | return -1; |
---|
| 172 | } |
---|
| 173 | va_start(ap, fmt); |
---|
| 174 | result = dsnprintf(&s, n, fmt, ap, 0); |
---|
[c1cdaa0] | 175 | va_end(ap); |
---|
| 176 | return result; |
---|
| 177 | } |
---|
| 178 | |
---|
| 179 | /******************************************************************************/ |
---|
| 180 | /* |
---|
| 181 | * This function appends the formatted string to the supplied string, |
---|
| 182 | * reallocing if required. |
---|
| 183 | */ |
---|
| 184 | |
---|
[a6b4c0df] | 185 | int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...) |
---|
[c1cdaa0] | 186 | { |
---|
| 187 | va_list ap; |
---|
| 188 | int result; |
---|
| 189 | |
---|
| 190 | a_assert(s); |
---|
| 191 | a_assert(fmt); |
---|
| 192 | |
---|
| 193 | if (msize == -1) { |
---|
| 194 | *s = NULL; |
---|
| 195 | } |
---|
| 196 | va_start(ap, fmt); |
---|
| 197 | result = dsnprintf(s, n, fmt, ap, msize); |
---|
| 198 | va_end(ap); |
---|
| 199 | return result; |
---|
| 200 | } |
---|
| 201 | |
---|
| 202 | /******************************************************************************/ |
---|
| 203 | /* |
---|
| 204 | * A vsprintf replacement. |
---|
| 205 | */ |
---|
| 206 | |
---|
[a6b4c0df] | 207 | int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg) |
---|
[c1cdaa0] | 208 | { |
---|
| 209 | a_assert(s); |
---|
| 210 | a_assert(fmt); |
---|
| 211 | |
---|
[a6b4c0df] | 212 | *s = NULL; |
---|
[c1cdaa0] | 213 | return dsnprintf(s, n, fmt, arg, 0); |
---|
| 214 | } |
---|
| 215 | |
---|
| 216 | /******************************************************************************/ |
---|
| 217 | /* |
---|
[a6b4c0df] | 218 | * Dynamic sprintf implementation. Supports dynamic buffer allocation. |
---|
[c1cdaa0] | 219 | * This function can be called multiple times to grow an existing allocated |
---|
| 220 | * buffer. In this case, msize is set to the size of the previously allocated |
---|
| 221 | * buffer. The buffer will be realloced, as required. If msize is set, we |
---|
| 222 | * return the size of the allocated buffer for use with the next call. For |
---|
| 223 | * the first call, msize can be set to -1. |
---|
| 224 | */ |
---|
| 225 | |
---|
| 226 | static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize) |
---|
| 227 | { |
---|
| 228 | strbuf_t buf; |
---|
| 229 | char_t c; |
---|
| 230 | |
---|
| 231 | a_assert(s); |
---|
| 232 | a_assert(fmt); |
---|
| 233 | |
---|
| 234 | memset(&buf, 0, sizeof(buf)); |
---|
| 235 | buf.s = *s; |
---|
| 236 | |
---|
| 237 | if (*s == NULL || msize != 0) { |
---|
| 238 | buf.max = size; |
---|
| 239 | buf.flags |= STR_REALLOC; |
---|
| 240 | if (msize != 0) { |
---|
| 241 | buf.size = max(msize, 0); |
---|
| 242 | } |
---|
| 243 | if (*s != NULL && msize != 0) { |
---|
| 244 | buf.count = gstrlen(*s); |
---|
| 245 | } |
---|
| 246 | } else { |
---|
| 247 | buf.size = size; |
---|
| 248 | } |
---|
| 249 | |
---|
| 250 | while ((c = *fmt++) != '\0') { |
---|
| 251 | if (c != '%' || (c = *fmt++) == '%') { |
---|
| 252 | put_char(&buf, c); |
---|
| 253 | } else { |
---|
| 254 | enum flag f = flag_none; |
---|
| 255 | int width = 0; |
---|
| 256 | int prec = -1; |
---|
| 257 | for ( ; c != '\0'; c = *fmt++) { |
---|
| 258 | if (c == '-') { |
---|
| 259 | f |= flag_minus; |
---|
| 260 | } else if (c == '+') { |
---|
| 261 | f |= flag_plus; |
---|
| 262 | } else if (c == ' ') { |
---|
| 263 | f |= flag_space; |
---|
| 264 | } else if (c == '#') { |
---|
| 265 | f |= flag_hash; |
---|
| 266 | } else if (c == '0') { |
---|
| 267 | f |= flag_zero; |
---|
| 268 | } else { |
---|
| 269 | break; |
---|
| 270 | } |
---|
| 271 | } |
---|
| 272 | if (c == '*') { |
---|
| 273 | width = va_arg(arg, int); |
---|
| 274 | if (width < 0) { |
---|
| 275 | f |= flag_minus; |
---|
| 276 | width = -width; |
---|
| 277 | } |
---|
| 278 | c = *fmt++; |
---|
| 279 | } else { |
---|
[a6b4c0df] | 280 | for ( ; gisdigit((int)c); c = *fmt++) { |
---|
[c1cdaa0] | 281 | width = width * 10 + (c - '0'); |
---|
| 282 | } |
---|
| 283 | } |
---|
| 284 | if (c == '.') { |
---|
| 285 | f &= ~flag_zero; |
---|
| 286 | c = *fmt++; |
---|
| 287 | if (c == '*') { |
---|
| 288 | prec = va_arg(arg, int); |
---|
| 289 | c = *fmt++; |
---|
| 290 | } else { |
---|
[a6b4c0df] | 291 | for (prec = 0; gisdigit((int)c); c = *fmt++) { |
---|
[c1cdaa0] | 292 | prec = prec * 10 + (c - '0'); |
---|
| 293 | } |
---|
| 294 | } |
---|
| 295 | } |
---|
| 296 | if (c == 'h' || c == 'l') { |
---|
| 297 | f |= (c == 'h' ? flag_short : flag_long); |
---|
| 298 | c = *fmt++; |
---|
| 299 | } |
---|
| 300 | if (c == 'd' || c == 'i') { |
---|
| 301 | long int value; |
---|
| 302 | if (f & flag_short) { |
---|
| 303 | value = (short int) va_arg(arg, int); |
---|
| 304 | } else if (f & flag_long) { |
---|
| 305 | value = va_arg(arg, long int); |
---|
| 306 | } else { |
---|
| 307 | value = va_arg(arg, int); |
---|
| 308 | } |
---|
| 309 | if (value >= 0) { |
---|
| 310 | if (f & flag_plus) { |
---|
| 311 | put_ulong(&buf, value, 10, 0, T("+"), width, prec, f); |
---|
| 312 | } else if (f & flag_space) { |
---|
| 313 | put_ulong(&buf, value, 10, 0, T(" "), width, prec, f); |
---|
| 314 | } else { |
---|
| 315 | put_ulong(&buf, value, 10, 0, NULL, width, prec, f); |
---|
| 316 | } |
---|
| 317 | } else { |
---|
| 318 | put_ulong(&buf, -value, 10, 0, T("-"), width, prec, f); |
---|
| 319 | } |
---|
| 320 | } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') { |
---|
| 321 | unsigned long int value; |
---|
| 322 | if (f & flag_short) { |
---|
| 323 | value = (unsigned short int) va_arg(arg, unsigned int); |
---|
| 324 | } else if (f & flag_long) { |
---|
| 325 | value = va_arg(arg, unsigned long int); |
---|
| 326 | } else { |
---|
| 327 | value = va_arg(arg, unsigned int); |
---|
| 328 | } |
---|
| 329 | if (c == 'o') { |
---|
| 330 | if (f & flag_hash && value != 0) { |
---|
| 331 | put_ulong(&buf, value, 8, 0, T("0"), width, prec, f); |
---|
| 332 | } else { |
---|
| 333 | put_ulong(&buf, value, 8, 0, NULL, width, prec, f); |
---|
| 334 | } |
---|
| 335 | } else if (c == 'u') { |
---|
| 336 | put_ulong(&buf, value, 10, 0, NULL, width, prec, f); |
---|
| 337 | } else { |
---|
| 338 | if (f & flag_hash && value != 0) { |
---|
| 339 | if (c == 'x') { |
---|
| 340 | put_ulong(&buf, value, 16, 0, T("0x"), width, |
---|
| 341 | prec, f); |
---|
| 342 | } else { |
---|
| 343 | put_ulong(&buf, value, 16, 1, T("0X"), width, |
---|
| 344 | prec, f); |
---|
| 345 | } |
---|
| 346 | } else { |
---|
| 347 | put_ulong(&buf, value, 16, 0, NULL, width, prec, f); |
---|
| 348 | } |
---|
| 349 | } |
---|
| 350 | |
---|
| 351 | } else if (c == 'c') { |
---|
| 352 | char_t value = va_arg(arg, int); |
---|
| 353 | put_char(&buf, value); |
---|
| 354 | |
---|
| 355 | } else if (c == 's' || c == 'S') { |
---|
| 356 | char_t *value = va_arg(arg, char_t *); |
---|
| 357 | if (value == NULL) { |
---|
| 358 | put_string(&buf, T("(null)"), -1, width, prec, f); |
---|
| 359 | } else if (f & flag_hash) { |
---|
| 360 | put_string(&buf, |
---|
| 361 | value + 1, (char_t) *value, width, prec, f); |
---|
| 362 | } else { |
---|
| 363 | put_string(&buf, value, -1, width, prec, f); |
---|
| 364 | } |
---|
| 365 | } else if (c == 'p') { |
---|
| 366 | void *value = va_arg(arg, void *); |
---|
| 367 | put_ulong(&buf, |
---|
| 368 | (unsigned long int) value, 16, 0, T("0x"), width, prec, f); |
---|
| 369 | } else if (c == 'n') { |
---|
| 370 | if (f & flag_short) { |
---|
| 371 | short int *value = va_arg(arg, short int *); |
---|
| 372 | *value = buf.count; |
---|
| 373 | } else if (f & flag_long) { |
---|
| 374 | long int *value = va_arg(arg, long int *); |
---|
| 375 | *value = buf.count; |
---|
| 376 | } else { |
---|
| 377 | int *value = va_arg(arg, int *); |
---|
| 378 | *value = buf.count; |
---|
| 379 | } |
---|
| 380 | } else { |
---|
| 381 | put_char(&buf, c); |
---|
| 382 | } |
---|
| 383 | } |
---|
| 384 | } |
---|
| 385 | if (buf.s == NULL) { |
---|
| 386 | put_char(&buf, '\0'); |
---|
| 387 | } |
---|
| 388 | |
---|
| 389 | /* |
---|
| 390 | * If the user requested a dynamic buffer (*s == NULL), ensure it is returned. |
---|
| 391 | */ |
---|
| 392 | if (*s == NULL || msize != 0) { |
---|
| 393 | *s = buf.s; |
---|
| 394 | } |
---|
| 395 | |
---|
| 396 | if (*s != NULL && size > 0) { |
---|
| 397 | if (buf.count < size) { |
---|
| 398 | (*s)[buf.count] = '\0'; |
---|
| 399 | } else { |
---|
| 400 | (*s)[buf.size - 1] = '\0'; |
---|
| 401 | } |
---|
| 402 | } |
---|
| 403 | |
---|
| 404 | if (msize != 0) { |
---|
| 405 | return buf.size; |
---|
| 406 | } |
---|
| 407 | return buf.count; |
---|
| 408 | } |
---|
| 409 | |
---|
| 410 | /******************************************************************************/ |
---|
| 411 | /* |
---|
| 412 | * Return the length of a string limited by a given length |
---|
| 413 | */ |
---|
| 414 | |
---|
| 415 | static int strnlen(char_t *s, unsigned int n) |
---|
| 416 | { |
---|
| 417 | unsigned int len; |
---|
| 418 | |
---|
| 419 | len = gstrlen(s); |
---|
| 420 | return min(len, n); |
---|
| 421 | } |
---|
| 422 | |
---|
| 423 | /******************************************************************************/ |
---|
| 424 | /* |
---|
| 425 | * Add a character to a string buffer |
---|
| 426 | */ |
---|
| 427 | |
---|
| 428 | static void put_char(strbuf_t *buf, char_t c) |
---|
| 429 | { |
---|
[a6b4c0df] | 430 | if (buf->count >= (buf->size - 1)) { |
---|
[c1cdaa0] | 431 | if (! (buf->flags & STR_REALLOC)) { |
---|
| 432 | return; |
---|
| 433 | } |
---|
| 434 | buf->size += STR_INC; |
---|
| 435 | if (buf->size > buf->max && buf->size > STR_INC) { |
---|
[a6b4c0df] | 436 | /* |
---|
| 437 | * Caller should increase the size of the calling buffer |
---|
| 438 | */ |
---|
[c1cdaa0] | 439 | buf->size -= STR_INC; |
---|
| 440 | return; |
---|
| 441 | } |
---|
| 442 | if (buf->s == NULL) { |
---|
[a6b4c0df] | 443 | buf->s = balloc(B_L, buf->size * sizeof(char_t)); |
---|
[c1cdaa0] | 444 | } else { |
---|
[a6b4c0df] | 445 | buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t)); |
---|
[c1cdaa0] | 446 | } |
---|
| 447 | } |
---|
| 448 | buf->s[buf->count] = c; |
---|
[a6b4c0df] | 449 | if (c != '\0') { |
---|
| 450 | ++buf->count; |
---|
| 451 | } |
---|
[c1cdaa0] | 452 | } |
---|
| 453 | |
---|
| 454 | /******************************************************************************/ |
---|
| 455 | /* |
---|
| 456 | * Add a string to a string buffer |
---|
| 457 | */ |
---|
| 458 | |
---|
| 459 | static void put_string(strbuf_t *buf, char_t *s, int len, int width, |
---|
[a6b4c0df] | 460 | int prec, enum flag f) |
---|
[c1cdaa0] | 461 | { |
---|
| 462 | int i; |
---|
| 463 | |
---|
| 464 | if (len < 0) { |
---|
| 465 | len = strnlen(s, prec >= 0 ? prec : ULONG_MAX); |
---|
| 466 | } else if (prec >= 0 && prec < len) { |
---|
| 467 | len = prec; |
---|
| 468 | } |
---|
| 469 | if (width > len && !(f & flag_minus)) { |
---|
| 470 | for (i = len; i < width; ++i) { |
---|
| 471 | put_char(buf, ' '); |
---|
| 472 | } |
---|
| 473 | } |
---|
| 474 | for (i = 0; i < len; ++i) { |
---|
| 475 | put_char(buf, s[i]); |
---|
| 476 | } |
---|
| 477 | if (width > len && f & flag_minus) { |
---|
| 478 | for (i = len; i < width; ++i) { |
---|
| 479 | put_char(buf, ' '); |
---|
| 480 | } |
---|
| 481 | } |
---|
| 482 | } |
---|
| 483 | |
---|
| 484 | /******************************************************************************/ |
---|
| 485 | /* |
---|
| 486 | * Add a long to a string buffer |
---|
| 487 | */ |
---|
| 488 | |
---|
| 489 | static void put_ulong(strbuf_t *buf, unsigned long int value, int base, |
---|
[a6b4c0df] | 490 | int upper, char_t *prefix, int width, int prec, enum flag f) |
---|
[c1cdaa0] | 491 | { |
---|
| 492 | unsigned long x, x2; |
---|
| 493 | int len, zeros, i; |
---|
| 494 | |
---|
| 495 | for (len = 1, x = 1; x < ULONG_MAX / base; ++len, x = x2) { |
---|
| 496 | x2 = x * base; |
---|
| 497 | if (x2 > value) { |
---|
| 498 | break; |
---|
| 499 | } |
---|
| 500 | } |
---|
| 501 | zeros = (prec > len) ? prec - len : 0; |
---|
| 502 | width -= zeros + len; |
---|
| 503 | if (prefix != NULL) { |
---|
| 504 | width -= strnlen(prefix, ULONG_MAX); |
---|
| 505 | } |
---|
| 506 | if (!(f & flag_minus)) { |
---|
[a6b4c0df] | 507 | if (f & flag_zero) { |
---|
| 508 | for (i = 0; i < width; ++i) { |
---|
| 509 | put_char(buf, '0'); |
---|
| 510 | } |
---|
| 511 | } else { |
---|
| 512 | for (i = 0; i < width; ++i) { |
---|
| 513 | put_char(buf, ' '); |
---|
| 514 | } |
---|
[c1cdaa0] | 515 | } |
---|
| 516 | } |
---|
| 517 | if (prefix != NULL) { |
---|
| 518 | put_string(buf, prefix, -1, 0, -1, flag_none); |
---|
| 519 | } |
---|
| 520 | for (i = 0; i < zeros; ++i) { |
---|
| 521 | put_char(buf, '0'); |
---|
| 522 | } |
---|
| 523 | for ( ; x > 0; x /= base) { |
---|
| 524 | int digit = (value / x) % base; |
---|
| 525 | put_char(buf, (char) ((digit < 10 ? '0' : (upper ? 'A' : 'a') - 10) + |
---|
| 526 | digit)); |
---|
| 527 | } |
---|
| 528 | if (f & flag_minus) { |
---|
| 529 | for (i = 0; i < width; ++i) { |
---|
| 530 | put_char(buf, ' '); |
---|
| 531 | } |
---|
| 532 | } |
---|
| 533 | } |
---|
| 534 | |
---|
| 535 | /******************************************************************************/ |
---|
| 536 | /* |
---|
| 537 | * Convert an ansi string to a unicode string. On an error, we return the |
---|
| 538 | * original ansi string which is better than returning NULL. nBytes is the |
---|
| 539 | * size of the destination buffer (ubuf) in _bytes_. |
---|
| 540 | */ |
---|
| 541 | |
---|
| 542 | char_t *ascToUni(char_t *ubuf, char *str, int nBytes) |
---|
| 543 | { |
---|
| 544 | #if UNICODE |
---|
| 545 | if (MultiByteToWideChar(CP_ACP, 0, str, nBytes / sizeof(char_t), ubuf, |
---|
| 546 | nBytes / sizeof(char_t)) < 0) { |
---|
| 547 | return (char_t*) str; |
---|
| 548 | } |
---|
| 549 | #else |
---|
| 550 | memcpy(ubuf, str, nBytes); |
---|
| 551 | #endif |
---|
| 552 | return ubuf; |
---|
| 553 | } |
---|
| 554 | |
---|
| 555 | /******************************************************************************/ |
---|
| 556 | /* |
---|
| 557 | * Convert a unicode string to an ansi string. On an error, return the |
---|
| 558 | * original unicode string which is better than returning NULL. |
---|
| 559 | * N.B. nBytes is the number of _bytes_ in the destination buffer, buf. |
---|
| 560 | */ |
---|
| 561 | |
---|
[a6b4c0df] | 562 | char *uniToAsc(char *buf, char_t *ustr, int nBytes) |
---|
[c1cdaa0] | 563 | { |
---|
| 564 | #if UNICODE |
---|
| 565 | if (WideCharToMultiByte(CP_ACP, 0, ustr, nBytes, buf, nBytes, NULL, |
---|
| 566 | NULL) < 0) { |
---|
| 567 | return (char*) ustr; |
---|
| 568 | } |
---|
| 569 | #else |
---|
| 570 | memcpy(buf, ustr, nBytes); |
---|
| 571 | #endif |
---|
| 572 | return (char*) buf; |
---|
| 573 | } |
---|
| 574 | |
---|
| 575 | /******************************************************************************/ |
---|
| 576 | /* |
---|
| 577 | * allocate (balloc) a buffer and do ascii to unicode conversion into it. |
---|
[a6b4c0df] | 578 | * cp points to the ascii buffer. alen is the length of the buffer to be |
---|
| 579 | * converted not including a terminating NULL. Return a pointer to the |
---|
| 580 | * unicode buffer which must be bfree'd later. Return NULL on failure to |
---|
| 581 | * get buffer. The buffer returned is NULL terminated. |
---|
[c1cdaa0] | 582 | */ |
---|
[a6b4c0df] | 583 | |
---|
| 584 | char_t *ballocAscToUni(char *cp, int alen) |
---|
[c1cdaa0] | 585 | { |
---|
[a6b4c0df] | 586 | char_t *unip; |
---|
[c1cdaa0] | 587 | int ulen; |
---|
| 588 | |
---|
[a6b4c0df] | 589 | ulen = (alen + 1) * sizeof(char_t); |
---|
[c1cdaa0] | 590 | if ((unip = balloc(B_L, ulen)) == NULL) { |
---|
| 591 | return NULL; |
---|
| 592 | } |
---|
| 593 | ascToUni(unip, cp, ulen); |
---|
[a6b4c0df] | 594 | unip[alen] = 0; |
---|
[c1cdaa0] | 595 | return unip; |
---|
| 596 | } |
---|
| 597 | |
---|
| 598 | /******************************************************************************/ |
---|
| 599 | /* |
---|
| 600 | * allocate (balloc) a buffer and do unicode to ascii conversion into it. |
---|
| 601 | * unip points to the unicoded string. ulen is the number of characters |
---|
[a6b4c0df] | 602 | * in the unicode string not including a teminating null. Return a pointer |
---|
| 603 | * to the ascii buffer which must be bfree'd later. Return NULL on failure |
---|
| 604 | * to get buffer. The buffer returned is NULL terminated. |
---|
[c1cdaa0] | 605 | */ |
---|
[a6b4c0df] | 606 | |
---|
| 607 | char *ballocUniToAsc(char_t *unip, int ulen) |
---|
[c1cdaa0] | 608 | { |
---|
| 609 | char * cp; |
---|
| 610 | |
---|
[a6b4c0df] | 611 | if ((cp = balloc(B_L, ulen+1)) == NULL) { |
---|
[c1cdaa0] | 612 | return NULL; |
---|
| 613 | } |
---|
| 614 | uniToAsc(cp, unip, ulen); |
---|
[a6b4c0df] | 615 | cp[ulen] = '\0'; |
---|
[c1cdaa0] | 616 | return cp; |
---|
| 617 | } |
---|
| 618 | |
---|
| 619 | /******************************************************************************/ |
---|
[a6b4c0df] | 620 | /* |
---|
| 621 | * convert a hex string to an integer. The end of the string or a non-hex |
---|
| 622 | * character will indicate the end of the hex specification. |
---|
| 623 | */ |
---|
| 624 | |
---|
| 625 | unsigned int hextoi(char_t *hexstring) |
---|
| 626 | { |
---|
| 627 | register char_t *h; |
---|
| 628 | register unsigned int c, v; |
---|
| 629 | |
---|
| 630 | v = 0; |
---|
| 631 | h = hexstring; |
---|
| 632 | if (*h == '0' && (*(h+1) == 'x' || *(h+1) == 'X')) { |
---|
| 633 | h += 2; |
---|
| 634 | } |
---|
| 635 | while ((c = (unsigned int)*h++) != 0) { |
---|
| 636 | if (c >= '0' && c <= '9') { |
---|
| 637 | c -= '0'; |
---|
| 638 | } else if (c >= 'a' && c <= 'f') { |
---|
| 639 | c = (c - 'a') + 10; |
---|
| 640 | } else if (c >= 'A' && c <= 'F') { |
---|
| 641 | c = (c - 'A') + 10; |
---|
| 642 | } else { |
---|
| 643 | break; |
---|
| 644 | } |
---|
| 645 | v = (v * 0x10) + c; |
---|
| 646 | } |
---|
| 647 | return v; |
---|
| 648 | } |
---|
| 649 | |
---|
| 650 | /******************************************************************************/ |
---|
| 651 | /* |
---|
| 652 | * convert a string to an integer. If the string starts with "0x" or "0X" |
---|
| 653 | * a hexidecimal conversion is done. |
---|
| 654 | */ |
---|
| 655 | |
---|
| 656 | unsigned int gstrtoi(char_t *s) |
---|
| 657 | { |
---|
| 658 | if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) { |
---|
| 659 | s += 2; |
---|
| 660 | return hextoi(s); |
---|
| 661 | } |
---|
| 662 | return gatoi(s); |
---|
| 663 | } |
---|
| 664 | |
---|
| 665 | /******************************************************************************/ |
---|
[c1cdaa0] | 666 | |
---|