Goto sanos source index

//
// stdlib.c
//
// Standard library functions
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 
// 1. Redistributions of source code must retain the above copyright 
//    notice, this list of conditions and the following disclaimer.  
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.  
// 3. Neither the name of the project nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
// SUCH DAMAGE.
// 

#include <os.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <inifile.h>

static long holdrand = 1L;

typedef void (__cdecl *proc_t)(void);

static proc_t *atexit_begin = NULL;
static proc_t *atexit_end = NULL;
static proc_t *atexit_last = NULL;

#pragma function(abs)
#pragma function(labs)

static int __parse_args(char *args, char **argv, int local)
{
  char *p;
  int argc;
  char *start;
  char *end;
  char *buf;
  int delim;
  int escapes;

  p = args;
  argc = 0;
  while (*p)
  {
    while (*p == ' ') p++;
    if (!*p) break;

    escapes = 0;
    if (*p == '"' || *p == '\'')
    {
      delim = *p++;
      start = p;
      while (*p && *p != delim) 
      {
        if (*p == '\\' && *(p + 1)) escapes++;
        p++;
      }
      end = p;
      if (*p == delim) p++;
    }
    else
    {
      start = p;
      while (*p && *p != ' ') p++;
      end = p;
    }

    if (argv)
    {
      if (local)
        buf = (char *) _lmalloc(end - start - escapes + 1);
      else
        buf = (char *) malloc(end - start - escapes + 1);

      if (!buf) break;

      if (escapes)
      {
        char *s = start;
        char *t = buf;
        while (s < end)
        {
          if (*s == '\\' && *(s + 1)) s++;
          *t++ = *s++;
        }
        *t = 0;
      }
      else
      {
        memcpy(buf, start, end - start);
        buf[end - start] = 0;
      }
        
      argv[argc] = buf;
    }
    
    argc++;
  }

  return argc;
}

int parse_args(char *args, char **argv)
{
  return __parse_args(args, argv, 0);
}

int _lparse_args(char *args, char **argv)
{
  return __parse_args(args, argv, 1);
}

void free_args(int argc, char **argv)
{
  int i;

  for (i = 0; i < argc; i++) free(argv[i]);
  if (argv) free(argv);
}

void _lfree_args(int argc, char **argv)
{
  int i;

  for (i = 0; i < argc; i++) _lfree(argv[i]);
  if (argv) _lfree(argv);
}

int atexit(proc_t exitfunc)
{
  if (atexit_end == atexit_last)
  {
    int size = atexit_end - atexit_begin;
    int newsize = size + 32;
    atexit_begin = (proc_t *) realloc(atexit_begin, newsize * sizeof(proc_t));
    if (atexit_begin == NULL) return -ENOMEM;
    atexit_end = atexit_begin + size;
    atexit_last = atexit_begin + newsize;
  }

  *atexit_end++ = exitfunc;
  return 0;
}

void run_atexit_handlers()
{
  if (atexit_begin)
  {
    while (--atexit_end >= atexit_begin) if (*atexit_end != NULL) (**atexit_end)();
    free(atexit_begin);
    atexit_begin = atexit_end = atexit_last = NULL;
  }
}

void abort()
{
  raise(SIGABRT);
#ifdef __GNUC__
  while (1);
#endif
}

int abs(int number)
{
  return number >= 0 ? number : -number;
}

div_t div(int numer, int denom)
{
  div_t result;

  result.quot = numer / denom;
  result.rem  = numer - (result.quot * denom);

  if (numer < 0 && result.rem > 0) 
  {
    result.quot++;
    result.rem -= denom;
  }

  return result;
}

long labs(long n)
{
  return  n >= 0L ? n : -n;
}

ldiv_t ldiv(long numer, long denom)
{
  ldiv_t result;

  result.quot = numer / denom;
  result.rem = numer % denom;

  if (numer < 0 && result.rem > 0) 
  {
    result.quot++;
    result.rem -= denom;
  }

  return result;
}

void srand(unsigned int seed)
{
  holdrand = (long) seed;
}

int rand()
{
  return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}

int system(const char *command)
{
  return spawn(P_WAIT, NULL, command, NULL, NULL);
}

char *realpath(const char *path, char *buffer)
{
  int rc;

  rc = canonicalize(path, buffer, MAXPATH);
  if (rc < 0) return NULL;
  return buffer;
}

int getrusage(int who, struct rusage *usage)
{
  // TODO implement
  errno = ENOSYS;
  return -1;
}