static char *SccsId = "@(#)extr_prof.c 4.1 (TU-Delft) 05/24/90";
/**********************************************************

Name/Version      : NBOOL/4.1

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)	  : T.G.R. van Leuken, J.T. Fokkema
Creation date	  : 15-Jun-1982
Modified by       : S. de Graaf
Modification date : 09-Dec-1985


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1984 , All rights reserved
**********************************************************/
#include "nbool.h"

extr_profile (sr_pos)
int     sr_pos;			/* x_position of the sr	 */
{

    struct sr_field *c_sr;	/* ptr to the current sr */

/* this function examines the state_ruler and determines */
/* according to the difference in the mask_past and	 */
/* mask_fut layers which edges must be added to the	 */
/* bolean files.					 */

    c_sr = h_sr -> next;
    while (c_sr != h_sr -> prev) {
	if ((c_sr -> mask_fut != c_sr -> mask_past) ||
		(c_sr -> p_chg_ct != NULL)) {
	    buff_edge (c_sr, sr_pos);
	}
	c_sr = c_sr -> next;
    }
}

buff_edge (c_sr, sr_pos)
struct sr_field *c_sr;		/* ptr to the current sr */
int     sr_pos;			/* state_ruler position  */
{

/* this function determines in which bolean file the	 */
/* edge must be placed and if it concerns a start, stop	 */
/*  or change_edge. It uses two subroutines: add_edge	 */
/* to add a new edge to the buffers of a file and	 */
/* update_edge to update an edge in the file buffers in	 */
/* the case of adjecent edges.				 */

    int     pres_flag;		/* form status in sr_field */
    unsigned int    mask_past;	/* sr_layers of the past */
    unsigned int    mask_fut;	/* sr_layers of the fut. */
    struct min_term *mt_pntr;	/* current min_term ptr	 */
    struct form *frm_pntr;	/* current form pointer	 */
    char    edge_type;		/* edge_type to insert	 */
    int     chk_type;		/* check_type of new edge */
    int     chk_type_old;	/* previous check_type	 */

    mask_past = c_sr -> mask_past;
    mask_fut = c_sr -> mask_fut;
    frm_pntr = fp_head;
    while (frm_pntr != NULL) {
	pres_flag = 0;
	if ((((mask_past ^ mask_fut) | c_sr -> ov_mask) &
		    frm_pntr -> vuln_mask) == 0) {
	    frm_pntr = frm_pntr -> next;
	    continue;
	}
	mt_pntr = frm_pntr -> mt_pntr;
	while (mt_pntr != NULL) {
	    if (((mask_past & mt_pntr -> mask) == mt_pntr -> mask) &&
		    ((~mask_past & mt_pntr -> not_mask) ==
			mt_pntr -> not_mask)) {
		pres_flag = pres_flag | PAST_PRESENT;
		if (c_sr -> chk_type != DIFF_CT)
		    chk_type = c_sr -> chk_type;
		else
		    chk_type = det_chktype (c_sr, mt_pntr -> mask);
		if ((c_sr -> p_chg_ct != NULL) &&
			((c_sr -> ov_mask & mt_pntr -> mask) != 0))
		    chk_type_old = det_old_ct (c_sr, mt_pntr -> mask);
		else
		    chk_type_old = chk_type;
		break;
	    }
	    mt_pntr = mt_pntr -> next;
	}
	mt_pntr = frm_pntr -> mt_pntr;
	while (mt_pntr != NULL) {
	    if (((mask_fut & mt_pntr -> mask) == mt_pntr -> mask) &&
		    ((~mask_fut & mt_pntr -> not_mask) ==
			mt_pntr -> not_mask)) {
		pres_flag = pres_flag | FUT_PRESENT;
		if (c_sr -> chk_type != DIFF_CT)
		    chk_type = c_sr -> chk_type;
		else
		    chk_type = det_chktype (c_sr, mt_pntr -> mask);
		if ((c_sr -> p_chg_ct != NULL) &&
			((c_sr -> ov_mask & mt_pntr -> mask) != 0))
		    chk_type_old = det_old_ct (c_sr, mt_pntr -> mask);
		else
		    chk_type_old = chk_type;
		break;
	    }
	    mt_pntr = mt_pntr -> next;
	}
	switch (pres_flag) {
	    case NOT_PRESENT: 
		edge_type = '@';
		break;
	    case PAST_PRESENT: 
		if (chk_type_old == chk_type)
		    edge_type = 'B';
		else
		    edge_type = 'F';
		break;
	    case FUT_PRESENT: 
		if (chk_type_old == chk_type)
		    edge_type = 'A';
		else
		    edge_type = 'E';
		break;
	    case PRESENT: 
		if (chk_type_old == chk_type)
		    edge_type = '@';
		else
		    edge_type = 'D';
		break;
	    default: 
		break;
	}
	if (edge_type != '@') {
	    if ((frm_pntr -> curr_place != -1) &&
		    (edge_type ==
			frm_pntr -> b_pntr[frm_pntr -> curr_place] -> edge) &&
		    (chk_type ==
			frm_pntr -> b_pntr[frm_pntr -> curr_place] -> ct) &&
		    (c_sr -> yb ==
			frm_pntr -> b_pntr[frm_pntr -> curr_place] -> yt) &&
		    (sr_pos == frm_pntr -> b_pntr[frm_pntr -> curr_place] -> x))
		update_edge (c_sr, frm_pntr);
	    else
		add_edge (c_sr, frm_pntr, edge_type, chk_type, sr_pos);
	}
	frm_pntr = frm_pntr -> next;
    }
}

