/* %Z%%M% %I% %E% */

/*
 * Copyright (c) 1991-2004 by Wayne C. Gramlich.
 * All rights reserved.
 */

/*
 * This file implements the status base type:
 */

#ifndef STHEADERS_H
#include "stheaders.h"
#endif

#ifndef STRING_H
#include "string.h"
#endif

#ifndef MEMORY_H
#include "memory.h"
#endif

#ifndef UNIX_ASSERT_H
#include "unix_assert.h"
#endif

#ifndef UNIX_SETJMP_H
#include "unix_setjmp.h"
#endif

typedef jmp_buf *Long_jump;
typedef struct {
    void (*routine)(void);
    void *param;
} *Call_through;

extern module___object long_jump__module__object;

Long_jump long_jump___initial = (Long_jump)0;

extern void long_jump__external__initialize(void);
extern unsigned long_jump__address_get(Long_jump);
extern Long_jump long_jump__allocate(void);
extern String long_jump__assert_file_name_replace(String);
extern unsigned long_jump__assert_is_empty(void);
extern unsigned long_jump__assert_line_number_replace(unsigned);
extern Long_jump long_jump__assert_long_jump_replace(Long_jump);
extern void long_jump__jump(Long_jump, unsigned);
extern unsigned long_jump__set(Long_jump);

static object___object long_jump_initial_object = {
	"",				/* Package name */
	"long_jump",			/* Type name */
	"??",				/* Object name */
	(type___reference *)0,		/* Type reference */
	(int *)0,			/* Pointer to long_jump size */
	0,				/* Static needs count */
	(need___entry *)0,		/* Static needs */
	5,				/* Parameter needs count */
	(need___entry *)0,		/* Parameter needs */
	(void **)&long_jump___initial,	/* Object pointer */
	(instantiation___object *)0	/* Instantiation list */
};
static object___object *object_list[1] = {
	&long_jump_initial_object,
};

void
long_jump__external__initialize(void)
{
    long_jump__module__object.object_count = 1;
    long_jump__module__object.objects = object_list;
}

/*
 * long_jump__address_get(long_jump)
 *	This routine will return the address of {long_jump}.
 */
unsigned
long_jump__address_get(
    Long_jump long_jump)
{
    return (unsigned)long_jump;
}

/*
 * long_jump__allocate()
 *	This routine will allocate and return a new {Long_jump} object.
 */
Long_jump
long_jump__allocate(void)
{
    Long_jump		long_jump;

    long_jump = memory_alloc(Long_jump);
    return long_jump;
}

/*
 * long_jump__jump(long_jump, value)
 *	This routine will cause longjmp() will attempt to transfer
 *	program control to the context stored in {long_jump} with
 *	a return value of {value}.  If this procedure returns,
 *	the long jump failed to occur.
 */
void
long_jump__jump(
    Long_jump long_jump,
    unsigned value)
{
    /* (void)fprintf(stderr,
      "=>jump@long_jump(0x%x, %d)\n", long_jump, value); */
    longjmp(*long_jump, value);
    /* (void)fprintf(stderr,
      "<=jump@long_jump(0x%x, %d)\n", long_jump, value); */
}


/*
 * long_jump__setup(long_jump, normal, failure)
 *	This procedure will store procedure context information into
 *	{long_jump} and then invoke the {normal} procedure.  If some
 *	time during the execution of the {normal} procedure, a call
 *	to {jump}@({long_jump}) is performed, all execution of the
 *	code from {normal} down is brutally terminated with no chance
 *	to clean up and {failure} is invoked.  {true} is returned if
 *	{failure} is invoked and {false} if only {normal} is invoked.
 */
unsigned
long_jump__setup(
    Long_jump long_jump,
    Call_through normal,
    Call_through failure)
{
    /* (void)fprintf(stderr, "=>long_jump_setup(0x%x, *, *)\n", long_jump); */
    if (setjmp(*long_jump) == 0) {
	/* (void)fprintf(stderr, "=>normal()\n"); */
	normal->routine();
	/* (void)fprintf(stderr, "<=normal()\n"); */
	return 0;
    } else {
	/* (void)fprintf(stderr, "=>failure()\n"); */
	failure->routine();
	/* (void)fprintf(stderr, "<=failure()\n"); */
	return 1;
    }
}

