/* leads.c */
/* author: Edward A. Green */
/* purpose: to generate a list of basic block leaders. */

#include "proj3.h"


/*********************************************/
/* ROUTINES TO MAKE THE LIST OF LEADER LINES */
/*********************************************/

/* FIND THE BLOCK HEADERS FROM THE LABEL LIST.  MAKE A LIST OF THEM */
LEADS  *make_lead_list(LEADS *lead, LABELS *label_list)
{
	LABELS *x, *y;  /* 2 pointer vectors to labels list: */
			/* to do both cond. and uncond. gotos, */
			/* and labels. */
	LEADS  *add_lead(LEADS *lead, int line);

	lead=add_lead(lead, 1);  /* i) the first statement is a leader */
	x=label_list;
	while (x!=NULL)
	  {
	  if ((x->field=='C') || (x->field=='U'))
	    {
	    /* ADD A SENTINAL RECORD */
	    if (strcmp(x->label,"_exit")) add_lead(lead, x->line+1);
	    y=label_list;
	    while (y!=NULL)
	      {
	      /* BRANCH DESTINATIONS ARE HEADERS */
	      if (y->field=='L' && !strcmp(y->label,x->label))
		add_lead(lead, y->line);
	      y=y->next;
	      }
	    }
	  /* 1ST LINE OF THE PROGRAM IS A HEADER */
	  else if (!strcmp(x->label,"_start"))
	    add_lead(lead, x->line);
	  x=x->next;
	  }
	return(lead);
}


/* ADD A BLOCK HEADER RECORD TO THE LEADER LIST */
LEADS *add_lead(LEADS *lead, int line)
{
	LEADS *index;
	LEADS *index2;
	LEADS *holder;
	LEADS  *new_lead(int lead);

	if (lead==NULL)
	  {
	  lead=new_lead(line);
	  return(lead);
	  }

	if (line < lead->line)
	  {
	  holder=new_lead(line);
	  holder->next=lead;
	  lead=holder;
	  return(lead);
	  }

	index2=lead->next;
	index=lead;
	while (index2!=NULL)
	  {
	  if (index2->line>line) index2=NULL;
	  else
	    {
	    index=index2;
	    index2=index2->next;
	    }
	  }

	if (index->line==line) return(lead);

	holder=new_lead(line);
	holder->next=index->next;
	index->next=holder;

	return(lead);
}


/* ALLOCATE SPACE FOR A NEW HEADER RECORD */
LEADS *new_lead(int line)
{
	LEADS *holder;

	if (NULL==(holder=(LEADS *)malloc(sizeof(holder))))
	  {
	  printf("Problems allocating memory in make_lead...\n");
	  exit(1);
	  }

	holder->line=line;
	holder->next=NULL;
	return(holder);
}


/************************************************************************/
/* Routines to retrieve information from the LEAD and LABELS structures */
/************************************************************************/
/* GIVEN A LINE NUMBER, RETURN THE BLOCK NUMBER */
int block_num(LEADS *lead, int line)
{
	int i;
	LEADS *test;

	i=0;
	test=lead;
	while (test!=NULL)
	  {
	  if (line<test->line) return(i-1);
	  test=test->next;
	  i++;
	  }
	return(i-1);
}

