stdlib 6.17 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
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
/* Copyright 1996 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* stdlib.c: ANSI draft (X3J11 Oct 86) library, section 4.10 */
/* Copyright (C) Codemist Ltd, 1988 */
/* version 0.02a */

#include "hostsys.h"      /* for _terminateio(), and _exit() etc */
#include "kernel.h"
#include <stdlib.h>
#include <signal.h>

/* atof, atoi, atol, strtod, strtol, strtoul are implemented in scanf.c  */

/* mblen, mbtowc, wctomb, mbstowcs, wcstombs are implemented in locale.c */

static unsigned long int next = 1;

int _ANSI_rand()     /* This is the ANSI suggested portable code */
{
    next = next * 1103515245 + 12345;
    return (unsigned int) (next >> 16) % 32768;
}

void _ANSI_srand(unsigned int seed)
{
    next = seed;
}

/* Now the random-number generator that the world is expected to use */

static unsigned _random_number_seed[55] =
/* The values here are just those that would be put in this horrid
   array by a call to __srand(1). DO NOT CHANGE __srand() without
   making a corresponding change to these initial values.
*/
{   0x00000001, 0x66d78e85, 0xd5d38c09, 0x0a09d8f5, 0xbf1f87fb,
    0xcb8df767, 0xbdf70769, 0x503d1234, 0x7f4f84c8, 0x61de02a3,
    0xa7408dae, 0x7a24bde8, 0x5115a2ea, 0xbbe62e57, 0xf6d57fff,
    0x632a837a, 0x13861d77, 0xe19f2e7c, 0x695f5705, 0x87936b2e,
    0x50a19a6e, 0x728b0e94, 0xc5cc55ae, 0xb10a8ab1, 0x856f72d7,
    0xd0225c17, 0x51c4fda3, 0x89ed9861, 0xf1db829f, 0xbcfbc59d,
    0x83eec189, 0x6359b159, 0xcc505c30, 0x9cbc5ac9, 0x2fe230f9,
    0x39f65e42, 0x75157bd2, 0x40c158fb, 0x27eb9a3e, 0xc582a2d9,
    0x0569d6c2, 0xed8e30b3, 0x1083ddd2, 0x1f1da441, 0x5660e215,
    0x04f32fc5, 0xe18eef99, 0x4a593208, 0x5b7bed4c, 0x8102fc40,
    0x515341d9, 0xacff3dfa, 0x6d096cb5, 0x2bb3cc1d, 0x253d15ff
};

static int _random_j = 23, _random_k = 54;

int rand()
{
/* See Knuth vol 2 section 3.2.2 for a discussion of this random
   number generator.
*/
    unsigned int temp;
    temp = (_random_number_seed[_random_k] += _random_number_seed[_random_j]);
    if (--_random_j == 0) _random_j = 54, --_random_k;
    else if (--_random_k == 0) _random_k = 54;
    return (temp & 0x7fffffff);         /* result is a 31-bit value */
    /* It seems that it would not be possible, under ANSI rules, to */
    /* implement this as a 32-bit value. What a shame!              */
}

void srand(unsigned int seed)
{
/* This only allows you to put 32 bits of seed into the random sequence,
   but it is very improbable that you have any good source of randomness
   that good to start with anyway! A linear congruential generator
   started from the seed is used to expand from 32 to 32*55 bits.
*/
    int i;
    _random_j = 23;
    _random_k = 54;
    for (i = 0; i<55; i++)
    {   _random_number_seed[i] = seed + (seed >> 16);
/* This is not even a good way of setting the initial values.  For instance */
/* a better scheme would have r<n+1> = 7^4*r<n> mod (3^31-1).  Still I will */
/* leave this for now.                                                      */
        seed = 69069*seed + 1725307361;  /* computed modulo 2^32 */
    }
}

/* free, malloc, realloc etc are in the file alloc.c                     */

#define EXIT_LIMIT 33

typedef void (*vprocp)(void);
static union { vprocp p; int i; } _exitvector[EXIT_LIMIT] = {};
       /* initialised so not in bss (or shared library trouble) */
static struct {
    char number_of_exit_functions;
Richard Manby's avatar
Richard Manby committed
106
    char alloc_finalised, io_finalised, getenv_finalised;
Neil Turton's avatar
Neil Turton committed
107 108 109 110 111 112 113 114 115 116 117 118 119
} exit_s;

void _exit_init()
{
    if (_kernel_client_is_module()) {
        /* leave SWI mode exit handlers in place. number_of_exit_functions
           is guaranteed reasonable */
        while (exit_s.number_of_exit_functions != 0)
            if (_exitvector[--exit_s.number_of_exit_functions].i & 3) {
                ++exit_s.number_of_exit_functions; break;
            }
    } else
        exit_s.number_of_exit_functions = 0;
Richard Manby's avatar
Richard Manby committed
120
    exit_s.alloc_finalised = 0; exit_s.io_finalised = 0; exit_s.getenv_finalised = 0;
Neil Turton's avatar
Neil Turton committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
}

int atexit(vprocp func)
{
    if (exit_s.number_of_exit_functions >= EXIT_LIMIT) return 1;    /* failure */
    _exitvector[exit_s.number_of_exit_functions++].i =
        (int) func + _kernel_processor_mode();
    return 0;                                                /* success */
}

void _lib_shutdown()
{
    int mode = _kernel_processor_mode();
    while (exit_s.number_of_exit_functions!=0) {
        vprocp fn = _exitvector[--exit_s.number_of_exit_functions].p;
        if (((int) fn) & 3 != mode) { ++exit_s.number_of_exit_functions; break; };
        _call_client_0(fn);
    }
    /* ensure no recursion if finalisation fails */
Richard Manby's avatar
Richard Manby committed
140
    if (!exit_s.getenv_finalised) { exit_s.getenv_finalised = 1; _terminate_getenv(); }
Neil Turton's avatar
Neil Turton committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
    if (!exit_s.alloc_finalised) { exit_s.alloc_finalised = 1; _terminate_user_alloc(); }
    if (!exit_s.io_finalised) { exit_s.io_finalised = 1; _terminateio(); }
}


void exit(int n)
{
/* No longer calls _lib_shutdown: that is done as C finalisation called
   from _kernel_exit.
 */
    _exit(n);
}

void abort()
{
    raise(SIGABRT);
    exit(1);
}

int abs(int x)
{
    if (x<0) return (-x);
    else return x;
}

long int labs(long int x)
{
    if (x<0) return (-x);
    else return x;
}

div_t div(int numer, int denom)
{
/* This is a candidate for re-implementation in machine code so that the */
/* quotient and remainder can be computed all at once. However I am not  */
/* really convinced about the importance of the function so will not do  */
/* that yet!                                                             */
    div_t res;
    res.quot = numer / denom;
    res.rem  = numer % denom;
    return res;
}

ldiv_t ldiv(long int numer, long int denom)
{
    ldiv_t res;
    res.quot = numer / denom;
    res.rem  = numer % denom;
    return res;
}


/* end of stdlib.c */