/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "Licence").
 * You may not use this file except in compliance with the Licence.
 *
 * You can obtain a copy of the licence at RISC OS path @.^.LICENCE
 * or  http://www.riscosdev.com/lanman98/LICENCE.CDDL
 * See the Licence for the specific language governing permissions
 * and limitations under the Licence.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the Licence file. If applicable, add the
 * following below this CDDL HEADER, with the fields enclosed by
 * brackets "[]" replaced with your own identifying information:
 * Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
 
/*
 *   Copyright 1996 Warm Silence Software Ltd.  All rights reserved.
 *   Use is subject to license terms.
 */

/*   PHBG 8/1/97: Initial version
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "kernel.h"
#include "swis.h"
#include "error.h"
#include "memory.h"

static _kernel_oserror error = {0x10000, "Hello"};
static int fatal;

static void report_error(void)
{
    printf("Uncaught exception\n");
    ((void (*)(void)) 0)(); /* Branch through 0 */
}

void Error(char *fmt, ...)
{
    va_list args;

    error.errnum = 0x10000;
    va_start(args, fmt);
    vsprintf(error.errmess, fmt, args);
    va_end(args);
    fatal = 0;
    if(ExceptXXXStack)
        LongJmp(ExceptXXXStack->label);
    else
        report_error();
}

void ErrorDirect(char *fmt, ...)
{
    va_list args;

    error.errnum = 0x10000;
    va_start(args, fmt);
    vsprintf(error.errmess, fmt, args);
    va_end(args);
    fatal = 0;
    report_error();
}

void ErrorFatal(char *fmt, ...)
{
    va_list args;

    error.errnum = 0x10000;
    va_start(args, fmt);
    vsprintf(error.errmess, fmt, args);
    va_end(args);
    fatal = 1;
    if(ExceptXXXStack)
        LongJmp(ExceptXXXStack->label);
    else
        report_error();
}

void ErrorErr(_kernel_oserror *err)
{
    if(err)
    {
        error = *err;
        fatal = 0;
        if(ExceptXXXStack)
            LongJmp(ExceptXXXStack->label);
        else
            report_error();
    }
}

void ErrorNum(int err, char *s)
{
    error.errnum = err;
    strcpy(error.errmess, s);
    fatal = 0;
    if(ExceptXXXStack)
        LongJmp(ExceptXXXStack->label);
    else
        report_error();
}

_kernel_oserror *ExceptCaught(void)
{
    return &error;
}

void ExceptRethrow(void)
{
    ErrorErr(ExceptCaught());
}


exception_stack_t ExceptXXXStack = NULL;

exception_stack_t ExceptGetStack(void)
{
    return ExceptXXXStack;
}

void ExceptSetStack(exception_stack_t s)
{
    ExceptXXXStack = s;
}

void ExceptXXXPush(void)
{
    exception_stack_t new_ex;

    new_ex = Malloc0(sizeof(*new_ex));
    if(new_ex)
    {
        new_ex->link = ExceptXXXStack;
        /* Survives being interupted here. */
        ExceptXXXStack = new_ex;
    }
}

int ExceptXXXPop(void)
{
    exception_stack_t old;
    int failed;

    failed = 0;
    old = ExceptXXXStack;
    if(old)
    {
        failed = old->failed;
        ExceptXXXStack = old->link;
        Free(old);
    }
    return failed;
}

void ExceptVarXXX(void * dummy)
{
}
