/*
 * Copyright (c) 1995, 1996, 1997, 1998, 1999 The University of Utah and
 * the Computer Systems Laboratory at the University of Utah (CSL).
 *
 * This file is part of Flick, the Flexible IDL Compiler Kit.
 *
 * Flick is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Flick is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Flick; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place #330, Boston, MA 02111, USA.
 */

#ifndef _mom_compiler_h_
#define _mom_compiler_h_

#include <stdio.h>
#include <stdarg.h>
#include <limits.h>

#ifdef __cplusplus
extern "C" {
#endif


#if defined(__GNUC__) && (__GNUC__ >= 2)
#  if __GNUC_MINOR__ >= 7
#    define DECL_NORETURN(decl) decl __attribute__((__noreturn__))
#    define DEFN_NORETURN(decl) decl
#  else
#    if __GNUC_MINOR__ >= 6
#      define DECL_NORETURN(decl) decl __attribute__((noreturn))
#      define DEFN_NORETURN(decl) decl
#    else
#      define DECL_NORETURN(decl) volatile decl
#      define DEFN_NORETURN(decl) volatile decl
#    endif
#  endif
#else
#  define DECL_NORETURN(decl) decl
#  define DEFN_NORETURN(decl) decl
#endif


/* suffixes for default output filenames */
#define AOID_SUFFIX ".aod"
#define PRES_C_SUFFIX ".prc"
#define PRESD_SUFFIX ".prd"


/* main() must provide this variable
   and set it to the value of argv[0].  */
extern char *progname;


/*
 * Print an error message and exit the program.  Takes a `printf'-style format
 * string and arguments.
 */
DECL_NORETURN(void panic(const char *format, ...));

/*
 * Print a warning.  Takes a `printf'-style format string and arguments.
 */
void warn(const char *format, ...);

/*
 * Like the normal allocation routines, but these never return null.  They call
 * `panic' if we run out of memory.
 */
void *real_mustmalloc(long size, const char *file, int line);
void *real_mustcalloc(long size, const char *file, int line);
void *real_mustrealloc(void *orig_buf,
		       long new_size, const char *file, int line);
char *real_muststrdup(const char *str, const char *file, int line);

#define mustmalloc(size)	real_mustmalloc((size), __FILE__, __LINE__)
#define mustcalloc(size)	real_mustcalloc((size), __FILE__, __LINE__)
#define mustrealloc(org, size)	real_mustrealloc((org), \
						 (size), __FILE__, __LINE__)
#define muststrdup(str)		real_muststrdup((str), __FILE__, __LINE__)

/*
 * Invoke the C or C++ preprocessor on `filename', with command arguments
 * `flags'.  If `filename' is null, arrange for the preprocessor to read from
 * stdin.
 *
 * Return a `FILE *' so that we receive the preprocessor's output.  As a side
 * effect, set the global variable `infilename' to be a printable version of
 * `filename'.
 */
FILE *call_c_preprocessor(const char *filename, const char *flags);
FILE *call_cxx_preprocessor(const char *filename, const char *flags);

/* Various file name processors */

/*
 * Returns the file part of the file name, its just a pointer into the given
 * string, so dup it if you want a new one
 */
const char *file_part(const char *filename);
/* Returns the directory part of the file name, its a new string */
const char *dir_part(const char *filename);
/* Appends filename onto pathname, being careful to insert a '/' if needed */
const char *add_file_part(const char *pathname, const char *filename);
/* Returns true if filename is an absolute path */
int absolute_path(const char *filename);
/* Returns true if filename refers to the current directory (i.e. '.') */
int current_dir(const char *filename);
/*
 * Copy the specified `orig' filename into a new buffer, and replace its suffix
 * (the last `.' and everything beyond it) with the specified `newsuffix'.
 */
char *resuffix(const char *orig, const char *newsuffix);
/* Converts, in place, a filename to a valid C identifier */
void filename_to_c_id(char *filename);

/*
 * Open the file named by `path', in the mode specified by `mode', searching
 * the directories named in `dir_list'.
 */
FILE *fopen_search(const char *path,
		   const char * const *dir_list,
		   const char *mode,
		   /* OUT */ char **out_path);

/*
 * "Allocating sprintf" --- allocates exactly the right amount of memory to
 * contain the formatted string.  Panics if the allocation fails; never returns
 * null.
 */
char *flick_asprintf(const char *fmt, ...);

/*
 * Case-insensitive string comparison.  Since `strcasecmp' is not an ANSI C
 * standard function, we provide this function for ourselves.
 */
int flick_strcasecmp(const char *s1, const char *s2);

/* w_indent.c */
void w_indent(int indent);

/* w_print.c */
void w_putc(char c);
void w_vprintf(const char *format, va_list vl);
void w_printf(const char *format, ...);
void w_set_fh(FILE *out_fh);

/* w_i_print.c */
void w_i_vprintf(int indent, const char *format, va_list vl);
void w_i_printf(int indent, const char *format, ...);

/*
 * We often want to use string literals when building parts of our intermediate
 * representations --- e.g., `cast_new_expr_name("printf")'.  This should be
 * allowed, because we never try to modify or free a string through an IR node
 * reference; in other words, we treat strings in our IRs as `const char *'s.
 *
 * Unfortunately, in ANSI C++, literal strings have type `const char[]'.  The
 * type definitions of our IR nodes always use `char *' because the code for
 * IRs is created for us by `rpcgen', which always maps strings to `char *'s.
 *
 * Since we can't change our node typedefs, we compensate.  We use the special
 * `ir_strlit' macro to import a string into our IRs.  `ir_strlit' accepts a
 * string and produces a `char *', which we may then insert into an IR node
 * without warning from an ANSI C++ compiler.
 *
 * Currently, `ir_strlit' simply casts away the constness of the string, since
 * we promise not to modify the string through the IR reference.  Copying the
 * string is just too expensive, spacewise.
 *
 * Use this macro ONLY to insert a string literal into an `rpcgen'-created IR
 * node.  Don't use this macro to cast away `const'ness in other situations!
 */
