/*********************************************************************/
/*                  pC++/Sage++  Copyright (C) 1993                  */
/*  Indiana University  University of Oregon  University of Rennes   */
/*********************************************************************/

#define EXTEND_NODE 2  /* move this definition to h/ files. */
                       /* should agree with cftn.gram definition. */
/*
 * stat.c
 *
 * Routines for handling Fortran statements
 *
 */

#include "inc.h"
#include "defines.h"
#include "extern.h"
#ifdef SYS5
#include <string.h>
#else
#include <strings.h>
#endif

extern int parstate;
extern PTR_SYMB head_symb, global_list, star_symb;
extern PTR_BFND cur_bfnd, global_bfnd, pred_bfnd, cur_scope();
extern PTR_BFND last_bfnd; /*OMP*/
extern PTR_TYPE global_float, global_int, global_bool, global_default, vartype;
extern PTR_LABEL head_label;
extern PTR_LABEL thislabel;
extern PTR_TYPE impltype[];
extern PTR_BLOB head_blob, cur_blob;
extern PTR_CMNT comments;
extern int yylineno;
extern int mod_offset;
extern int nioctl;
extern int yydebug;

void fatalstr();
void execerr();
int chk_params();
void err();
void setimpl();

PTR_BFND get_bfnd();
PTR_LLND make_llnd();
PTR_SYMB make_symb();
PTR_BLOB make_blob();
PTR_LABEL make_label();
PTR_SYMB install_entry();
PTR_SYMB get_proc_symbol();
PTR_HASH correct_symtab();
int end_group = 0;

/* 
   The following two routines are used for reading in input/output
   control lists. 
*/

void
startioctl()
{

	inioctl = YES;
        nioctl = 0; 

}

void
endioctl()
{
	inioctl = NO;

}


/*
 * Follow a chain of blob nodes to get the last
 *
 * input:
 *	 blob - the list to be searched
 *
 * output:
 *	 pointer to the last node in the list
 */
PTR_BLOB
follow_blob(blob)
	PTR_BLOB blob;
{
	register PTR_BLOB next, last;

	for (next = last = blob; next; next = next->next)
		last = next;
	return (last);
}


/* 
 * make_if takes an expression to make an IF_NODE
 * Also allocates a collection point and points the false branch
 * to the collection point
 */
PTR_BFND
make_if(expr)
	PTR_LLND expr;
{
	PTR_BFND p;
	void set_blobs(), make_prog_header();
	void err();

	/*
        if (pred_bfnd->variant == GLOBAL)
	  make_prog_header();
	*/
	
	/*	if (expr->type->variant != T_BOOL) {
		err("Non-logical expression in IF statement", 28);
		expr = LLNULL;
	}
        */ /*06.06.03*/ 
	p = get_bfnd(fi,IF_NODE, SMNULL, expr, LLNULL, LLNULL);
/*	set_blobs(p, pred_bfnd, NEW_GROUP1); */
	return (p);
}


PTR_BFND
make_forall(lexpr,expr)
	PTR_LLND expr,lexpr;
{
	PTR_BFND p;
	void set_blobs(), make_prog_header();
	void err();

	/*
        if (pred_bfnd->variant == GLOBAL)
	  make_prog_header();
	*/
	/*	if (expr && expr->type->variant != T_BOOL) {
		err("Non-logical expression in FORALL statement", 288);
		expr = LLNULL;
	}
         */ /*06.06.03*/ 
	p = get_bfnd(fi,FORALL_NODE, SMNULL, lexpr, expr, LLNULL);
/*	set_blobs(p, pred_bfnd, NEW_GROUP1); */
	return (p);
}

/*
 * make_elseif fixes the control frame to reflect the current paring state
 */

void
make_elseif(expr,s)
	PTR_LLND expr;
        PTR_SYMB s;  /*podd 3.02.03*/
{
	register PTR_BFND p = NULL;
	void execerr(), make_endblock();

	/*	if (expr->type->variant != T_BOOL) {
		err("Non-logical expression in IF statement", 28);
		expr = LLNULL;
	}
        */ /*06.06.03*/ 
	if (pred_bfnd->variant == IF_NODE || pred_bfnd->variant == ELSEIF_NODE)
		p = get_bfnd(fi,ELSEIF_NODE, s, expr, LLNULL, LLNULL);
	else
		err("ELSEIF out of place", 31);
	p->control_parent = pred_bfnd;
	pred_bfnd->entry.Template.bl_ptr2 = make_blob(fi,p, BLNULL);
	pred_bfnd = p;
	cur_blob = p->entry.Template.bl_ptr1 = make_blob(fi,BFNULL, BLNULL);
}

void
make_elsewhere_mask(expr,s)
	PTR_LLND expr;
        PTR_SYMB s;  /*podd 15.02.03*/
{
	register PTR_BFND p = NULL;
	void execerr(), make_endblock();

	/*if (expr->type->variant != T_BOOL) {
		err("Non-logical expression in IF statement", 28);
		expr = LLNULL;
		}*/
	if (pred_bfnd->variant == WHERE_BLOCK_STMT || pred_bfnd->variant == ELSEWH_NODE)
		p = get_bfnd(fi,ELSEWH_NODE, s, expr, LLNULL, LLNULL);
	else
		err("ELSEWHERE out of place", 291);
	p->control_parent = pred_bfnd;
	pred_bfnd->entry.Template.bl_ptr2 = make_blob(fi,p, BLNULL);
	pred_bfnd = p;
	cur_blob = p->entry.Template.bl_ptr1 = make_blob(fi,BFNULL, BLNULL);
}



/*
 * make_else fixes the control stack to reflect the current state of parsing
 * and put all BIF nodes after the saved control frame as the true branch of
 * the If statement
 */
void
make_else(s)
PTR_SYMB s;  /*podd 3.02.03*/
{
	void execerr(), set_blobs();
	PTR_BFND p;

	if (pred_bfnd->variant != IF_NODE && pred_bfnd->variant != ELSEIF_NODE)
	  err("ELSE out of place", 32);
	p = get_bfnd(fi,CONTROL_END, s, LLNULL, LLNULL, LLNULL);
        if (is_openmp_stmt) { /*OMP*/
            is_openmp_stmt = 0; /*OMP*/
            p -> decl_specs = BIT_OPENMP; /*OMP*/
        } /*OMP*/
	set_blobs(p, pred_bfnd, SAME_GROUP);
        cur_blob = pred_bfnd->entry.Template.bl_ptr2
	  = make_blob(fi,BFNULL, BLNULL);
}

