source: rtems/cpukit/httpd/misc.c @ 8d3b3be

4.104.114.84.95
Last change on this file since 8d3b3be was 8d3b3be, checked in by Joel Sherrill <joel.sherrill@…>, on 07/01/02 at 22:16:57

2002-07-01 Joel Sherrill <joel@…>

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