/*-------------------------------------------------------------------------*/
/* GNU Prolog                                                              */
/*                                                                         */
/* Part  : Prolog engine                                                   */
/* File  : obj_chain.c                                                     */
/* Descr.: object chaining management                                      */
/* Author: Daniel Diaz                                                     */
/*                                                                         */
/* Copyright (C) 1999 Daniel Diaz                                          */
/*                                                                         */
/* GNU Prolog is free software; you can redistribute it and/or modify it   */
/* under the terms of the GNU General Public License as published by the   */
/* Free Software Foundation; either version 2, or any later version.       */
/*                                                                         */
/* GNU Prolog is distributed in the hope that it will be useful, but       */
/* WITHOUT ANY WARRANTY; without even the implied warranty of              */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU        */
/* General Public License for more details.                                */
/*                                                                         */
/* You should have received a copy of the GNU General Public License along */
/* with this program; if not, write to the Free Software Foundation, Inc.  */
/* 59 Temple Place - Suite 330, Boston, MA 02111, USA.                     */
/*-------------------------------------------------------------------------*/
#include <stdio.h>

#include "obj_chain.h"
#include "pl_params.h"
#include "../EnginePl/config.h"

#define DBGPRINTF printf

#if 0
#define DEBUG
#endif


void Fatal_Error(char *format,...);




/*---------------------------------*/
/* Constants                       */
/*---------------------------------*/

/*---------------------------------*/
/* Type Definitions                */
/*---------------------------------*/

typedef struct
    {
     void (*fct_exec_system)();
     void (*fct_exec_user)();
    }ObjInf;


/*---------------------------------*/
/* Global Variables                */
/*---------------------------------*/

extern ObjChain  obj_chain_begin;
extern ObjChain *obj_chain_end;

static ObjInf    obj_tbl[MAX_OBJECT];
static int       nb_obj;




/*---------------------------------*/
/* Function Prototypes             */
/*---------------------------------*/

/*-------------------------------------------------------------------------*/
/* FIND_LINKED_OBJECTS                                                     */
/*                                                                         */
/*-------------------------------------------------------------------------*/
void Find_Linked_Objects(void)

{
 ObjChain *p,**q;
 int       i;

 nb_obj=0;

#ifdef DEBUG
 DBGPRINTF("ObjChain: chain begin: %#x\n",(unsigned) &obj_chain_begin);
 DBGPRINTF("ObjChain: chain end  : %#x\n",(unsigned) &obj_chain_end);
#endif

 if (obj_chain_begin.next!=&obj_chain_end || obj_chain_end!=&obj_chain_begin)
     Fatal_Error("obj_chain: executable file corrupted");

 p=&obj_chain_begin+1;
 while(p<(ObjChain *) &obj_chain_end)
    {
     if (p->magic1!=OBJ_CHAIN_MAGIC_1 || p->magic2!=OBJ_CHAIN_MAGIC_2 || 
         (q=p->next)<(ObjChain **) &obj_chain_begin || 
         q>&obj_chain_end || *q!=p)
        {
#if MSDOS
         p=(ObjChain *)((char *) p+1);
#else
         p=(ObjChain *)((long *) p+1);
#endif

#ifdef DEBUG
         DBGPRINTF(".");
#endif
         continue;
        }

#ifdef DEBUG
     DBGPRINTF("\n*** Obj Found  start: %#x  end: %#x  Initializer: %#x\n",
            (unsigned) p,(unsigned) q,(unsigned) (p->fct_init));
#endif
     (*p->fct_init)();
#ifdef M_powerpc_linux
     p=(ObjChain *) ((long *) p+1);
#else
     p=(ObjChain *) (q+1);
#endif
    }

 i=nb_obj;                /* call Exec System functions from last to first */
 while(--i>=0)
    {
#ifdef DEBUG
     DBGPRINTF("\n+++ Executing Exec System Function at: %#lx\n",
               (long) (obj_tbl[i].fct_exec_system));
#endif
     (*(obj_tbl[i].fct_exec_system))();
    }

 i=nb_obj;                  /* call Exec User functions from last to first */
 while(--i>=0)
    {
#ifdef DEBUG
     DBGPRINTF("\n+++ Executing Exec User Function at: %#lx\n",
               (long) (obj_tbl[i].fct_exec_user));
#endif
     (*(obj_tbl[i].fct_exec_user))();
    }
}




/*-------------------------------------------------------------------------*/
/* NEW_OBJECT                                                              */
/*                                                                         */
/* Called by compiled prolog code.                                         */
/*-------------------------------------------------------------------------*/
void New_Object(void (*fct_exec_system)(),void (*fct_exec_user)())

{
 obj_tbl[nb_obj].fct_exec_system=fct_exec_system;
 obj_tbl[nb_obj].fct_exec_user  =fct_exec_user;
 nb_obj++;
}