void
make_elsewhere(s)
     PTR_SYMB s; /*15.02.03*/
{
	void execerr(), set_blobs();
	PTR_BFND p;

	if (pred_bfnd->variant != WHERE_BLOCK_STMT  && pred_bfnd->variant != ELSEWH_NODE)
	   err("ELSEWHERE out of place", 291 );
	p = get_bfnd(fi,CONTROL_END, s, LLNULL, LLNULL, LLNULL);
        if (is_openmp_stmt) { /*OMP*/
            is_openmp_stmt = 0; /*OMP*/
            p -> decl_specs = BIT_OPENMP; /*OMP*/
        } /*OMP*/
	set_blobs(p, pred_bfnd, SAME_GROUP);
        cur_blob = pred_bfnd->entry.Template.bl_ptr2
	  = make_blob(fi,BFNULL, BLNULL);
}


/*
 * make_endblock sets up the statement list to the proper branch according
 * to the control stack's status and then pop the control stack.
 */
void
make_endblock(p) 
PTR_BFND p;
{
	PTR_BFND past_pred;
	PTR_BLOB q;
	void set_blobs();

	if ((pred_bfnd==BFNULL) || (pred_bfnd->control_parent==BFNULL))
	   fatalstr("Illegal end of block",(char *)NULL,258);
	if (cur_blob->ref==BFNULL) { /* empty block body */
/*	  pred_bfnd->entry.Template.bl_ptr1 = BLNULL; */
	  cur_blob->ref = p;
        }
	else
	   if (p) set_blobs(p, pred_bfnd, SAME_GROUP);
	past_pred = pred_bfnd;
	pred_bfnd = pred_bfnd->control_parent;
	if (pred_bfnd->variant == GLOBAL) parstate = OUTSIDE;
	q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	cur_blob = (q && (q->ref == past_pred)) ?
	             q
		    :follow_blob(pred_bfnd->entry.Template.bl_ptr2);
}


void
make_endif(s) 
PTR_SYMB s;  /*podd 3.02.03*/
{      
	PTR_BFND p, past_pred;
	PTR_BLOB q;
	void set_blobs();

	if ((pred_bfnd==BFNULL) || (pred_bfnd->control_parent==BFNULL)
	     || ((pred_bfnd->variant != IF_NODE) &&
	        (pred_bfnd->variant != ELSEIF_NODE))) {
		fatalstr("Illegal END IF", (char *)NULL, 260);
	}
	if ((!cur_blob->ref) || (cur_blob->ref->variant != CONTROL_END)) {
	   p = get_bfnd(fi,CONTROL_END, s, LLNULL, LLNULL, LLNULL);
	   p = get_bfnd(fi,CONTROL_END, s, LLNULL, LLNULL, LLNULL);
           if (is_openmp_stmt) { /*OMP*/
              is_openmp_stmt = 0; /*OMP*/
              p -> decl_specs = BIT_OPENMP; /*OMP*/
           } /*OMP*/
           /*change by podd*/
	   if(thislabel){
              thislabel->statbody = p;
              thislabel->labtype = LABEXEC;
              p->label = thislabel;   
           }                   
	   set_blobs(p, pred_bfnd, SAME_GROUP);
	}
	while (pred_bfnd->variant == ELSEIF_NODE)
	  pred_bfnd = pred_bfnd->control_parent;
	past_pred = pred_bfnd;
	pred_bfnd = pred_bfnd->control_parent;
	q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	cur_blob = (q && (q->ref == past_pred)) ?
	             q
		    :follow_blob(pred_bfnd->entry.Template.bl_ptr2);
/*	cur_blob = follow_blob(pred_bfnd->entry.Template.bl_ptr1);*/
}

void
make_endwhere(s) 
     PTR_SYMB s;  /*15.02.03*/
{
	PTR_BFND p, past_pred;
	PTR_BLOB q;
	void set_blobs();

	if ((pred_bfnd==BFNULL) || (pred_bfnd->control_parent==BFNULL)
	     || ((pred_bfnd->variant != WHERE_BLOCK_STMT) &&
	        (pred_bfnd->variant != ELSEWH_NODE))) {
		fatalstr("Illegal ENDWHERE", (char *)NULL, 290);
	}
	if ((!cur_blob->ref) || (cur_blob->ref->variant != CONTROL_END)) {
	   p = get_bfnd(fi,CONTROL_END, s, LLNULL, LLNULL, LLNULL);
           if (is_openmp_stmt) { /*OMP*/
              is_openmp_stmt = 0; /*OMP*/
              p -> decl_specs = BIT_OPENMP; /*OMP*/
           } /*OMP*/
	   set_blobs(p, pred_bfnd, SAME_GROUP);
           /*change by podd*/
	   if(thislabel){
              thislabel->statbody = p;
              thislabel->labtype = LABEXEC;
              p->label = thislabel;   
           }                   
	}
	/* pred_bfnd = pred_bfnd->control_parent;*/
	/* cur_blob = follow_blob(pred_bfnd->entry.Template.bl_ptr1);*/
	while (pred_bfnd->variant == ELSEWH_NODE)
	  pred_bfnd = pred_bfnd->control_parent;
	past_pred = pred_bfnd;
	pred_bfnd = pred_bfnd->control_parent;
	q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	cur_blob = (q && (q->ref == past_pred)) ?
	             q
		    :follow_blob(pred_bfnd->entry.Template.bl_ptr2);
}

