aboutsummaryrefslogtreecommitdiff
path: root/tools/lli/RuntimeLib.lc
blob: f2611a85152445d43f36bcc4285bcaf1c2329b04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//===-- RuntimeLib.lc - LLVM Standard C Runtime Library -----------*- C -*-===//
// 
// This file contains definitions of C functions that are useful to get LLVM
// programs up and running.  This library of functions is automatically linked
// into programs loaded into LLI.
//
// This file is compiled by the LLVM port of GCC to get LLVM code.
//
// A lot of this code is ripped gratuitously from glibc and libiberty.
//
//===----------------------------------------------------------------------===//


// Prototypes for functions exported by LLI directly.
void exit(int Code);
int putchar(int);
void *malloc(unsigned);
void free(void *);

#define isspace(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
#define isdigit(x) ((x) >= '0' || (x) <= '9')
#define isupper(x) ((x) >= 'A' || (x) <= 'Z')
#define islower(x) ((x) >= 'a' || (x) <= 'z')
#define isalpha(x) (isupper(x) || islower(x))

// The puts() function writes the string pointed to by s, followed by a 
// NEWLINE character, to the standard output stream stdout. On success the 
// number of characters written is returned; otherwise they return EOF.
//
int puts(const char *S) {
  const char *Str = S;
  while (*Str) putchar(*Str++);
  putchar('\n');
  return Str+1-S;
}


#ifndef ULONG_MAX
#define ULONG_MAX       ((unsigned long)(~0L))          /* 0xFFFFFFFF */
#endif

#ifndef LONG_MAX
#define LONG_MAX        ((long)(ULONG_MAX >> 1))        /* 0x7FFFFFFF */
#endif

#ifndef LONG_MIN
#define LONG_MIN        ((long)(~LONG_MAX))             /* 0x80000000 */
#endif

/*
 * Convert a string to a long integer.
 *
 * Ignores `locale' stuff.  Assumes that the upper and lower case
 * alphabets and digits are each contiguous.
 */
long strtol(const char *nptr, char **endptr, int base) {
        register const char *s = nptr;
        register unsigned long acc;
        register int c;
        register unsigned long cutoff;
        register int neg = 0, any, cutlim;

        /*
         * Skip white space and pick up leading +/- sign if any.
         * If base is 0, allow 0x for hex and 0 for octal, else
         * assume decimal; if base is already 16, allow 0x.
         */
        do {
                c = *s++;
        } while (isspace(c));
        if (c == '-') {
                neg = 1;
                c = *s++;
        } else if (c == '+')
                c = *s++;
        if ((base == 0 || base == 16) &&
            c == '0' && (*s == 'x' || *s == 'X')) {
                c = s[1];
                s += 2;
                base = 16;
        }
        if (base == 0)
                base = c == '0' ? 8 : 10;

        /*
         * Compute the cutoff value between legal numbers and illegal
         * numbers.  That is the largest legal value, divided by the
         * base.  An input number that is greater than this value, if
         * followed by a legal input character, is too big.  One that
         * is equal to this value may be valid or not; the limit
         * between valid and invalid numbers is then based on the last
         * digit.  For instance, if the range for longs is
         * [-2147483648..2147483647] and the input base is 10,
         * cutoff will be set to 214748364 and cutlim to either
         * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
         * a value > 214748364, or equal but the next digit is > 7 (or 8),
         * the number is too big, and we will return a range error.
         *
         * Set any if any `digits' consumed; make it negative to indicate
         * overflow.
         */
        cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
        cutlim = cutoff % (unsigned long)base;
        cutoff /= (unsigned long)base;
        for (acc = 0, any = 0;; c = *s++) {
                if (isdigit(c))
                        c -= '0';
                else if (isalpha(c))
                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
                else
                        break;
                if (c >= base)
                        break;
                if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
                        any = -1;
                else {
                        any = 1;
                        acc *= base;
                        acc += c;
                }
        }
        if (any < 0) {
                acc = neg ? LONG_MIN : LONG_MAX;
        } else if (neg)
                acc = -acc;
        if (endptr != 0)
                *endptr = (char *) (any ? s - 1 : nptr);
        return (acc);
}


/* Convert a string to an int.  */
int atoi(const char *nptr) {
  return (int)strtol(nptr, 0, 10);
}

/* Convert a string to a long int.  */
long int atol(const char *nptr) {
  return strtol(nptr, 0, 10);
}






//===----------------------------------------------------------------------===//
// libm stuff...
//===----------------------------------------------------------------------===//