update_edge (c_sr, frm_pntr)
struct sr_field *c_sr;		/* pointer to current sr */
struct form *frm_pntr;		/* current form	pointer	 */
{

/* this function updates an edge in the buffer of the	 */
/* bolean files in the case of adjecent edge segments.	 */

    struct min_term *mt_pntr;	/* current min_term ptr	 */

    b_pntr = frm_pntr -> b_pntr[frm_pntr -> curr_place];

/* The top_value of the edge and the type of connection	 */
/* of the upperside of the edge are updated.		 */

    b_pntr -> yt = c_sr -> yt;
    mt_pntr = frm_pntr -> mt_pntr;
    while (mt_pntr != NULL) {
	if (((c_sr -> next -> mask_fut & mt_pntr -> mask) ==
		    mt_pntr -> mask) &&
		((~c_sr -> next -> mask_fut & mt_pntr -> not_mask) ==
		    mt_pntr -> not_mask)) {
	    b_pntr -> conn = b_pntr -> conn | 'B';
	    break;
	}
	mt_pntr = mt_pntr -> next;
    }
    if (mt_pntr == NULL) {
	b_pntr -> conn = b_pntr -> conn & ~('B' - '@');
    }
}

add_edge (c_sr, frm_pntr, edge_type, chk_type, sr_pos)
struct sr_field *c_sr;		/* pointer to current sr */
struct form *frm_pntr;		/* current form pointer	 */
char    edge_type;		/* type of the edge	 */
int     chk_type;		/* check_type of the edge */
int     sr_pos;			/* current sr position	 */
{

/* this function adds an edge to the buffers of a	 */
/* bolean file.						 */

    struct min_term *mt_pntr;	/* current min_term ptr	 */

    frm_pntr -> curr_place++;
    if (frm_pntr -> curr_place >= BUFLEN) {
	write_buf (frm_pntr, BUFLEN - 1);
	frm_pntr -> curr_place = 0;
    }
    b_pntr = frm_pntr -> b_pntr[frm_pntr -> curr_place];
    b_pntr -> x = sr_pos;
    b_pntr -> yb = c_sr -> yb;
    b_pntr -> yt = c_sr -> yt;
    b_pntr -> grp = NULL;
    b_pntr -> conn = '@';
    mt_pntr = frm_pntr -> mt_pntr;
    while (mt_pntr != NULL) {
	if (((c_sr -> prev -> mask_fut & mt_pntr -> mask) ==
		    mt_pntr -> mask) &&
		((~c_sr -> prev -> mask_fut & mt_pntr -> not_mask) ==
		    mt_pntr -> not_mask)) {
	    b_pntr -> conn = b_pntr -> conn | 'A';
	    break;
	}
	mt_pntr = mt_pntr -> next;
    }
    mt_pntr = frm_pntr -> mt_pntr;
    while (mt_pntr != NULL) {
	if (((c_sr -> next -> mask_fut & mt_pntr -> mask) ==
		    mt_pntr -> mask) &&
		((~c_sr -> next -> mask_fut & mt_pntr -> not_mask) ==
		    mt_pntr -> not_mask)) {
	    b_pntr -> conn = b_pntr -> conn | 'B';
	    break;
	}
	mt_pntr = mt_pntr -> next;
    }
    b_pntr -> ct = chk_type;
    b_pntr -> edge = edge_type;
}