void
make_endforall(s) 
     PTR_SYMB s; 
{
	PTR_BFND p, past_pred;
	PTR_BLOB q;
	void set_blobs();

	if ((pred_bfnd==BFNULL) || (pred_bfnd->control_parent==BFNULL)
	     || (pred_bfnd->variant != FORALL_NODE)) {
		fatalstr("Illegal ENDFORALL", (char *)NULL, 289);
	}
	if ((!cur_blob->ref) || (cur_blob->ref->variant != CONTROL_END)) {
	   p = get_bfnd(fi,CONTROL_END, s, LLNULL, LLNULL, LLNULL);
           if (is_openmp_stmt) { /*OMP*/
              is_openmp_stmt = 0; /*OMP*/
              p -> decl_specs = BIT_OPENMP; /*OMP*/
           } /*OMP*/
	   set_blobs(p, pred_bfnd, SAME_GROUP);
           /*change by podd*/
	   if(thislabel){
              thislabel->statbody = p;
              thislabel->labtype = LABEXEC;
              p->label = thislabel;   
           }                   
	}
	past_pred = pred_bfnd;
	pred_bfnd = pred_bfnd->control_parent;
	q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	cur_blob = (q && (q->ref == past_pred)) ?
	             q
		    :follow_blob(pred_bfnd->entry.Template.bl_ptr2);
}

void
make_endselect(s) 
     PTR_SYMB s; 
{
	PTR_BFND p, past_pred;
	PTR_BLOB q;
	void set_blobs();

	if ((pred_bfnd==BFNULL) || (pred_bfnd->control_parent==BFNULL)
	     || (pred_bfnd->variant != SWITCH_NODE)) {
		fatalstr("Illegal ENDSELECT", (char *)NULL, 286);
	}
	if ((!cur_blob->ref) || (cur_blob->ref->variant != CONTROL_END)) {
	   p = get_bfnd(fi,CONTROL_END, s, LLNULL, LLNULL, LLNULL);
           if (is_openmp_stmt) { /*OMP*/
              is_openmp_stmt = 0; /*OMP*/
              p -> decl_specs = BIT_OPENMP; /*OMP*/
           } /*OMP*/
	   set_blobs(p, pred_bfnd, SAME_GROUP);
           
	   if(thislabel){
              thislabel->statbody = p;
              thislabel->labtype = LABEXEC;
              p->label = thislabel;   
           }                   
	}
	past_pred = pred_bfnd;
	pred_bfnd = pred_bfnd->control_parent;
	q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	cur_blob = (q && (q->ref == past_pred)) ?
	             q
		    :follow_blob(pred_bfnd->entry.Template.bl_ptr2);
}


void
make_endextend() 
{
	PTR_BFND p;
	void set_blobs();

	if ((pred_bfnd==BFNULL) || (pred_bfnd->control_parent==BFNULL)
	     || ((pred_bfnd->variant != PDO_NODE) &&
	        (pred_bfnd->variant != PSECTIONS_NODE))) {
/*		fatalstr("Illegal end extend[ed] statement\n", (char *)NULL);*/
	}
	if ((!cur_blob->ref) || (cur_blob->ref->variant != CONTROL_END)) {
	   p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
           if (is_openmp_stmt) { /*OMP*/
              is_openmp_stmt = 0; /*OMP*/
              p -> decl_specs = BIT_OPENMP; /*OMP*/
           } /*OMP*/
	   set_blobs(p, pred_bfnd, SAME_GROUP);
	}
	pred_bfnd = pred_bfnd->control_parent;
	cur_blob = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	if (cur_blob->ref->variant == CONTROL_END)
	cur_blob = follow_blob(pred_bfnd->entry.Template.bl_ptr2);
}

/* 18th, Dec. 90 */
/* modified to take care of PCF FORTRAN's variety of END statements */

PTR_BFND
make_enddoall()
{
        PTR_BFND p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
	PTR_BLOB q;
        if (is_openmp_stmt) { /*OMP*/
           is_openmp_stmt = 0; /*OMP*/
           p -> decl_specs = BIT_OPENMP; /*OMP*/
        } /*OMP*/
	if ((!pred_bfnd) ||
	    ((pred_bfnd->variant != CDOALL_NODE) &&
	     (pred_bfnd->variant != SDOALL_NODE) &&
	     (pred_bfnd->variant != DOACROSS_NODE) &&
	     (pred_bfnd->variant != CDOACROSS_NODE) &&
             (pred_bfnd->variant != PARDO_NODE) &&
             (pred_bfnd->variant != PROCESS_DO_STAT) &&
             (pred_bfnd->variant != PDO_NODE)))
	   execerr("enddoall statement out of place", (char *)NULL);
	q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	if (q != cur_blob) {
	   pred_bfnd->entry.Template.bl_ptr1 =
                 pred_bfnd->entry.Template.bl_ptr2;
	   pred_bfnd->entry.Template.bl_ptr2 = BLNULL;
	}
	return p;
}

PTR_BFND
make_endprocesses()
{
        PTR_BFND p = get_bfnd(fi,PROCESSES_END, SMNULL, LLNULL, LLNULL, LLNULL);
	PTR_BLOB q;

	if ((!pred_bfnd) || (pred_bfnd->variant != PROCESSES_STAT))
	   execerr("endprocesses statement out of place", (char *)NULL);
	q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	if (q != cur_blob) {
	   pred_bfnd->entry.Template.bl_ptr1 =
                 pred_bfnd->entry.Template.bl_ptr2;
	   pred_bfnd->entry.Template.bl_ptr2 = BLNULL;
	}
	return p;
}


void
make_loop()
{
	PTR_BFND p;
	void set_blobs();

	if ((pred_bfnd->variant != CDOALL_NODE) &&
	    (pred_bfnd->variant != SDOALL_NODE) &&
	    (pred_bfnd->variant != DOACROSS_NODE) &&
	    (pred_bfnd->variant != CDOACROSS_NODE))
	  execerr("loop statement out of place", (char *)NULL);
	p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
        if (is_openmp_stmt) { /*OMP*/
           is_openmp_stmt = 0; /*OMP*/
           p -> decl_specs = BIT_OPENMP; /*OMP*/
        } /*OMP*/
	set_blobs(p, pred_bfnd, SAME_GROUP);
	cur_blob = pred_bfnd->entry.Template.bl_ptr1
	  = make_blob(fi,(PTR_BFND) NULL, (PTR_BLOB) NULL);
}


/*
 * Setup of logical IF statement
 */
