/* 
 *  @OPENGROUP_COPYRIGHT@
 *  COPYRIGHT NOTICE
 *  Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
 *  Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
 *  ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
 *  the full copyright text.
 *  
 *  This software is subject to an open license. It may only be
 *  used on, with or for operating systems which are themselves open
 *  source systems. You must contact The Open Group for a license
 *  allowing distribution and sublicensing of this software on, with,
 *  or for operating systems which are not Open Source programs.
 *  
 *  See http://www.opengroup.org/openmotif/license for full
 *  details of the license agreement. Any use, reproduction, or
 *  distribution of the program constitutes recipient's acceptance of
 *  this agreement.
 *  
 *  EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
 *  PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 *  WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
 *  OR FITNESS FOR A PARTICULAR PURPOSE
 *  
 *  EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
 *  NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE
 *  EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGES.
*/ 
/* 
 * HISTORY
*/ 
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$XConsortium: UilP2Reslv.c /main/11 1995/07/14 09:36:35 drk $"
#endif
#endif

/*
*  (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */

/*
**++
**  FACILITY:
**
**      User Interface Language Compiler (UIL)
**
**  ABSTRACT:
**
**      This module contain the second pass routines for resolving forward
**	references.
**
**--
**/


/*
**
**  INCLUDE FILES
**
**/

#include "UilDefI.h"


/*
**
**  DEFINE and MACRO DEFINITIONS
**
**/



/*
**
**  EXTERNAL VARIABLE DECLARATIONS
**
**/


/*
**
**  GLOBAL VARIABLE DECLARATIONS
**
**/



/*
**
**  OWN VARIABLE DECLARATIONS
**
**/


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function processes forward references from the first pass.
**
**  FORMAL PARAMETERS:
**
**      none
**
**  IMPLICIT INPUTS:
**
**      sym_az_forward_ref_chain
**	sym_az_val_forward_ref_chain
**
**  IMPLICIT OUTPUTS:
**
**      none
**
**  FUNCTION VALUE:
**
**      void
**
**  SIDE EFFECTS:
**
**      error messages may be issued for objects that are still undefined
**	or of the wrong type
**
**--
**/

void	sem_resolve_forward_refs()