#define ir_strlit(str)		((char *) (str))


/*****************************************************************************/

/*
 * This stuff is for standard command line handling.
 */

/* `flag_kind' identifies the types of our flag data. */
enum flag_kind {
	fk_FLAG,
	fk_STRING,
	fk_NUMBER
};
typedef enum flag_kind flag_kind;

/*
 * A `flag_value' contains the data value associated with one occurrence of a
 * command-line flag.
 */
union flag_value {
	int		flag;
	const char *	string;
	int		number;
};
typedef union flag_value flag_value;

/*
 * A `flag_value_seq' contains the data associted with all occurrences of a
 * particular flag on the command line.
 */
struct flag_value_seq {
	unsigned int	len;		/* # of set slots in `values'. */
	unsigned int	max;		/* Allocated length of `values'. */
	flag_value *	values;		/* The data specified for this flag. */
};
typedef struct flag_value_seq flag_value_seq;
void grow_flag_value_seq(flag_value_seq *fvs, int needed);

/*
 * A `flags_in' describes the properties of a command-line flag: its name,
 * type, the number of times that it may appear on the command line, and so on.
 */
struct flags_in {
	char		sng;		/* The short form (e.g., `-o'). */
	const char *	dbl;		/* The long form (e.g., `--opt'). */
	flag_kind	kind;		/* The argument type. */
	int		max_occur;	/* Max # of times flag may occur. */
	flag_value	dfault;		/* Default value. */
	const char *	explain;	/* A string explaining the flag. */
};
typedef struct flags_in flags_in;

/*
 * Special values for `max_occur' above, indicating that the flag may appear
 * any number of times, and how those multiple occurrences should be
 * aggregated.
 */
#define FLAG_UNLIMITED_LIST (-1)	/* Collect the values in a list. */
#define FLAG_UNLIMITED_USE_LAST (-2)	/* Last value wins. */
#define FLAG_UNLIMITED_OR (-3)		/* Logical `or', for flags. */

#define FLAG_UNLIMITED_P(max_occur) ((max_occur) < 0)

/*
 * A `flags_out' describes the parsed command line.
 */
struct flags_out {
	char *			progname;
	flag_value_seq *	flag_seqs;
	int			other_count;
	char **			other;
	int			error;
};
typedef struct flags_out flags_out;

/*
 * This takes a bunch of flags (in the flgs array) and a command line, and
 * builds the flags_out.
 */
flags_out parse_args(int argc, char *argv[], int flag_count, flags_in *flgs);
/*
 * This will print a usage statement automatically.
 */
void print_args_usage(const char *progname,
		      int flag_count, flags_in *flgs,
		      const char *cl_extra, const char *extra);
/*
 * This will pretty-print all the flags --- useful for debugging, etc.
 */
void print_args_flags(flags_out res, int flag_count, flags_in *flgs);

/*
 * This will add the standard flick flags `-v/--version', `-u/--usage', and
 * `-o/--output <filename>' to the array.
 */
void set_def_flags(flags_in *flgs);
/*
 * This will handle version, usage, and errors.
 */
void std_handler(flags_out out, int flag_count, flags_in *flgs,
		 const char *cl_info, const char *info);

/* These are standard locations for the flags to go */
#define STD_FLAGS 4
#define OUTPUT_FILE_FLAG 2

struct fe_flags {
	const char *output;
	const char *cpp_flags;
	int nocpp;
	const char *input;
};
typedef struct fe_flags fe_flags;
/* Since we don't have an FE library, this is here... */
fe_flags front_end_args(int argc, char **argv, const char *info);


/*****************************************************************************/

struct ptr_stack {
	void **ptrs;
	int top;
	int size;
};

struct ptr_stack *create_ptr_stack();
void delete_ptr_stack(struct ptr_stack *stack);
void push_ptr(struct ptr_stack *stack, void *ptr);
void pop_ptr(struct ptr_stack *stack);
void *top_ptr(struct ptr_stack *stack);
int empty_ptr_stack(struct ptr_stack *stack);
int ptr_stack_length(struct ptr_stack *stack);

/* Node struct that is used for
   doubly linked list */
struct list_node {
	struct list_node *succ;
	struct list_node *pred;
};

/* List struct itself, just think of it
   as a combined header and tail node */
struct dl_list {
	struct list_node *head; /* points to the head node */
	struct list_node *tail; /* always == 0 */
	struct list_node *tail_pred; /* points to the tail node */
};

/* list_node/dl_list manipulation functions */
void remove_node(struct list_node *list_node);
void new_list(struct dl_list *list);
void add_head(struct dl_list *list, struct list_node *list_node);
void add_tail(struct dl_list *list, struct list_node *list_node);
struct list_node *rem_head(struct dl_list *list);
struct list_node *rem_tail(struct dl_list *list);
int empty_list(struct dl_list *list);
void insert_node(struct list_node *pred, struct list_node *list_node);

struct h_entry {
	struct h_entry *next;
	const char *name;
};

struct h_table {
	int table_size;
	struct h_entry **entries;
};

struct h_table *create_hash_table(int size);
void delete_hash_table(struct h_table *ht);
void add_entry(struct h_table *ht, struct h_entry *he);
void rem_entry(struct h_table *ht, const char *name);
struct h_entry *find_entry(struct h_table *ht, const char *name);

#ifdef __cplusplus
}
#endif

#endif /* _mom_compiler_h_ */

/* End of file. */



syntax highlighted by Code2HTML, v. 0.9.1