PTR_BFND
make_logif(if_stmt, body)
	PTR_BFND if_stmt, body;
{
        /*PTR_BFND temp;*/
        PTR_BLOB new_blob;
	void set_blobs(), make_prog_header();

/*
	if (expr->type->variant != T_BOOL) {
		err("non-logical expression in IF statement");
		expr = LLNULL;
	} 
	if (pred_bfnd->variant == GLOBAL)
	  make_prog_header();
	temp = get_bfnd(fi,LOGIF_NODE, SMNULL, expr, LLNULL, LLNULL);
	set_blobs(temp, pred_bfnd, SAME_GROUP);
*/
	new_blob = make_blob(fi,body, BLNULL);
	if_stmt->entry.Template.bl_ptr1 = new_blob;
	body->control_parent = if_stmt;
	return (if_stmt);
}

void
make_extend(s)
     PTR_SYMB s;
{
	void execerr(), set_blobs();
	PTR_BFND p, past_pred;
	PTR_BLOB q;
       if ((pred_bfnd==BFNULL) || (pred_bfnd->control_parent==BFNULL)
	     || ((pred_bfnd->variant != FOR_NODE) &&
	         (pred_bfnd->variant != WHILE_NODE))) {
		fatalstr("Illegal END DO",(char *)NULL, 259);
	}
	p = get_bfnd(fi,CONTROL_END, s, LLNULL, LLNULL, LLNULL);
	if (is_openmp_stmt) { /*OMP*/
		is_openmp_stmt = 0;  /*OMP*/
		p -> decl_specs = BIT_OPENMP; /*OMP*/
	} /*OMP*/
           /*change by podd*/
	   if(thislabel){
              thislabel->statbody = p;
              thislabel->labtype = LABEXEC;
              p->label = thislabel;   
           }                   
	set_blobs(p, pred_bfnd, SAME_GROUP);
	if ((pred_bfnd->variant == PDO_NODE) &&
            (pred_bfnd->index == EXTEND_NODE))
	{
	     cur_blob = pred_bfnd->entry.Template.bl_ptr2
		                          = make_blob(fi,BFNULL, BLNULL);
        }
	else 
	{
	     past_pred = pred_bfnd;
	     pred_bfnd = pred_bfnd->control_parent;
	     q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	     cur_blob = (q && (q->ref == past_pred)) ?
		         q : follow_blob(pred_bfnd->entry.Template.bl_ptr2);
	}
}

void
make_section_extend()
{
	void execerr(), set_blobs();
	PTR_BFND p, past_pred, set_stat_list();
	PTR_BLOB q;
	
   {
	/* mark end of section */
	p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
	set_stat_list(pred_bfnd, p);
	/* mark end of psections's sections */
	p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
	set_blobs(p, pred_bfnd, SAME_GROUP);
	/* prepare for extend statements of psections in case */
	if ((pred_bfnd->variant == PSECTIONS_NODE) && 
            (pred_bfnd->index == EXTEND_NODE))
	{
	     cur_blob = pred_bfnd->entry.Template.bl_ptr2
		                          = make_blob(fi,BFNULL, BLNULL);
        }
	else 
	{
	     past_pred = pred_bfnd;
	     pred_bfnd = pred_bfnd->control_parent;
	     q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	     cur_blob = (q && (q->ref == past_pred)) ?
		         q : follow_blob(pred_bfnd->entry.Template.bl_ptr2);
	}
   }
}

void
make_section(section_name, wait_list)
PTR_LLND section_name, wait_list;
{
	void execerr(), set_blobs();
	PTR_BFND p, set_stat_list();
	
   {
	if (pred_bfnd->variant == SECTION_NODE)
	{
	     p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
	     set_stat_list(pred_bfnd, p);
	}
	if ((pred_bfnd->variant == PSECTIONS_NODE) ||
            (pred_bfnd->variant == PARSECTIONS_NODE))
	{
        p = get_bfnd(fi,SECTION_NODE, SMNULL, section_name, wait_list, LLNULL);
	set_stat_list(pred_bfnd, p);
/*	pred_bfnd = p;*/
	}
	else printf("stat.c:make_section: SECTION NODE's attachment point is not a PSECTION NODE\n"); 
	
   }
}

/* 
 * procedure_call gets an id and parameter list.
 * It handles procedures not seen yet
 */
PTR_SYMB
procedure_call(entry)
PTR_HASH entry;
{
	register PTR_SYMB symb_ptr;

	entry = correct_symtab(entry, PROCEDURE_NAME);
	for (symb_ptr = entry->id_attr; symb_ptr; symb_ptr = symb_ptr->outer)
		if (symb_ptr->variant == PROCEDURE_NAME)
			return (symb_ptr);

	symb_ptr = get_proc_symbol(entry);
	symb_ptr->variant = PROCEDURE_NAME;
	symb_ptr->type = global_default;
	symb_ptr->entry.proc_decl.seen = NO;
	return (symb_ptr);
}


/*
 * proceduer match_parameters gets a proc_id and param_list and performs type
 * checking
 */
void
match_parameters(proc_id, param_list)
	PTR_SYMB proc_id;
	PTR_LLND param_list;
{
	PTR_LLND new;
	void err();

	new = make_llnd(fi,FUNC_CALL, param_list, LLNULL, proc_id);
	if (proc_id->entry.proc_decl.seen == YES)
		if (!chk_params(proc_id->entry.proc_decl.in_list, param_list))
		  /*	err(" Parameter mismatch ")*/ /*podd*/ ;

 /*
  * if procedure declaration not seen yet and otherwise too add this call to
  * the call list 
  */
	new->entry.proc.next_call = proc_id->entry.proc_decl.call_list;
	proc_id->entry.proc_decl.call_list = new;
}


/*
 * chk_params checks formals against actuals -- to be added later
 */
int
chk_params(formal, actual)
	PTR_SYMB formal;
	PTR_LLND actual;
{
	return (1);
}


/*
 * set_stat_list  -- links together an old BIF node list with a new one
 *
 * input:
 *	  old_list - old BIF node list
 *	  stat	   - new BIF node
 *
 * output:
 *	  a BIF node list that links these two together
 */