{
    sym_forward_ref_entry_type		* fwd_entry;
    sym_forward_ref_entry_type		* next_fwd_entry;
    sym_val_forward_ref_entry_type	* fwd_val_entry;
    sym_val_forward_ref_entry_type	* next_fwd_val_entry;
    sym_widget_entry_type		** target_obj_entry;
    sym_value_entry_type		** target_val_entry;
    sym_parent_list_type        	* parent_node;
    sym_parent_list_type        	* parent_ptr;
    int                         	found;

    /* 
    **	Forward references are placed on a chain by the first pass of
    **	the compiler.  This routine walks the chain checking that
    **	    1) name is now defined
    **	    2) name points to the correct type of object
    */

    for (fwd_entry = sym_az_forward_ref_chain;  
	 fwd_entry != NULL;  
	 fwd_entry = next_fwd_entry)
    {
	sym_name_entry_type	* name_entry;
	sym_widget_entry_type	* object_entry;
	unsigned short int	object_type;


	/*
	**  Save the pointer to the next forward entry so we can free the current 
	**  entry after it is processed.
	*/
	next_fwd_entry = fwd_entry->az_next_ref;


	/*
	**  Call the Status callback routine to report our progress.
	*/
	/* %COMPLETE */
	Uil_percent_complete = 60;
	if (Uil_cmd_z_command.status_cb != (Uil_continue_type(*)())NULL)
	    diag_report_status();    


	object_type = fwd_entry->header.b_type;
	name_entry = fwd_entry->az_name;
	object_entry = (sym_widget_entry_type *) name_entry->az_object;

	if (object_entry == NULL)
	{
	    diag_issue_diagnostic
		( d_never_def,
		  _sar_source_pos2 (fwd_entry),
		  diag_object_text( object_type ),
		  name_entry->c_text );
	    continue;
	}

	/*
	** Make sure object references are to correct type of object.
	** A forward reference naming a widget class may be correctly
	** resolved by the corresponding gadget class, and vice versa.
	*/
	if ((object_entry->header.b_type!=object_type) &&
	    (uil_gadget_variants[object_entry->header.b_type]!=object_type) &&
	    (uil_gadget_variants[object_type]!=object_entry->header.b_type))
	    {
	    diag_issue_diagnostic
		(d_ctx_req,
		 _sar_source_pos2(fwd_entry),
		 diag_object_text(object_type),
		 diag_object_text(object_entry->header.b_type));
	    continue;
	    }

	target_obj_entry =
		(sym_widget_entry_type * *) fwd_entry->a_update_location;
	*target_obj_entry = object_entry;

	/*
	** Update objects on forward refernce chain so that their parent_lists point
	** to the objects which reference them
	*/
	if (fwd_entry -> parent != NULL)
	    {
	    found = FALSE;
	    for (parent_ptr = object_entry -> parent_list;
		((parent_ptr != NULL) && (found == FALSE));
		parent_ptr = parent_ptr -> next)
		{
		if (parent_ptr -> parent == fwd_entry -> parent)
		    found = TRUE;
		}
	    if (found == FALSE)
		{
		parent_node = (sym_parent_list_type *) 
		    sem_allocate_node (sym_k_parent_list_entry, 
		    sym_k_parent_list_size);
		parent_node -> next = object_entry -> parent_list;
		object_entry -> parent_list = parent_node;
		parent_node -> parent = fwd_entry -> parent;
		}
	    }


	/*
	**  Free the Forward reference entry now that it is no longer needed
	*/    
	sem_free_node(( sym_entry_type *)fwd_entry);

    }


    /*
    **  Now resolve the forward references to values
    **/

    /* 
    **	Forward references are placed on a chain by the first pass of
    **	the compiler.  This routine walks the chain checking that
    **	    1) name is now defined
    **	    2) name points to the correct type of value
    */

    for (fwd_val_entry = sym_az_val_forward_ref_chain;  
	 fwd_val_entry != NULL;  
	 fwd_val_entry = next_fwd_val_entry)
    {
	sym_name_entry_type	* name_entry;
	sym_value_entry_type	* value_entry;
	sym_obj_entry_type	* obj_entry;


	/*
	**  Save the pointer to the next forward entry so we can free the current 
	**  entry after it is processed.
	*/
	next_fwd_val_entry = fwd_val_entry->az_next_ref;


	/*
	**  Call the Status callback routine to report our progress.
	*/
	/* %COMPLETE */
	Uil_percent_complete = 60;
	if (Uil_cmd_z_command.status_cb != (Uil_continue_type(*)())NULL)
	    diag_report_status();    

	name_entry = fwd_val_entry->az_name;
	value_entry = (sym_value_entry_type *) name_entry->az_object;
	obj_entry = (sym_obj_entry_type *) name_entry->az_object;

	if (value_entry == NULL)
	{
	    diag_issue_diagnostic
		( d_never_def,
		  _sar_source_pos2 (fwd_val_entry),
		  "value",
		  name_entry->c_text );
	    continue;
	}

	switch (fwd_val_entry->fwd_ref_flags)
	    {
	    case (sym_k_patch_add):
	    case (sym_k_patch_list_add):
		{
    	        target_val_entry =
		        (sym_value_entry_type * *) fwd_val_entry->a_update_location;
	        *target_val_entry = value_entry;
	        break;
	        }
	    default:
		_assert(FALSE, "Illegal forward reference");
            }


	/*
	**  Free the Forward reference entry now that it is no longer needed
	*/    
	sem_free_node(( sym_entry_type *)fwd_val_entry);

    }




}
