/*
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 */
/* $Id$ */
/*	D E C L A R A T O R   M A N I P U L A T I O N		*/

#include	"parameters.h"
#include    "declarator.h"
#include	<alloc.h>
#include	<flt_arith.h>
#include	"arith.h"
#include	"type.h"
#include	"proto.h"
#include	"Lpars.h"
#include	"declar.h"
#include	"def.h"
#include    "idf.h"
#include	"label.h"
#include	"expr.h"
#include	"sizes.h"
#include	"level.h"
#include    "error.h"

extern char options[];
struct declarator null_declarator;

struct type *
declare_type(
	struct type *tp,
	struct declarator *dc)
{
	/*	Applies the decl_unary list starting at dc->dc_decl_unary
		to the type tp and returns the result.
		Functions that are declared within a parameter type list
		are purely prototypes. Simply add the type list to the
		function node.
	*/
	register struct decl_unary *du = dc->dc_decl_unary;

	while (du)	{
		tp = construct_type(du->du_fund, tp, du->du_typequal,
				    du->du_count, du->du_proto);
		du = du->next;
	}
	return tp;
}

void add_decl_unary(register struct declarator *dc, int fund, int qual,  arith count, struct formal *fm, struct proto *pl)
{
	/*	A decl_unary describing a constructor with fundamental
		type fund and with size count is inserted in front of the
		declarator dc.
	*/
	register struct decl_unary *new = new_decl_unary();

	new->next = dc->dc_decl_unary;
	new->du_fund = fund;
	new->du_count = count;
	new->du_typequal = qual;
	new->du_proto = pl;
	if (fm)	{
		if (dc->dc_decl_unary)	{
			/* parameters only allowed at first decl_unary	*/
			error("formal parameters list discarded");
		}
		else	{
			/* register the proto	*/
			dc->dc_formal = fm;
		}
	}

	dc->dc_decl_unary = new;
}

void remove_declarator(struct declarator *dc)
{
	/*	The decl_unary list starting at dc->dc_decl_unary is
		removed.
	*/
	register struct decl_unary *du = dc->dc_decl_unary;

	while (du)	{
		struct decl_unary *old_du = du;

		du = du->next;
		free_decl_unary(old_du);
	}
}

void reject_params(register struct declarator *dc)
{
	/*	The declarator is checked to have no parameters, if it
		is an old-style function.  If it is a new-style function,
		the identifiers are removed.  The function is not called in
		case of a function definition.
	*/
	register struct decl_unary *du = dc->dc_decl_unary;
	int	err_given = 0;

	if (dc->dc_formal)	{
		error("non_empty formal parameter pack");
		free_formals(dc->dc_formal);
		dc->dc_formal = 0;
		err_given = 1;
	}
	while (du) {
		if (du->du_fund == FUNCTION) {
			if (du->du_proto) remove_proto_idfs(du->du_proto);
			else if (! err_given && ! options['o']) {
				err_given = 1;
				warning("old-fashioned function declaration");
			}
		}
		du = du->next;
	}
}

void check_array_subscript(register struct expr *expr)
{
	writh size = expr->VL_VALUE;

	if (size < 0)	{
		error("array size is negative");
		expr->VL_VALUE = 1;
	}
	else
	if (size == 0) {
		strict("array size is 0");
	}
	else
	if (size & ~max_unsigned) {	/* absolutely ridiculous */
		expr_error(expr, "overflow in array size");
		expr->VL_VALUE = 1;
	}
}