PTR_BFND
set_stat_list(old_list, stat)
	PTR_BFND old_list, stat;
{
	PTR_BFND ret=BFNULL;
	BOOL    start_new_group = NO;
	void fatal(), set_blobs(), make_prog_header(), close_groups();
       
	if (!stat) return (old_list);
        /* The proper place for this piece of code is in cur_scope(). */
	/* if (pred_bfnd->variant == GLOBAL)
	    make_prog_header(); */
	switch (stat->variant) {
 	    case (IF_NODE):
	    case (LOGIF_NODE):
            case (FORALL_STAT):
	          close_groups();
	          return (old_list);
  	    /* start of group */
 
            case (INTERFACE_STMT):
            case (INTERFACE_OPERATOR):
            case (INTERFACE_ASSIGNMENT):
            case (STRUCT_DECL):
	    case (CDOALL_NODE): 
	    case (SDOALL_NODE):
	    case (DOACROSS_NODE):
	    case (CDOACROSS_NODE):
	    case (FOR_NODE):
	    case (PROCESS_DO_STAT):
	    case (WHILE_NODE):
	    case (FORALL_NODE):
            case (PARDO_NODE):
            case (PROCESSES_STAT):
	    case (PDO_NODE):
	    case (PARREGION_NODE):
	    case (PSECTIONS_NODE):
            case (PARSECTIONS_NODE):
	    case (SECTION_NODE):
            case (CRITSECTION_NODE):
            case (SINGLEPROCESS_NODE):
	    case (SWITCH_NODE):
	    case (WHERE_BLOCK_STMT):
	    case (OMP_SECTION_DIR): /*OMP*/
	    case (OMP_PARALLEL_DIR): /*OMP*/
	    case (OMP_SINGLE_DIR): /*OMP*/
	    case (OMP_MASTER_DIR): /*OMP*/
	    case (OMP_CRITICAL_DIR): /*OMP*/
	    case (OMP_ORDERED_DIR): /*OMP*/
            case (OMP_WORKSHARE_DIR): /*OMP*/
	    case (OMP_PARALLEL_SECTIONS_DIR): /*OMP*/
	    case (OMP_PARALLEL_WORKSHARE_DIR): /*OMP*/
          /*  case (ACC_REGION_DIR): */   /*ACC*/
          /*  case (ACC_DATA_REGION_DIR): */   /*ACC*/
	        start_new_group = NEW_GROUP1;
	    /* NO_OP nodes */
	    case (VAR_DECL):
	    case (PARAM_DECL):
	    case (COMM_STAT):
	    case (NAMELIST_STAT):
	    case (PROS_COMM):
	    case (DIM_STAT):
            case (HPF_TEMPLATE_STAT):
            case (HPF_PROCESSORS_STAT):
	    case (DVM_DISTRIBUTE_DIR):
	    case (DVM_ALIGN_DIR):
	    case (DVM_DYNAMIC_DIR):
            case (DVM_SHADOW_DIR):
	    case (DVM_VAR_DECL):
            case (DVM_POINTER_DIR):
            case (DVM_HEAP_DIR):
	    case (DVM_INHERIT_DIR):
	    case (DVM_TASK_DIR):
            case (DVM_REDUCTION_GROUP_DIR):
	    case (DVM_REMOTE_GROUP_DIR):
            case (DVM_INDIRECT_GROUP_DIR):
            case (DVM_CONSISTENT_GROUP_DIR):
            case (DVM_CONSISTENT_DIR):
            case (DVM_ASYNCID_DIR):
            case (ACC_ROUTINE_DIR):
	    case (DATA_DECL):
	    case (EXTERN_STAT):
	    case (INTRIN_STAT):
	    case (EQUI_STAT):
	    case (IMPL_DECL):
	    case (SAVE_DECL):
	    case (INCLUDE_STAT):
	    case (ATTR_DECL):
	    case (INPORT_DECL):
	    case (OUTPORT_DECL):
            case (ALLOCATABLE_STMT):
	    case (SEQUENCE_STMT):
            case (PRIVATE_STMT):
            case (PUBLIC_STMT):
            case (OPTIONAL_STMT):
            case (POINTER_STMT):
            case (TARGET_STMT):
	    case (STATIC_STMT):
	    /* not an assignment stat */
	    case (GOTO_NODE):
	    case (ASSGOTO_NODE):
	    case (COMGOTO_NODE):
	    case (ARITHIF_NODE):
	    case (LOOP_NODE):
	    case (EXIT_NODE):
            case (CONT_STAT):
	    case (RETURN_STAT):
	    case (STOP_STAT):
	    case (PAUSE_NODE):
	    case (CASE_NODE):
	    case (DEFAULT_NODE):
            /* other */
	    case (ASSIGN_STAT):
	    case (STMTFN_STAT):
	    case (SUM_ACC):
	    case (MULT_ACC):
	    case (MAX_ACC):
	    case (MIN_ACC):
	    case (CAT_ACC):
	    case (OR_ACC):
	    case (AND_ACC):
	    case (READ_STAT):
	    case (WRITE_STAT):
	    case (PRINT_STAT):
	    case (BACKSPACE_STAT):
	    case (REWIND_STAT):
	    case (ENDFILE_STAT):
	    case (INQUIRE_STAT):
	    case (OPEN_STAT):
	    case (CLOSE_STAT):
	    case (OTHERIO_STAT):
	    case (FORMAT_STAT):
	    case (PROC_STAT):
            case (PROS_STAT):
            case (PROS_STAT_LCTN):
            case (PROS_STAT_SUBM):
	    case (ASSLAB_STAT):
            case (LOCK_NODE):
	    case (UNLOCK_NODE):
            case (POST_NODE):
	    case (WAIT_NODE):
	    case (CLEAR_NODE):
            case (POSTSEQ_NODE):
	    case (WAITSEQ_NODE):
	    case (SETSEQ_NODE):
	    case (PRIVATE_NODE):
            case (GUARDS_NODE):
	    case (CYCLE_STMT):
	    case (EXIT_STMT):
	    case (CONTAINS_STMT):
	    case (WHERE_NODE):
	    case (USE_STMT):
	    case (MODULE_PROC_STMT):
	    case (OVERLOADED_ASSIGN_STAT): 
	    case (POINTER_ASSIGN_STAT):
	    case (OVERLOADED_PROC_STAT):
            case (INTENT_STMT):
	    case (CHANNEL_STAT):
	    case (MERGER_STAT):
            case (DVM_REDISTRIBUTE_DIR):
            case (DVM_PARALLEL_ON_DIR):
            case (HPF_INDEPENDENT_DIR):
            case (DVM_SHADOW_GROUP_DIR):
            case (DVM_SHADOW_START_DIR):
            case (DVM_SHADOW_WAIT_DIR):
            case (DVM_REDUCTION_START_DIR):
            case (DVM_REDUCTION_WAIT_DIR):
            case (DVM_CONSISTENT_START_DIR):
            case (DVM_CONSISTENT_WAIT_DIR):
	    case (DVM_REALIGN_DIR):
	    case (DVM_NEW_VALUE_DIR):
	    case (DVM_REMOTE_ACCESS_DIR):
            case (DVM_TASK_REGION_DIR):
            case (DVM_END_TASK_REGION_DIR):
            case (DVM_ON_DIR):
            case (DVM_END_ON_DIR):
            case (DVM_MAP_DIR):
            case (DVM_PARALLEL_TASK_DIR):
            case (DVM_RESET_DIR):
            case (DVM_PREFETCH_DIR):
            case (DVM_INDIRECT_ACCESS_DIR):
            case (DVM_OWN_DIR):
            case (DVM_INTERVAL_DIR):
            case (DVM_ENDINTERVAL_DIR):
            case (DVM_EXIT_INTERVAL_DIR):
            case (DVM_DEBUG_DIR):
            case (DVM_ENDDEBUG_DIR):
            case (DVM_TRACEON_DIR):  
            case (DVM_TRACEOFF_DIR):
            case (DVM_BARRIER_DIR):
            case (DVM_CHECK_DIR):
            case (DVM_ASYNCHRONOUS_DIR):
            case (DVM_ENDASYNCHRONOUS_DIR):
            case (DVM_ASYNCWAIT_DIR):
            case (DVM_F90_DIR):
            case (DVM_IO_MODE_DIR):
            case (DVM_CP_CREATE_DIR):
            case (DVM_CP_LOAD_DIR):
            case (DVM_CP_SAVE_DIR):
            case (DVM_CP_WAIT_DIR):
            case (DVM_LOCALIZE_DIR):
            case (DVM_SHADOW_ADD_DIR):
	    case (MOVE_PORT):
            case (DVM_TEMPLATE_CREATE_DIR):
            case (DVM_TEMPLATE_DELETE_DIR):
	    case (SEND_STAT):
	    case (RECEIVE_STAT):
	    case (ENDCHANNEL_STAT):
	    case (PROBE_STAT):
	    case (ALLOCATE_STMT):
	    case (DEALLOCATE_STMT):
	    case (NULLIFY_STMT):
	    case (OMP_DO_DIR): /*OMP*/
	    case (OMP_END_DO_DIR): /*OMP*/
	    case (OMP_PARALLEL_DO_DIR): /*OMP*/
	    case (OMP_END_PARALLEL_DO_DIR): /*OMP*/
	    case (OMP_BARRIER_DIR): /*OMP*/
	    case (OMP_ATOMIC_DIR): /*OMP*/
	    case (OMP_FLUSH_DIR): /*OMP*/
	    case (OMP_THREADPRIVATE_DIR): /*OMP*/
	    case (OMP_ONETHREAD_DIR): /*OMP*/
            case (ACC_REGION_DIR):             /*ACC*/
            case (ACC_END_REGION_DIR):         /*ACC*/
            case (ACC_CHECKSECTION_DIR):       /*ACC*/
            case (ACC_END_CHECKSECTION_DIR):   /*ACC*/
            case (ACC_GET_ACTUAL_DIR):         /*ACC*/ 
            case (ACC_ACTUAL_DIR):             /*ACC*/
            case (SPF_ANALYSIS_DIR):           /*SPF*/
            case (SPF_PARALLEL_DIR):           /*SPF*/
            case (SPF_TRANSFORM_DIR):          /*SPF*/ 
            case (SPF_PARALLEL_REG_DIR):       /*SPF*/
            case (SPF_END_PARALLEL_REG_DIR):   /*SPF*/ 
            case (SPF_CHECKPOINT_DIR):         /*SPF*/ 
	      if (start_new_group) {
		if (stat->variant == CDOALL_NODE
		    || stat->variant == SDOALL_NODE
		    || stat->variant == DOACROSS_NODE
		    || stat->variant == CDOACROSS_NODE)
		  set_blobs(stat, pred_bfnd, NEW_GROUP2);
		else
		  set_blobs(stat, pred_bfnd, NEW_GROUP1);
	      } else
		  set_blobs(stat, pred_bfnd, SAME_GROUP);
		break;
	    case (CONTROL_END):
	    case (PROCESSES_END):
           /* case (ACC_END_REGION_DIR): */   /*ACC*/
	    case (OMP_END_PARALLEL_DIR): /*OMP*/
	    case (OMP_END_SINGLE_DIR): /*OMP*/
	    case (OMP_END_MASTER_DIR): /*OMP*/
	    case (OMP_END_CRITICAL_DIR): /*OMP*/
	    case (OMP_END_ORDERED_DIR): /*OMP*/
	    case (OMP_END_PARALLEL_WORKSHARE_DIR): /*OMP*/
	    case (OMP_END_WORKSHARE_DIR): /*OMP*/
	    case (OMP_END_PARALLEL_SECTIONS_DIR): /*OMP*/
	    case (OMP_END_SECTIONS_DIR): /*OMP*/ {
	        make_endblock(stat);
		break;
	    }
	    default:
		err("Compiler bug (stat.c)", 0);
		ret = old_list;
	}
     
	close_groups();
	return (ret);
}


