source: svn/trunk/newcon3bcm2_21bu/dta/src/libc.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 40.9 KB
Line 
1/**************************************************************************
2*                                                                         *
3*   PROJECT     : TMON (Transparent monitor)                              *
4*                                                                         *
5*   MODULE      : LIBC.c                                                  *
6*                                                                         *
7*   AUTHOR      : Michael Anburaj                                         *
8*                 URL  : http://geocities.com/michaelanburaj/             *
9*                 EMAIL: michaelanburaj@hotmail.com                       *
10*                                                                         *
11*   PROCESSOR   : MIPS 4Kc (32 bit RISC) - ATLAS board                    *
12*                                                                         *
13*   TOOL-CHAIN  : SDE & Cygnus                                            *
14*                                                                         *
15*   DESCRIPTION :                                                         *
16*   This is the LIBC module. Implements most of the standard library      *
17*   functions.                                                            *
18*                                                                         *
19**************************************************************************/
20
21#include "ministd.h"
22
23/* ********************************************************************* */
24/* Global definitions */
25
26/* for errno.h */
27int errno;
28
29/* File local definitions */
30
31/* for _doprintx */
32#define BUF     32
33
34#define ARG()                                                           \
35            _ulong =                                                    \
36                (flags & SHORTINT) ?                                    \
37                    (uint32_t)((int16_t)((uint16_t)va_arg(argp, uint32_t))) :   \
38                    (uint32_t)va_arg(argp, uint32_t);
39
40#define todigit(c)      ((c) - '0')
41#define tochar(n)       ((n) + '0')
42
43/* have to deal with the negative buffer count kludge */
44#define NEGATIVE_COUNT_KLUDGE
45
46#define LONGINT         0x01            /* long integer                 */
47#define LONGDBL         0x02            /* long double; unimplemented   */
48#define SHORTINT        0x04            /* short integer                */
49#define ALT             0x08            /* alternate form               */
50#define LADJUST         0x10            /* left adjustment              */
51#define ZEROPAD         0x20            /* zero (as opposed to blank) pad */
52#define HEXPREFIX       0x40            /* add 0x or 0X prefix          */
53#define SPACE           0x80            /* space if plus */
54#define SIGN            0x100           /* unsigned/signed long */
55#define PLUS            0x200           /* show plus */
56#define CR          0x13
57#define LF          0x10
58
59#define _U      0x01    /* upper */
60#define _L      0x02    /* lower */
61#define _D      0x04    /* digit */
62#define _C      0x08    /* cntrl */
63#define _P      0x10    /* punct */
64#define _S      0x20    /* white space (space/lf/tab) */
65#define _X      0x40    /* hex digit */
66#define _SP     0x80    /* hard space (0x20) */
67
68extern const unsigned char _ctype[];
69/* for strtol */
70#define  max_allowable(A)        (MAXINT/A - 1)
71#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
72
73#define isalnum(c)      ((__ismask(c)&(_U|_L|_D)) != 0)
74#define isalpha(c)      ((__ismask(c)&(_U|_L)) != 0)
75#define iscntrl(c)      ((__ismask(c)&(_C)) != 0)
76#define isdigit(c)      ((__ismask(c)&(_D)) != 0)
77#define isgraph(c)      ((__ismask(c)&(_P|_U|_L|_D)) != 0)
78#define islower(c)      ((__ismask(c)&(_L)) != 0)
79#define isprint(c)      ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
80#define ispunct(c)      ((__ismask(c)&(_P)) != 0)
81#define isspace(c)      ((__ismask(c)&(_S)) != 0)
82#define isupper(c)      ((__ismask(c)&(_U)) != 0)
83#define isxdigit(c)     ((__ismask(c)&(_D|_X)) != 0)
84
85#define isascii(c) (((unsigned char)(c))<=0x7f)
86#define toascii(c) (((unsigned char)(c))&0x7f)
87long strtol(
88        const   char    *str, 
89                char    **endptr, 
90                int     base);
91void *memchr(
92        const   void    *s,
93                int     c,
94                size_t  n);
95
96#ifndef TAB
97#define TAB_CH                 0x09
98#else
99#define TAB_CH                  TAB
100#endif
101
102#define SPACE_CH               0x20
103
104#ifndef SkipWhiteSpace
105#define SkipWhiteSpace(z)  while (*z == TAB_CH || *z == SPACE_CH) z++;
106#endif
107
108#ifndef toupper
109int toupper(int c);
110#endif
111
112#ifndef isnum
113#define isnum(x) (x >= '0' && x <= '9') ? 1 : 0
114#endif
115
116#ifndef ishexnum
117#define ishexnum(x) ((x >= '0' && x <= '9') || ((x & 0xDF) >= 'A' && (x & 0xDF) <= 'F')) ? 1 : 0
118#endif
119
120#ifndef MAXINT
121#define MAXINT  (int)0x7FFFFFFF
122#endif
123#ifndef ERANGE
124#define ERANGE 34
125#endif
126
127int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
128
129/* ********************************************************************* */
130/* Local functions */
131#if 0 /* JPF */
132static int skip_atoi(const char **s)
133{
134    int i=0;
135
136    while (isdigit(**s))
137        i = i*10 + *((*s)++) - '0';
138    return i;
139}
140
141/*
142 * No traps on overflows for any of these...
143 */
144
145#define do_div64_32(res, high, low, base) ({ \
146    unsigned long __quot, __mod; \
147    unsigned long __cf, __tmp, __tmp2, __i; \
148    \
149    __asm__(".set   push\n\t" \
150        ".set   noat\n\t" \
151        ".set   noreorder\n\t" \
152        "move   %2, $0\n\t" \
153        "move   %3, $0\n\t" \
154        "b  1f\n\t" \
155        " li    %4, 0x21\n" \
156        "0:\n\t" \
157        "sll    $1, %0, 0x1\n\t" \
158        "srl    %3, %0, 0x1f\n\t" \
159        "or %0, $1, %5\n\t" \
160        "sll    %1, %1, 0x1\n\t" \
161        "sll    %2, %2, 0x1\n" \
162        "1:\n\t" \
163        "bnez   %3, 2f\n\t" \
164        "sltu   %5, %0, %z6\n\t" \
165        "bnez   %5, 3f\n\t" \
166        "2:\n\t" \
167        " addiu %4,%4,-1\n\t" \
168        "subu   %0, %0, %z6\n\t" \
169        "addiu  %2, %2, 1\n" \
170        "3:\n\t" \
171        "bnez   %4, 0b\n\t" \
172        " srl   %5, %1, 0x1f\n\t" \
173        ".set   pop" \
174        : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
175          "=&r" (__i), "=&r" (__tmp2) \
176        : "Jr" (base), "0" (high), "1" (low)); \
177    \
178    (res) = __quot; \
179    __mod; })
180
181
182#define do_div(n, base) ({ \
183    unsigned long long __quot; \
184    unsigned long __upper, __low, __high, __mod; \
185    \
186    __quot = (n); \
187    __high = __quot >> 32; \
188    __low = __quot; \
189    __upper = __high; \
190    \
191    if (__high) \
192        __asm__("divu   $0,%z2,%z3" \
193            : "=h" (__upper), "=l" (__high) \
194            : "Jr" (__high), "Jr" (base)); \
195    \
196    __mod = do_div64_32(__low, __upper, __low, base); \
197    \
198    __quot = __high; \
199    __quot = __quot << 32 | __low; \
200    (n) = __quot; \
201    __mod; })
202
203static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
204static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
205
206static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
207{
208    char c,sign,tmp[66];
209    const char *digits;
210    int i;
211
212    digits = (type & LONGDBL) ? large_digits : small_digits;
213    if (type & LADJUST)
214        type &= ~ZEROPAD;
215    if (base < 2 || base > 36)
216        return 0;
217    c = (type & ZEROPAD) ? '0' : ' ';
218    sign = 0;
219    if (type & SIGN) {
220        if (num < 0) {
221            sign = '-';
222            num = -num;
223            size--;
224        } else if (type & PLUS) {
225            sign = '+';
226            size--;
227        } else if (type & SPACE) {
228            sign = ' ';
229            size--;
230        }
231    }
232    if (type & HEXPREFIX) {
233        if (base == 16)
234            size -= 2;
235        else if (base == 8)
236            size--;
237    }
238    i = 0;
239    if (num == 0)
240        tmp[i++]='0';
241    else while (num != 0)
242        tmp[i++] = digits[do_div(num,base)];
243    if (i > precision)
244        precision = i;
245    size -= precision;
246    if (!(type&(ZEROPAD+LADJUST))) {
247        while(size-->0) {
248            if (buf <= end)
249                *buf = ' ';
250            ++buf;
251        }
252    }
253    if (sign) {
254        if (buf <= end)
255            *buf = sign;
256        ++buf;
257    }
258    if (type & HEXPREFIX) {
259        if (base==8) {
260            if (buf <= end)
261                *buf = '0';
262            ++buf;
263        } else if (base==16) {
264            if (buf <= end)
265                *buf = '0';
266            ++buf;
267            if (buf <= end)
268                *buf = digits[33];
269            ++buf;
270        }
271    }
272    if (!(type & LADJUST)) {
273        while (size-- > 0) {
274            if (buf <= end)
275                *buf = c;
276            ++buf;
277        }
278    }
279    while (i < precision--) {
280        if (buf <= end)
281            *buf = '0';
282        ++buf;
283    }
284    while (i-- > 0) {
285        if (buf <= end)
286            *buf = tmp[i];
287        ++buf;
288    }
289    while (size-- > 0) {
290        if (buf <= end)
291            *buf = ' ';
292        ++buf;
293    }
294    return buf;
295}
296
297/*
298*********************************************************************************************
299*                                       _doprntx
300*
301* Description:
302*
303* Arguments  :
304*
305* Return     :
306*
307* Note(s)    :
308*********************************************************************************************
309*/
310
311static int _doprntx(
312        char            *fmt0,
313        va_list         argp,
314        void            (*putc)(),
315        char            **pca)
316{
317        uint8_t         *fmt;           /* format string                        */
318        int     ch;             /* character from fmt                   */
319        int     cnt;            /* return value accumulator             */
320        int     n;              /* random handy integer                 */
321        char    *t;             /* buffer pointer */
322        uint32_t        _ulong;         /* integer arguments %[diouxX]          */
323        int     base;           /* base for [diouxX] conversion         */
324        int     dprec;          /* decimal precision in [diouxX]        */
325        int     fieldsz;        /* field size expanded by sign, etc     */
326        int     flags;          /* flags as above                       */
327        int     fpprec;         /* `extra' floating precision in [eEfgG]*/
328        int     prec;           /* precision from format (%.3d), or -1  */
329        int     realsz;         /* field size expanded by decimal precision */
330        int     size;           /* size of converted field or string    */
331        int     width;          /* width from format (%8d), or 0        */
332        char    sign;           /* sign prefix (' ', '+', '-', or \0)   */
333        char    *digs;          /* digits for [diouxX] conversion       */
334        char    buf[BUF];       /* space for %c, %[diouxX], %[eEfgG]    */
335
336        fmt = (uint8_t*)fmt0;
337        digs = "0123456789abcdef";
338
339        for (cnt = 0;; ++fmt) {
340                for (; (ch = *fmt) && ch != '%';
341                     ++cnt, ++fmt)
342                    if(ch!='\n')
343                      putc(ch, pca);
344                    else
345                    { putc(CR, pca); putc(LF, pca); ++cnt; };
346                if (!ch)
347                        return (cnt);
348
349                flags = 0; dprec = 0; fpprec = 0; width = 0;
350                prec = -1;
351                sign = '\0';
352
353rflag:          switch (*++fmt) {
354                case ' ':
355                        /*
356                         * ``If the space and + flags both appear, the space
357                         * flag will be ignored.''
358                         *      -- ANSI X3J11
359                         */
360                        if (!sign)
361                                sign = ' ';
362                        goto rflag;
363                case '#':
364                        flags |= ALT;
365                        goto rflag;
366                case '*':
367                        /*
368                         * ``A negative field width argument is taken as a
369                         * - flag followed by a  positive field width.''
370                         *      -- ANSI X3J11
371                         * They don't exclude field widths read from args.
372                         */
373                        if ((width = va_arg(argp, int)) >= 0)
374                                goto rflag;
375                        width = -width;
376                        /* FALLTHROUGH */
377                case '-':
378                        flags |= LADJUST;
379                        goto rflag;
380                case '+':
381                        sign = '+';
382                        goto rflag;
383                case '.':
384                        if (*++fmt == '*')
385                                n = va_arg(argp, int);
386                        else {
387                                n = 0;
388                                while (isascii(*fmt) && isdigit(*fmt))
389                                        n = 10 * n + todigit(*fmt++);
390                                --fmt;
391                        }
392                        prec = n < 0 ? -1 : n;
393                        goto rflag;
394                case '0':
395                        /*
396                         * ``Note that 0 is taken as a flag, not as the
397                         * beginning of a field width.''
398                         *      -- ANSI X3J11
399                         */
400                        flags |= ZEROPAD;
401                        goto rflag;
402                case '1': case '2': case '3': case '4':
403                case '5': case '6': case '7': case '8': case '9':
404                        n = 0;
405                        do {
406                                n = 10 * n + todigit(*fmt);
407                        } while (isascii(*++fmt) && isdigit(*fmt));
408                        width = n;
409                        --fmt;
410                        goto rflag;
411                case 'L':
412                        flags |= LONGDBL;
413                        goto rflag;
414                case 'h':
415                        flags |= SHORTINT;
416                        goto rflag;
417                case 'l':
418                        flags |= LONGINT;
419                        goto rflag;
420                case 'c':
421                        *(t = buf) = va_arg(argp, int);
422                        size = 1;
423                        sign = '\0';
424                        goto pforw;
425                case 'D':
426                        flags |= LONGINT;
427                        /*FALLTHROUGH*/
428                case 'd':
429                case 'i':
430                        ARG();
431                        if ((long)_ulong < 0) {
432                                _ulong = -_ulong;
433                                sign = '-';
434                        }
435                        base = 10;
436                        goto number;
437                case 'n':
438                        if (flags & LONGINT)
439                                *va_arg(argp, long *) = cnt;
440                        else if (flags & SHORTINT)
441                                *va_arg(argp, short *) = cnt;
442                        else
443                                *va_arg(argp, int *) = cnt;
444                        break;                 
445                case 'O':
446                        flags |= LONGINT;
447                        /*FALLTHROUGH*/
448                case 'o':
449                        ARG();
450                        base = 8;
451                        goto nosign;
452                case 'p':
453                        /*
454                         * ``The argument shall be a pointer to void.  The
455                         * value of the pointer is converted to a sequence
456                         * of printable characters, in an implementation-
457                         * defined manner.''
458                         *      -- ANSI X3J11
459                         */
460                        /* NOSTRICT */
461                        _ulong = (uint32_t)va_arg(argp, void *);
462                        base = 16;
463                        goto nosign;
464                case 's':
465                        if (!(t = va_arg(argp, char *)))
466                                t = "(null)";
467                        if (prec >= 0) {
468                                /*
469                                 * can't use strlen; can only look for the
470                                 * NUL in the first `prec' characters, and
471                                 * strlen() will go further.
472                                 */
473                                char *p;
474
475                                if ((p = memchr(t, 0, prec))) {
476                                        size = p - t;
477                                        if (size > prec)
478                                                size = prec;
479                                } else
480                                        size = prec;
481                        } else
482                                size = strlen(t);
483                        sign = '\0';
484                        goto pforw;
485                case 'U':
486                        flags |= LONGINT;
487                        /*FALLTHROUGH*/
488                case 'u':
489                        ARG();
490                        base = 10;
491                        goto nosign;
492                case 'X':
493                        digs = "0123456789ABCDEF";
494                        /* FALLTHROUGH */
495                case 'x':
496                        ARG();
497                        base = 16;
498                        /* leading 0x/X only if non-zero */
499                        if (flags & ALT && _ulong != 0)
500                                flags |= HEXPREFIX;
501
502                        /* unsigned conversions */
503nosign:                 sign = '\0';
504                        /*
505                         * ``... diouXx conversions ... if a precision is
506                         * specified, the 0 flag will be ignored.''
507                         *      -- ANSI X3J11
508                         */
509number:                 if ((dprec = prec) >= 0)
510                                flags &= ~ZEROPAD;
511
512                        /*
513                         * ``The result of converting a zero value with an
514                         * explicit precision of zero is no characters.''
515                         *      -- ANSI X3J11
516                         */
517                        t = buf + BUF;
518                        if (_ulong != 0 || prec != 0) {
519                                do {
520                                        *--t = digs[_ulong % base];
521                                        _ulong /= base;
522                                } while (_ulong);
523                                digs = "0123456789abcdef";
524                                if (flags & ALT && base == 8 && *t != '0')
525                                        *--t = '0'; /* octal leading 0 */
526                        }
527                        size = buf + BUF - t;
528
529pforw:
530                        /*
531                         * All reasonable formats wind up here.  At this point,
532                         * `t' points to a string which (if not flags&LADJUST)
533                         * should be padded out to `width' places.  If
534                         * flags&ZEROPAD, it should first be prefixed by any
535                         * sign or other prefix; otherwise, it should be blank
536                         * padded before the prefix is emitted.  After any
537                         * left-hand padding and prefixing, emit zeroes
538                         * required by a decimal [diouxX] precision, then print
539                         * the string proper, then emit zeroes required by any
540                         * leftover floating precision; finally, if LADJUST,
541                         * pad with blanks.
542                         */
543
544                        /*
545                         * compute actual size, so we know how much to pad
546                         * fieldsz excludes decimal prec; realsz includes it
547                         */
548                        fieldsz = size + fpprec;
549                        if (sign)
550                                fieldsz++;
551                        if (flags & HEXPREFIX)
552                                fieldsz += 2;
553                        realsz = dprec > fieldsz ? dprec : fieldsz;
554
555                        /* right-adjusting blank padding */
556                        if ((flags & (LADJUST|ZEROPAD)) == 0 && width)
557                                for (n = realsz; n < width; n++)
558                                        putc(' ', pca);
559                        /* prefix */
560                        if (sign)
561                                putc(sign, pca);
562                        if (flags & HEXPREFIX) {
563                                putc('0', pca);
564                                putc((char)*fmt, pca);
565                        }
566                        /* right-adjusting zero padding */
567                        if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
568                                for (n = realsz; n < width; n++)
569                                        putc('0', pca);
570                        /* leading zeroes from decimal precision */
571                        for (n = fieldsz; n < dprec; n++)
572                                putc('0', pca);
573
574                        /* the string or number proper */
575                        n=size;
576                        while (--n >= 0)
577                          putc(*t++, pca);
578                        /* trailing f.p. zeroes */
579                        while (--fpprec >= 0)
580                                putc('0', pca);
581                        /* left-adjusting padding (always blank) */
582                        if (flags & LADJUST)
583                                for (n = realsz; n < width; n++)
584                                        putc(' ', pca);
585                        /* finally, adjust cnt */
586                        cnt += width > realsz ? width : realsz;
587                        break;
588                case '\0':      /* "%?" prints ?, unless ? is NULL */
589                        return (cnt);
590                default:
591                        putc((char)*fmt, pca);
592                        cnt++;
593                }
594        }
595        /* NOTREACHED */
596}
597
598/* ********************************************************************* */
599/* Global functions */
600
601/*
602*********************************************************************************************
603*                                       atoi
604*
605* Description: Look in the standard headers.
606*
607* Arguments  :
608*
609* Return     :
610*
611* Note(s)    :
612*********************************************************************************************
613*/
614int atoi(char *s)
615{
616  return (int) strtol ((const char *)s, (char **) 0, 10);
617}
618#endif
619/*
620*********************************************************************************************
621*                                       memchr
622*
623* Description: Look in the standard headers.
624*
625* Arguments  :
626*
627* Return     :
628*
629* Note(s)    :
630*********************************************************************************************
631*/
632void *memchr(
633        const   void    *s,
634                int     c,
635                size_t  n)
636{
637        char *mys = (char *)s;
638        while ((int)--n >= 0)
639            if (*mys++ == c) 
640                return (void *) --mys;
641        return NULL;
642}
643#if 0 /* JPF */
644/*
645*********************************************************************************************
646*                                       putch
647*
648* Description: Look in the standard headers.
649*
650* Arguments  :
651*
652* Return     :
653*
654* Note(s)    :
655*********************************************************************************************
656*/
657
658static void putch(char ch, char **pca)
659{
660        *(*pca)++ = ch;
661}
662
663/*
664*********************************************************************************************
665*                                       printf
666*
667* Description: Look in the standard headers.
668*
669* Arguments  :
670*
671* Return     :
672*
673* Note(s)    :
674*********************************************************************************************
675*/
676
677static void _putc(char ch, char **pca)
678{
679    CONSOL_SendCh(ch);
680}
681
682
683int printf(const char *fmt, ...)
684{
685    int ret;
686    va_list args;
687    va_start(args,fmt);
688    ret = _doprntx((char *)fmt, args, (void (*)())_putc, 0);
689    va_end(args);
690    return ret;
691}
692
693int vprintf(const char *fmt, va_list ap)
694{
695        int ret;
696        ret = _doprntx((char *)fmt, ap, (void (*)())_putc, 0);
697        return ret;
698}
699
700/*
701*********************************************************************************************
702*                                       vsprintf
703*
704* Description: Look in the standard headers.
705*
706* Arguments  :
707*
708* Return     :
709*
710* Note(s)    :
711*********************************************************************************************
712*/
713
714int vsprintf(char *buf, char *fmt, va_list ap)
715{
716        int len = _doprntx(fmt, ap, (void (*)())putch, &buf);
717
718        putch(0, &buf);
719        return len;
720}
721#endif
722/*
723*********************************************************************************************
724*                                       sprintf
725*
726* Description: Look in the standard headers.
727*
728* Arguments  :
729*
730* Return     :
731*
732* Note(s)    :
733*********************************************************************************************
734*/
735
736int sprintf(char* buf, ...)
737{
738        va_list args;
739        char    *fmt;
740        int     len;
741
742        va_start(args, buf);
743        fmt = va_arg(args, char *);
744    len = vsnprintf(buf, 256, fmt, args);
745        va_end(args);
746
747        return len;
748}
749
750/*
751*********************************************************************************************
752*                                       strcpy
753*
754* Description: Look in the standard headers.
755*
756* Arguments  :
757*
758* Return     :
759*
760* Note(s)    :
761*********************************************************************************************
762*/
763#if 0 /* JPF */
764char *strcpy(char *s1, const char *s2)
765{
766        char            *s = s1;
767
768        while ((*s1++ = *s2++));
769        return s;
770}
771
772/*
773*********************************************************************************************
774*                                       strlen
775*
776* Description: Look in the standard headers.
777*
778* Arguments  :
779*
780* Return     :
781*
782* Note(s)    :
783*********************************************************************************************
784*/
785
786int strlen(const char *s)
787{
788        int     l = 0;
789
790        while (*s++) l++;
791        return l;
792}
793#endif
794
795/*
796*********************************************************************************************
797*                                       strtol
798*
799* Description: Look in the standard headers.
800*
801* Arguments  :
802*
803* Return     :
804*
805* Note(s)    :
806*********************************************************************************************
807*/
808
809long strtol(
810        const   char    *str, 
811                char    **endptr, 
812                int     base)
813{
814        long    i = 0;
815        int     s = 1;
816        int     c;
817       
818        /* skip white space */
819        while(isspace(*str)) {
820                str++;
821        }
822       
823        /* sign flag check */
824        if (*str == '+') str++;
825        else if (*str == '-') {
826                s = -1;
827                str++;
828        }
829
830        if (*str == '0') {
831                if (toupper(*++str) == 'X')     base = 16,str++;
832                else if (base == 0)             base = 8;
833                }
834        if (base == 0) base = 10;
835       
836       
837        if (base <= 10)
838        /* digit str to number */
839                for (; isdigit(*str); str++) {
840                        if (i < max_allowable(base))
841                                i = i * base + (*str - '0');
842                        else {
843                                i = MAXINT;
844                                errno = ERANGE;
845                        }
846                }
847        else if (base > 10) {
848                for (; (c = *str); str++) {
849                        if (isdigit(c))
850                                c = c - '0';
851                        else {
852                                c = toupper(c);
853
854                                if (c >= 'A' && c < ('A' - 10 + base))
855                                        c = c - 'A' + 10;
856                                else
857                                        break;
858                        }
859                        if (i < max_allowable(base))
860                                i = i * base + c;
861                        else {
862                                i = MAXINT;
863                                errno = ERANGE;
864                        }
865                }
866        }       
867        else
868                return 0;               /* negative base is not allowed */
869       
870        if (endptr) *endptr = (char *) str;
871
872        if (s == -1)
873                i = -i;
874
875        return i;
876}
877
878/*
879*********************************************************************************************
880*                                       tolower
881*
882* Description: Look in the standard headers.
883*
884* Arguments  :
885*
886* Return     :
887*
888* Note(s)    :
889*********************************************************************************************
890*/
891
892int tolower(int c)
893{
894        if (isupper(c))
895                return c + ('a' - 'A'); else
896                return c;
897}
898
899/*
900*********************************************************************************************
901*                                       toupper
902*
903* Description: Look in the standard headers.
904*
905* Arguments  :
906*
907* Return     :
908*
909* Note(s)    :
910*********************************************************************************************
911*/
912
913int toupper(int c)
914{
915        if (islower(c))
916                return c - ('a' - 'A'); else
917                return c;
918}
919
920/*
921*********************************************************************************************
922*                                       memcmp
923*
924* Description: Look in the standard headers.
925*       The memcmp() function returns  an  integer  less  than,  equal  to,  or
926*       greater than zero if the first n bytes of s1 is found, respectively, to
927*       be less than, to match, or be greater than the first n bytes of s2.
928*
929* Arguments  :
930*               s1      pointer to first memory address to compare
931*               s2      pointer to 2nd memory address to compare
932*               n       number of bytes to compare
933* Return     :
934*
935* Note(s)    :
936*********************************************************************************************
937*/
938#if 0 /* JPF */
939int memcmp(const void *s1, const void *s2, size_t n)
940{
941        register unsigned char c1, c2;
942
943        for (; n--; s1++, s2++) {
944                c1 = *(unsigned char *)s1;
945                c2 = *(unsigned char *)s2;
946                if (c1 != c2)
947                        return (c1 - c2);
948        }
949        return 0;
950}
951
952/*
953*********************************************************************************************
954*                                       strcmp
955*
956*       The  strcmp()  function compares the two strings s1 and s2.  It returns
957*       an integer less than, equal to, or greater than zero if  s1  is  found,
958*       respectively, to be less than, to match, or be greater than s2.
959*
960* Arguments  :
961*               s1      pointer to first string address to compare
962*               s2      pointer to 2nd string address to compare
963* Return     :
964*
965* Note(s)    :
966*********************************************************************************************
967*/
968int strcmp(const char *s1, const char *s2)
969{
970        while (*s1 == *s2++) {
971                if ('\0' == *s1++)
972                        return 0;
973        };
974        return (*s1 - *s2);
975}
976#endif
977/*
978*********************************************************************************************
979*                                       strncmp
980*
981*       The  strncmp()  function  is similar, except it only compares the first
982*       (at most) n characters of s1 and s2.
983*
984* Arguments  :
985*               s1      pointer to first string address to compare
986*               s2      pointer to 2nd string address to compare
987*               n       number of bytes to compare
988* Return     :
989*
990* Note(s)    :
991*********************************************************************************************
992*/
993#if 0
994int strncmp(const char *s1, const char *s2, size_t n)
995{
996        register unsigned char c1, c2;
997       
998        while (n-- > 0) {
999                c1 = (unsigned char)*s1++;
1000                c2 = (unsigned char)*s2++;
1001                if (c1 != c2)
1002                        return (c1 - c2);
1003                if ('\0' == c1)
1004                        return 0;
1005        }
1006        return 0;
1007}
1008#endif
1009/*
1010*********************************************************************************************
1011*                                       strncpy
1012*
1013*       The strncpy() function is similar, except that not more than n bytes of
1014*       src  are copied. Thus, if there is no null byte among the first n bytes
1015*       of src, the result will not be null-terminated.
1016*
1017* Arguments  :
1018*               dest      pointer to destination address to copy
1019*               src       pointer to source address to copy
1020*               n       number of bytes to compare
1021* Return     :
1022*
1023* Note(s)    :
1024*********************************************************************************************
1025*/
1026#if 0 /* JPF */
1027char *strncpy(char *dest, const char *src, size_t n)
1028{
1029        if (n != 0) {
1030                register char *d = dest;
1031                register const char *s = src;
1032
1033                do {
1034                        if ((*d++ = *s++) == 0) {
1035                                /* NUL pad the remaining n-1 bytes */
1036                                while (--n != 0)
1037                                        *d++ = 0;
1038                                break;
1039                        }
1040                } while (--n != 0);
1041        }
1042        return (dest);
1043}
1044#endif
1045/*
1046 *********************************************************************************************
1047 *                                       strcat
1048 *
1049 *      The  strcat()  function appends the src string to the dest string over-
1050 *      writing the `\0' character at the end of dest, and then adds  a  termi-
1051 *      nating  `\0'  character.   The  strings  may  not overlap, and the dest
1052 *      string must have enough space for the result.
1053 *
1054 * Arguments  :
1055 *               dest      pointer to destination address to concatenate
1056 *               src       pointer to source address to concatenate
1057 * Return     :
1058 *
1059 * Note(s)    :
1060 *********************************************************************************************
1061 */
1062char *strcat(char *dest, const char *src)
1063{
1064        register char *s1 = dest;
1065
1066        while (*dest++);
1067        --dest;
1068
1069        while ((*dest++ = *src++));
1070
1071        return s1;
1072}
1073/*
1074 *********************************************************************************************
1075 *                                       strcat
1076 *
1077 *      The  strcat()  function appends the src string to the dest string over-
1078 *      writing the `\0' character at the end of dest, and then adds  a  termi-
1079 *      nating  `\0'  character.   The  strings  may  not overlap, and the dest
1080 *      string must have enough space for the result.
1081 *
1082 * Arguments  :
1083 *               dest      pointer to destination address to concatenate
1084 *               src       pointer to source address to concatenate
1085 * Return     :
1086 *
1087 * Note(s)    :
1088 *********************************************************************************************
1089 */
1090char *strncat(char *dest, const char *src,int n)
1091{
1092        register char *s1 = dest;
1093
1094        while (*dest++);
1095        --dest;
1096
1097        while ((*dest++ = *src++));
1098
1099        return s1;
1100}
1101
1102/*
1103 *********************************************************************************************
1104 *                                       memmove
1105 *
1106 * The  memmove()  function  copies n bytes from memory area src to memory
1107 *     area dest.  The memory areas may overlap.
1108 *
1109 * Arguments  :
1110 *               dest      pointer to destination address to move
1111 *               src       pointer to source address to move
1112 *               n         n bytes to move
1113 * Return     :
1114 *
1115 * Note(s)    :
1116 *********************************************************************************************
1117 */
1118void *memmove(void *dest, const void *src, size_t n)
1119{
1120        return memcpy(dest, src, n);
1121}
1122
1123/*
1124 *********************************************************************************************
1125 *                                       strchr
1126 *
1127 *
1128 * The  strchr() function returns a pointer to the first occurrence of the
1129 *      character c in the string s.
1130 *
1131 * Arguments  :
1132 *               s      pointer to string to search for
1133 *               c      charactor to search for
1134 * Return     :
1135 *
1136 * Note(s)    :
1137 *********************************************************************************************
1138 */
1139char *strchr(register const char *s, int c)
1140{
1141        do {
1142                if ((int)(*s) == c)
1143                {       
1144                        return (char *)s;
1145                }
1146        } while (*s++);
1147
1148        return 0;
1149}
1150
1151/*
1152 *********************************************************************************************
1153 *                                       sscanf
1154 *
1155 *
1156 * The scanf family of functions scans input  according  to  a  format  as
1157 *      described  below.   This  format may contain conversion specifiers; the
1158 *      results from such conversions, if any, are stored through  the  pointer
1159 *      arguments.   The  scanf  function  reads  input from the standard input
1160 *      stream stdin, fscanf reads input from the stream  pointer  stream,  and
1161 *      sscanf reads its input from the character string pointed to by str.
1162 *
1163 * Arguments  :
1164 *               buf    pointer to string to scan for
1165 *               fmt    format string to scan for
1166 *               arg    arguments. Note that only one parameter is used.
1167 * Return     :
1168 *
1169 * Note(s)    :
1170 *********************************************************************************************
1171 */
1172#if 0 /* JPF */
1173int sscanf (char* buf, const char* fmt, unsigned int * arg)
1174{
1175    int valid;
1176    unsigned int result, base;
1177    char * pbuf;
1178
1179    if (!buf || !fmt || !arg)
1180        return 0;
1181
1182    SkipWhiteSpace(fmt);
1183    SkipWhiteSpace(buf);
1184
1185    pbuf = buf;
1186
1187    if (*fmt != '%')
1188        return 0;
1189    fmt++;
1190    if (*fmt == 'x' || *fmt == 'X')
1191        base = 16;
1192    else if (*fmt == 'd' || *fmt == 'D')
1193        base = 10;
1194    else
1195        return 0;
1196
1197    for (valid=0,result=0,pbuf=buf; ishexnum(*pbuf); pbuf++)
1198    {
1199        result *= base;
1200        if (isnum (*pbuf))
1201            result += (unsigned long) (*pbuf - 0x30);
1202        else if (base == 16)
1203            result += (unsigned long) (toupper(*pbuf) - 0x37);
1204        else
1205            return 0;
1206        valid=1;
1207    }
1208    if (valid)
1209        *arg = result;
1210
1211    return valid;
1212}
1213
1214size_t strnlen(const char * s, size_t count)
1215{
1216    const char *sc;
1217
1218    for (sc = s; count-- && *sc != '\0'; ++sc)
1219        /* nothing */;
1220    return sc - s;
1221}
1222int perror(const char *str)
1223{
1224    printf(str); printf("\n");
1225    return 0;
1226}
1227#endif
1228
1229/**
1230* vsnprintf - Format a string and place it in a buffer
1231* @buf: The buffer to place the result into
1232* @size: The size of the buffer, including the trailing null space
1233* @fmt: The format string to use
1234* @args: Arguments for the format string
1235*
1236* Call this function if you are already dealing with a va_list.
1237* You probably want snprintf instead.
1238 */
1239#if 0 /* JPF */
1240int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
1241{
1242    int len;
1243    unsigned long long num;
1244    int i, base;
1245    char *str, *end, c;
1246    const char *s;
1247
1248    int flags;      /* flags to number() */
1249
1250    int field_width;    /* width of output field */
1251    int precision;      /* min. # of digits for integers; max
1252                   number of chars for from string */
1253    int qualifier;      /* 'h', 'l', or 'L' for integer fields */
1254                /* 'z' support added 23/7/1999 S.H.    */
1255                /* 'z' changed to 'Z' --davidm 1/25/99 */
1256
1257    str = buf;
1258    end = buf + size - 1;
1259
1260    if (end < buf - 1) {
1261        end = ((void *) -1);
1262        size = end - buf + 1;
1263    }
1264
1265    for (; *fmt ; ++fmt) {
1266        if (*fmt != '%') {
1267            if (str <= end)
1268                *str = *fmt;
1269            ++str;
1270            continue;
1271        }
1272
1273
1274        /* process flags */
1275        flags = 0;
1276        repeat:
1277            ++fmt;      /* this also skips first '%' */
1278            switch (*fmt) {
1279                case '-': flags |= LADJUST; goto repeat;
1280                case '+': flags |= PLUS; goto repeat;
1281                case ' ': flags |= SPACE; goto repeat;
1282                case '#': flags |= HEXPREFIX; goto repeat;
1283                case '0': flags |= ZEROPAD; goto repeat;
1284            }
1285
1286        /* get field width */
1287        field_width = -1;
1288        if (isdigit(*fmt))
1289            field_width = skip_atoi(&fmt);
1290        else if (*fmt == '*') {
1291            ++fmt;
1292            /* it's the next argument */
1293            field_width = va_arg(args, int);
1294            if (field_width < 0) {
1295                field_width = -field_width;
1296                flags |= LADJUST;
1297            }
1298        }
1299
1300        /* get the precision */
1301        precision = -1;
1302        if (*fmt == '.') {
1303            ++fmt;
1304            if (isdigit(*fmt))
1305                precision = skip_atoi(&fmt);
1306            else if (*fmt == '*') {
1307                ++fmt;
1308                /* it's the next argument */
1309                precision = va_arg(args, int);
1310            }
1311            if (precision < 0)
1312                precision = 0;
1313        }
1314
1315
1316        /* get the conversion qualifier */
1317        qualifier = -1;
1318        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
1319            qualifier = *fmt;
1320            ++fmt;
1321            if (qualifier == 'l' && *fmt == 'l') {
1322                qualifier = 'L';
1323                ++fmt;
1324            }
1325        }
1326
1327        /* default base */
1328        base = 10;
1329
1330        switch (*fmt) {
1331            case 'c':
1332                if (!(flags & LADJUST)) {
1333                    while (--field_width > 0) {
1334                        if (str <= end)
1335                            *str = ' ';
1336                        ++str;
1337                    }
1338                }
1339                c = (unsigned char) va_arg(args, int);
1340                if (str <= end)
1341                    *str = c;
1342                ++str;
1343                while (--field_width > 0) {
1344                    if (str <= end)
1345                        *str = ' ';
1346                    ++str;
1347                }
1348                continue;
1349
1350            case 's':
1351                s = va_arg(args, char *);
1352                if (!s)
1353                    s = "<NULL>";
1354
1355                len = strnlen(s, precision);
1356                len = strnlen(s, precision);
1357
1358                if (!(flags & LADJUST)) {
1359                    while (len < field_width--) {
1360                        if (str <= end)
1361                            *str = ' ';
1362                        ++str;
1363                    }
1364                }
1365                for (i = 0; i < len; ++i) {
1366                    if (str <= end)
1367                        *str = *s;
1368                    ++str; ++s;
1369                }
1370                while (len < field_width--) {
1371                    if (str <= end)
1372                        *str = ' ';
1373                    ++str;
1374                }
1375                continue;
1376
1377            case 'p':
1378                if (field_width == -1) {
1379                    field_width = 2*sizeof(void *);
1380                    flags |= ZEROPAD;
1381                }
1382                str = number(str, end,
1383                        (unsigned long) va_arg(args, void *),
1384                        16, field_width, precision, flags);
1385                continue;
1386
1387            case 'n':
1388                /* FIXME:
1389                * What does C99 say about the overflow case here? */
1390                if (qualifier == 'l') {
1391                    long * ip = va_arg(args, long *);
1392                    *ip = (str - buf);
1393                } else if (qualifier == 'Z') {
1394                    size_t * ip = va_arg(args, size_t *);
1395                    *ip = (str - buf);
1396                } else {
1397                    int * ip = va_arg(args, int *);
1398                    *ip = (str - buf);
1399                }
1400                continue;
1401
1402            case '%':
1403                if (str <= end)
1404                    *str = '%';
1405                ++str;
1406                continue;
1407
1408                /* integer number formats - set up the flags and "break" */
1409            case 'o':
1410                base = 8;
1411                break;
1412
1413            case 'X':
1414                flags |= LONGDBL;
1415            case 'x':
1416                base = 16;
1417                break;
1418
1419            case 'd':
1420            case 'i':
1421                flags |= SIGN;
1422            case 'u':
1423                break;
1424
1425            default:
1426                if (str <= end)
1427                    *str = '%';
1428                ++str;
1429                if (*fmt) {
1430                    if (str <= end)
1431                        *str = *fmt;
1432                    ++str;
1433                } else {
1434                    --fmt;
1435                }
1436                continue;
1437        }
1438        if (qualifier == 'L')
1439            num = va_arg(args, long long);
1440        else if (qualifier == 'l') {
1441            num = va_arg(args, unsigned long);
1442            if (flags & SIGN)
1443                num = (signed long) num;
1444        } else if (qualifier == 'Z') {
1445            num = va_arg(args, size_t);
1446        } else if (qualifier == 'h') {
1447            num = (unsigned short) va_arg(args, int);
1448            if (flags & SIGN)
1449                num = (signed short) num;
1450        } else {
1451            num = va_arg(args, unsigned int);
1452            if (flags & SIGN)
1453                num = (signed int) num;
1454        }
1455        str = number(str, end, num, base,
1456                field_width, precision, flags);
1457    }
1458    if (str <= end)
1459        *str = '\0';
1460    else if (size > 0)
1461        /* don't write out a null byte if the buf size is zero */
1462        *end = '\0';
1463    /* the trailing null byte doesn't count towards the total
1464    * ++str;
1465    */
1466    return str-buf;
1467}
1468#endif
1469/**
1470 * strtoul - convert a string to an unsigned long
1471 * @cp: The start of the string
1472 * @endp: A pointer to the end of the parsed string will be placed here
1473 * @base: The number base to use
1474 */
1475unsigned long strtoul(const char *cp,char **endp,int base)
1476{
1477    unsigned long result = 0,value;
1478
1479    if (!base) {
1480        base = 10;
1481        if (*cp == '0') {
1482            base = 8;
1483            cp++;
1484            if ((*cp == 'x') && isxdigit(cp[1])) {
1485                cp++;
1486                base = 16;
1487            }
1488        }
1489    }
1490    while (isxdigit(*cp) &&
1491           (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
1492        result = result*base + value;
1493        cp++;
1494    }
1495    if (endp)
1496        *endp = (char *)cp;
1497    return result;
1498}
1499
1500char* strtok(char *s, const char *delim)
1501{
1502  const char *spanp;
1503  int c, sc;
1504  char *tok;
1505  static char *last;
1506   
1507  if (s == NULL && (s = last) == NULL)
1508    return (NULL);
1509
1510  /*
1511   * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
1512   */
1513 cont:
1514  c = *s++;
1515  for (spanp = delim; (sc = *spanp++) != 0;) {
1516    if (c == sc)
1517      goto cont;
1518  }
1519
1520  if (c == 0) {                 /* no non-delimiter characters */
1521    last = NULL;
1522    return (NULL);
1523  }
1524  tok = s - 1;
1525
1526  /*
1527   * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
1528   * Note that delim must have one NUL; we stop if we see that, too.
1529   */
1530  for (;;) {
1531    c = *s++;
1532    spanp = delim;
1533    do {
1534      if ((sc = *spanp++) == c) {
1535        if (c == 0)
1536          s = NULL;
1537        else
1538          s[-1] = 0;
1539        last = s;
1540        return (tok);
1541      }
1542    } while (sc != 0);
1543  }
1544  /* NOTREACHED */
1545}
1546
1547/*
1548 * The strspn() function calculates the length of the initial segment of s
1549 *      which consists entirely of characters in accept.
1550 */
1551int
1552strspn (const char *string, const char *accept)
1553{
1554  size_t count = 0;
1555  while (strchr (accept, *string))
1556    {
1557      ++count, ++string;
1558    }
1559
1560  return count;
1561}
1562
1563/*
1564 * The strcspn() function calculates the length of the initial segment  of
1565 *      s which consists entirely of characters not in reject.
1566 *  which contains no characters from REJECT.
1567 */
1568int
1569strcspn (const char *s, const char *reject)
1570{
1571  size_t count = 0;
1572
1573  while (*s != '\0')
1574    if (strchr (reject, *s++) == NULL)
1575      ++count;
1576    else
1577      return count;
1578
1579  return count;
1580}
1581
1582/*
1583 * The  strstr() function finds the first occurrence of the substring nee-
1584 *      dle in the string haystack.  The terminating `\0'  characters  are  not
1585 *      compared.
1586 */
1587char *
1588strstr (const char *buf, const char *sub)
1589{
1590  register char *bp;
1591  register char *sp;
1592
1593  if (!*sub)
1594    return (char *)buf;
1595  while (*buf)
1596    {
1597      bp = (char *)buf;
1598      sp = (char *)sub;
1599      do {
1600          if (!*sp)
1601            return (char *)buf;
1602      } while (*bp++ == *sp++);
1603      buf += 1;
1604    }
1605  return NULL;
1606}
1607
1608void exit(int stat)
1609{
1610        __asm__("sdbbp");
1611}
1612
1613void abort(int stat)
1614{
1615        __asm__("sdbbp");
1616}
1617
1618int abs(int j)
1619{
1620        if (j < 0)
1621                return -j;
1622        return j;
1623}
1624
1625/* ministd.c also defined this function */
1626#if 0
1627void *realloc(void *ptr,int size)
1628{
1629    void *nptr;
1630    if (!ptr)
1631        return malloc(size);
1632
1633    nptr = malloc(size);
1634
1635    if (!nptr)
1636        return NULL;
1637
1638    memcpy(nptr,ptr,size);
1639    free(ptr);
1640    return nptr;
1641}
1642#endif
1643
1644/* bdbg.c also defined this function */
1645#if 0
1646char* strrchr(char *s,int c)
1647{
1648    int len = strlen(s);
1649    char* lptr = &s[len];
1650
1651    while (len) {
1652        if (*lptr == (char)c) {
1653            return lptr;
1654        }
1655                len--;
1656                lptr--;
1657    }
1658    return NULL;
1659}
1660#endif
1661
1662char * strpbrk (const char *s, const char *accept)
1663{
1664  while (*s != '\0')
1665    {
1666      const char *a = accept;
1667      while (*a != '\0')
1668        if (*a++ == *s)
1669          return (char *) s;
1670      ++s;
1671    }
1672
1673  return NULL;
1674}
1675
1676typedef struct div_t
1677{
1678    int q;
1679    int rem;
1680}div_t;
1681
1682div_t div(int num, int den)
1683{
1684    static div_t q;
1685
1686    q.q = num/den;
1687    q.rem = num % den;
1688    return q;
1689}
1690
1691extern int atoi(char *s);
1692
1693long atol(char* s)
1694{
1695    return (long)atoi(s);
1696}
1697
1698char *strerror(int errnum)
1699{
1700    static char s_errstr[64];
1701    snprintf(s_errstr,64,"%s = %d\n",__FUNCTION__,errnum);
1702    return s_errstr;
1703}
1704/* ********************************************************************* */
Note: See TracBrowser for help on using the repository browser.