write_buf (frm_pntr, nbr)
struct form *frm_pntr;		/* current form pointer	 */
int     nbr;			/* last buffer to write	 */
{
/* this function adds the contents of the buffers up	 */
/* till nbr to a temporarily file in a binairy form.	 */
/* filename: TEMP_ONE.					 */
/* the variable frm_pntr->curr_place is set to -1 to	 */
/* indicate that the buffers belonging to the file are	 */
/* empty again.						 */

    int     i;			/* loop variable	 */
    FILE   *f_out;		/* file pointer		 */

    sprintf (fr_name, TEMP_ONE, frm_pntr -> f_nbr, pid);
    OPEN (f_out, fr_name, "a");
    for (i = 0; i <= nbr; i++) {
	b_pntr = frm_pntr -> b_pntr[i];
	fwrite ((char *) b_pntr, sizeof (*b_pntr), 1, f_out);
    }
    frm_pntr -> curr_place = -1;
    CLOSE (f_out);
}

det_chktype (c_sr, mask)
struct sr_field *c_sr;		/* current sr position	 */
unsigned int    mask;		/* layers to treat	 */
{
/* This procedure determines the checktype of the layers */
/* given in mask in the sr_field given by c_sr and	 */
/* returns its value.					 */
/* If the checktypes are different zero is returned.	 */

    int     i;			/* loop variable	 */
    int     chk_type;		/* checktype returned	 */

    chk_type = INITIAL;
    for (i = 0; i < nomasks; i++) {
	if ((edges[i].mask & mask) != 0) {
	    if (chk_type == INITIAL)
		chk_type = c_sr -> p_chk -> chk_arr[i];
	    else
		if (c_sr -> p_chk -> chk_arr[i] != chk_type)
		    return (0);
	}
    }
    return (chk_type);
}

det_old_ct (c_sr, mask)
struct sr_field *c_sr;		/* current sr position	 */
unsigned int    mask;		/* layers to treat	 */
{
/* This procedure determines, if a change of checktype	 */
/* has taken place in one of the layers of mask, the old */
/* checktype and returns its value.			 */
/* If the checktypes of the layers in mask are different */
/* zero is returned.					 */

    int     i;			/* loop variable	 */
    int     chk_type_old;	/* checktype returned	 */
    struct checktype   *p_chg_ct;/* ptr to chged chk_types */

    chk_type_old = INITIAL;
    p_chg_ct = c_sr -> p_chg_ct;
    while (p_chg_ct != NULL) {
	if ((p_chg_ct -> mask & mask) != 0) {
	    if (chk_type_old == INITIAL)
		chk_type_old = p_chg_ct -> chk_type;
	    else
		if (p_chg_ct -> chk_type != chk_type_old)
		    return (0);
	}
	p_chg_ct = p_chg_ct -> next;
    }
    if (c_sr -> chk_type != DIFF_CT) {
	if (c_sr -> chk_type != chk_type_old)
	    return (0);
    }
    else {
	mask = mask & c_sr -> ov_mask;
	for (i = 0; i < nomasks; i++) {
	    if ((edges[i].mask & mask) != 0) {
		if (c_sr -> p_chk -> chk_arr[i] != chk_type_old)
		    return (0);
	    }
	}
    }
    return (chk_type_old);
}