void
close_groups()
{
     PTR_BFND past_pred;
     PTR_BLOB q;
     
     while (end_group > 0) {
	  past_pred = pred_bfnd;
	  pred_bfnd = pred_bfnd->control_parent;
	  q = follow_blob(pred_bfnd->entry.Template.bl_ptr1);
	  cur_blob = (q && (q->ref == past_pred)) ?
	       q : follow_blob(pred_bfnd->entry.Template.bl_ptr2); 
/*	  cur_blob = follow_blob(pred_bfnd->entry.Template.bl_ptr1); */
	  --end_group;
     }
}


/*
 *  Makes a PROG_HEDR statement for programs which does not start with
 *  a program name.
 */ 
void
make_prog_header()
{/*never used function*/
     PTR_BFND first_bfnd;
     /*PTR_BLOB b;*/
     void set_blobs();
     first_bfnd = BFNULL;
     parstate = INSIDE;
     set_blobs(first_bfnd, global_bfnd, NEW_GROUP1);
}



PTR_SYMB
proc_decl_init(entry, type)
PTR_HASH entry;
int type;
{
	PTR_SYMB symb_ptr;

	undeftype = NO;
	entry = correct_symtab(entry, type);
	mod_offset = yylineno - 1;
	for (symb_ptr = head_symb; symb_ptr; symb_ptr = symb_ptr->thread)
		if ((strcmp(symb_ptr->ident, entry->ident) == 0) &&
		    (symb_ptr->variant == PROCEDURE_NAME))
			break;
	if (!symb_ptr)
		symb_ptr = install_entry(entry, SOFT);
	if (type == FUNCTION_NAME)
	   symb_ptr->type = (vartype == global_default) ?
	                        (undeftype ? global_unknown
			               :impltype[*entry->ident - 'a'])
			          : vartype;

	symb_ptr->variant = type;
	symb_ptr->scope = global_bfnd;
	symb_ptr->entry.proc_decl.seen = YES;
	return (symb_ptr);
}



