/*
 * Copyright (c) 2004 - 2010, Nils R. Weller
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef CONTROL_H
#define CONTROL_H

struct token;
struct expr;
struct scope;
struct function;
struct control;
struct label;

extern struct control	*curcont;

/*
 * label for goto or switch cases. Note that the actual label name will be
 * generated by icode_make_label() - to avoid name collisions - and thus
 * it is necessary to record the C source label name separately in ``name''
 */
struct label {
	char			*name;
	int			is_switch_label;
	int			appended;
	struct icode_instr	*instr;
	struct expr		*value; /* for ``case'' labels */
	struct label		*next;	
};

void	append_label_list(
	struct label **head,
	struct label **tail, 
	struct label *l
);

struct control {
	/*
	 * Type of control structure- if, do, while, for, else or switch
	 */
	int			type;
	int			compound_body;
	struct token		*tok;

	int			braces;
	int			putscope;

	/*
	 * Condition expression. if (ex),  do while (ex), while (ex),
	 * for (;ex;), switch (ex)
	 */
	struct expr		*cond;
	/*
	 * for() initialization expression, if type = for - for (finit;;)
	 */
	struct expr		*finit;

	/*
	 * C99 style for () initialization with variable declaration
	 */
	struct decl		**dfinit;
	struct scope		*dfscope;

	/*
	 * for() continuing expression, if type = for - for (;;fcont)
	 */
	struct expr		*fcont;

	/*
	 * The body statement may be preceded by a label;
	 * if (foo) label: puts("bar");
	 */
	struct icode_list	*body_labels;

	/*
	 * If we are dealing with a single statement, as in switch (0)
	 * default: puts("hello world"), this is a pointer to that statement
	 */
	struct statement	*stmt;

	/* switch labels */
	struct label		*labels;
	struct label		*labels_tail;

	/* Start of control structure if loop */ 
	struct icode_instr	*startlabel;

	/* End of control structure if loop, if-else statement or switch */
	struct icode_instr	*endlabel;

	/* Condition in do-while loop. Needed for ``continue'' */
	struct icode_instr	*do_cond;

	/* Label preceding ``z;'' in ``for (x; y; z)'' - for ``continue'' */
	struct icode_instr	*fcont_label;

	struct control	*parent; /* parent control structure, if any */

	struct control	*prev; /* `if' if this is `else' */

	struct control	*next; /* `else' if this is `if' */
};


struct control *parse_ctrl(struct control *parent, struct token **tok,
int putscope, int *compound);
void	complete_ctrl(struct token **tok, struct control *ctrl);
int	is_label(struct token **tok);
int	try_label(struct token **tok, struct label **resp);

#endif