/*
 * End of declaration section of procedure.  Allocate storage.
 */
void
enddcl()
{ PTR_BFND scope;
 PTR_SYMB fname,res;
	parstate = INEXEC;
        /*16.03.03*/
        scope=cur_scope();
        if(scope->variant == FUNC_HEDR && scope->entry.Template.ll_ptr1){ /*current scope is function header with RESULT clause*/
          fname = scope->entry.Template.symbol;
          res = scope->entry.Template.ll_ptr1->entry.Template.symbol;
          fname->type = res->type; /* characteristics of result identifier are set on function name*/
          fname->attr =fname->attr | res->attr;
        }  
/*
	docommon();
	doequiv();
	docomleng();
*/
}

/*
 * Start a new procedure
 */
void
newprog()
{
	void execerr();

	mod_offset = yylineno - 1;
	/* if (parstate != OUTSIDE)
		execerr("missing end statement", (char *)NULL); */	
        if (parstate == OUTSIDE) {
	  setimpl(global_float, 'a', 'z');
	  setimpl(global_int, 'i', 'n');
        } 
        parstate = INSIDE;

}


/*
 * Main program or Block data
 */
void
startproc(prgname, class)
	PTR_SYMB prgname;
	int     class;
{
}


/*
 *  pop_lab either marks all labels in inner blocks unreachable
 *    or moves all labels referred to in inner blocks out a level
 */ /*
void
pop_lab()
{
	register PTR_LABEL lp;

	for (lp = head_label; lp; lp = lp->next)
		if (lp->labdefined) {
*/		/* mark all labels in inner blocks unreachable */
/*			if (lp->blklevel > blklevel)
				lp->labinacc = YES;
		} else if (lp->blklevel > blklevel) {
*/		/* move all labels referred to in inner blocks out a level */
/*			lp->blklevel = blklevel;
		}
}
*/

/*
 * make_do handles the DO statement.
 *
 * input:
 *	  label - the label of the last statement of the DO loop
 *	  spec  - list of low level nodes specifying the starting,
 *		  value, end value, and increment of the loop
 *
 * output:
 *	  returns a BIF node which contains the necessary information
 *	  of a loop header
 */
PTR_BFND
make_do(type, label, symbol, start, end, stride)
        int      type;
	PTR_LABEL label;
	PTR_SYMB symbol;
        PTR_LLND start, end, stride;
{
       
	PTR_BFND bfnd;
	PTR_LLND ddot;

        if (symbol != SMNULL)
	  symbol->dovar = 1;
        if(type == FOR_NODE)
	  ddot = make_llnd(fi, DDOT, start, end, SMNULL);
        else
          ddot = start;
	bfnd = get_bfnd(fi, type, symbol, ddot, stride, LLNULL);
	bfnd->entry.for_node.doend = label;
	return (bfnd);
}

/* Assuming where_cond is unused in FORTRAN */
PTR_BFND
make_pardo(type, label, symbol, start, end, stride, qualities)
        int      type;
	PTR_LABEL label;
	PTR_SYMB symbol;
        PTR_LLND start, end, stride, qualities;
{
       
	PTR_BFND bfnd;
	PTR_LLND ddot;

	ddot = make_llnd(fi, DDOT, start, end, SMNULL);
	bfnd = get_bfnd(fi, type, symbol, ddot, stride, LLNULL);
	bfnd->entry.for_node.doend = label;
	bfnd->entry.for_node.where_cond = qualities;
	return (bfnd);
}

PTR_BFND
make_processdo(type, label, symbol, start, end, stride)
        int      type;
	PTR_LABEL label;
	PTR_SYMB symbol;
        PTR_LLND start, end, stride;
{
       
	PTR_BFND bfnd;
	PTR_LLND ddot;

        symbol->dovar = 1;
	ddot = make_llnd(fi, DDOT, start, end, SMNULL);
	bfnd = get_bfnd(fi, type, symbol, ddot, stride, LLNULL);
	bfnd->entry.for_node.doend = label;
	return (bfnd);
}

PTR_BFND
make_processes()
{
	PTR_BFND p;
	void make_prog_header();

	if (pred_bfnd->variant == GLOBAL)
	  make_prog_header();

	p = get_bfnd(fi, PROCESSES_STAT, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}

void
set_blobs(stat, parent, new_group)
PTR_BFND stat, parent;
int new_group;
{
	if (((new_group == NEW_GROUP1) && stat->entry.Template.bl_ptr1) ||
	    ((new_group == NEW_GROUP2) && stat->entry.Template.bl_ptr2))
	  return;
	stat->control_parent = parent;
	if (!cur_blob) {
	  /*(void)fprintf(stderr, "cur_blob is null !\n");*/ /*podd*/
           fatalstr("Illegal program structure (set_blobs)",(char *)NULL,342);
	   return;
	}
	if (cur_blob->ref) {
		cur_blob->next = make_blob(fi,stat, BLNULL);
		cur_blob = cur_blob->next;
	} else 
	  cur_blob->ref = stat;
	if (new_group) {
		pred_bfnd = stat;
		cur_blob = make_blob(fi,BFNULL, BLNULL);
		if (new_group == NEW_GROUP1)
		   stat->entry.Template.bl_ptr1 = cur_blob;
		else
		   stat->entry.Template.bl_ptr2 = cur_blob;
	}
}

PTR_LABEL make_label_node(fi, l)
   	PTR_FILE fi;
	long	 l;
   {    PTR_LABEL new_lab;
        PTR_BFND  this_scope;
        this_scope = cur_scope();
	for (new_lab = fi->head_lab; new_lab; new_lab = new_lab->next)
		if (new_lab->stateno == l && new_lab->scope == this_scope)
			return (new_lab);
        new_lab =make_label(fi, l);
        if(new_lab->stateno == 0)
           err("Label out of range",38);
        new_lab -> scope = this_scope;
        return (new_lab);
   }

int is_interface_stat(st)
     PTR_BFND st;
{if(st->variant == INTERFACE_STMT || st->variant == INTERFACE_ASSIGNMENT || st->variant == INTERFACE_OPERATOR)
   return(1);
 else
   return(0);
}

PTR_BFND
make_endparallel()
{
        PTR_BFND p = get_bfnd(fi,OMP_END_PARALLEL_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	/*PTR_BLOB q;*/
	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_PARALLEL_DIR))
	   execerr("OMP END PARALLEL DIR out of place", (char *)NULL);
	return p;
}

PTR_BFND
make_parallel()
{
	PTR_BFND p = get_bfnd(fi, OMP_PARALLEL_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}


PTR_BFND
make_endsingle()
{
        PTR_BFND p = get_bfnd(fi,OMP_END_SINGLE_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	/*PTR_BLOB q;*/

	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_SINGLE_DIR))
	   execerr("OMP END SINGLE DIR out of place", (char *)NULL);
	return p;
}

PTR_BFND
make_single()
{
	PTR_BFND p;
	p = get_bfnd(fi, OMP_SINGLE_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}

PTR_BFND
make_endmaster()
{
        PTR_BFND p = get_bfnd(fi,OMP_END_MASTER_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_MASTER_DIR))
	   execerr("OMP END MASTER DIR out of place", (char *)NULL);
	return p;
}

PTR_BFND
make_master()
{
	PTR_BFND p = get_bfnd(fi, OMP_MASTER_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}

PTR_BFND
make_endordered()
{
        PTR_BFND p = get_bfnd(fi,OMP_END_ORDERED_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	/*PTR_BLOB q;*/

	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_ORDERED_DIR))
	   execerr("OMP END ORDERED DIR out of place", (char *)NULL);
	return p;
}

PTR_BFND
make_ordered()
{
	PTR_BFND p;
	p = get_bfnd(fi, OMP_ORDERED_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}

PTR_BFND
make_endcritical()
{
        PTR_BFND p = get_bfnd(fi,OMP_END_CRITICAL_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_CRITICAL_DIR))
	   execerr("OMP END CRITICAL DIR out of place", (char *)NULL);
	return p;
}

PTR_BFND
make_critical()
{
	PTR_BFND p = get_bfnd(fi, OMP_CRITICAL_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}

PTR_BFND
make_endsections()
{
        PTR_BFND p;
	/*PTR_BLOB q;*/
	/* mark end of section */
	p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
	set_stat_list(pred_bfnd, p);
	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_SECTIONS_DIR)) {
		fprintf (stderr,"%d",pred_bfnd->variant);
	   execerr("OMP END SECTIONS DIR out of place", (char *)NULL);
	}
        p = get_bfnd(fi,OMP_END_SECTIONS_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return p;
}

PTR_BFND
make_sections(PTR_LLND clause)
{
	PTR_BFND p;
	p = get_bfnd(fi, OMP_SECTIONS_DIR, SMNULL, clause, LLNULL, LLNULL);
	set_blobs(p, pred_bfnd, NEW_GROUP1);
	p = get_bfnd(fi, OMP_SECTION_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}

PTR_BFND
make_ompsection()
{
    PTR_BFND p;
    /*PTR_BLOB q;*/
    if (pred_bfnd) {
	if (pred_bfnd->variant == OMP_SECTION_DIR) {
		if (last_bfnd->variant == OMP_SECTION_DIR) {
			return BFNULL;	
		} else {
			p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
			set_stat_list(pred_bfnd, p);
		}
	}
    }
    p = get_bfnd(fi, OMP_SECTION_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
    return p;
}

PTR_BFND
make_endparallelsections()
{
        PTR_BFND p;
	/*PTR_BLOB q;*/
	/* mark end of section */
	p = get_bfnd(fi,CONTROL_END, SMNULL, LLNULL, LLNULL, LLNULL);
	set_stat_list(pred_bfnd, p);
	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_PARALLEL_SECTIONS_DIR)) {
		fprintf (stderr,"%d",pred_bfnd->variant);
		execerr("OMP END PARALLEL SECTIONS DIR out of place", (char *)NULL);
	}
        p = get_bfnd(fi,OMP_END_PARALLEL_SECTIONS_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return p;
}

PTR_BFND
make_parallelsections(PTR_LLND clause)
{
	PTR_BFND p;
	p = get_bfnd(fi, OMP_PARALLEL_SECTIONS_DIR, SMNULL, clause, LLNULL, LLNULL);
	set_blobs(p, pred_bfnd, NEW_GROUP1);
	p = get_bfnd(fi, OMP_SECTION_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}

PTR_BFND
make_endworkshare()
{
        PTR_BFND p = get_bfnd(fi,OMP_END_WORKSHARE_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	/*PTR_BLOB q;*/
	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_WORKSHARE_DIR))
	   execerr("OMP END WORKSHARE DIR out of place", (char *)NULL);
	return p;
}

PTR_BFND
make_workshare()
{
	PTR_BFND p = get_bfnd(fi, OMP_WORKSHARE_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}

PTR_BFND
make_endparallelworkshare()
{
        PTR_BFND p = get_bfnd(fi,OMP_END_PARALLEL_WORKSHARE_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	if ((!pred_bfnd) || (pred_bfnd->variant != OMP_PARALLEL_WORKSHARE_DIR))
	   execerr("OMP END PARALLEL WORKSHARE DIR out of place", (char *)NULL);
	return p;
}

PTR_BFND
make_parallelworkshare()
{
	PTR_BFND p;
	p = get_bfnd(fi, OMP_PARALLEL_WORKSHARE_DIR, SMNULL, LLNULL, LLNULL, LLNULL);
	return (p);
}
