/*
 	Copyright (C) 2001, 2002 Artem V. Andreev (artem@AA5779.spb.edu)

    This program 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.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* $Id: util.h,v 1.16 2002/12/26 09:34:41 aa5779 Exp $ */
#ifndef UTIL_H
#define UTIL_H

#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>

/***\group[Declarations in \thisfile]
*/
const char *libutils_version(void);
const char *libutils_srcdate(void);

int versioncmp(const char *ver1, const char *ver2);

const char *translate_cvs_date(const char *date);

void strupr(char *str);
int isnamesym(int ch);
int isplainnamesym(int ch);

char *set_current_filename(char *fname);

void fatal_error(const char *fmt, ...);
void warning(const char *fmt, ...);

void register_error_handler(void *arg);
void print_error_msg(const char *fmt, ...);
void recover_error(const char *fmt, ...);
void unwind_error(void);
char *get_error_desc(void);
void *get_eh_data(void);
jmp_buf *get_error_buf(void);

/*** \macro[CATCH]
a macro to set a checkpoint where control is transferred to
for a registered error handler. \see[functions][register_error_handler] 
Standard restrictions on use of \ref[setjmp(3)]
do apply.
*/
#define CATCH() (setjmp(*get_error_buf()))

// Safe memory allocation functions

void *xmalloc(size_t size);
void *xcalloc(size_t n, size_t size);
void *xrealloc(void *addr, size_t news);
char *xstrdup(const char *str);

void *alloc_chunk(int size);
void free_chunk(void *chunk, int size);
void reset_free_chunks(void);

/*** \xmacro[ALLOC, FREE]
Wrapper for \see[functions][alloc_chunk], \see[functions][free_chunk]
*/
#define ALLOC(type) (alloc_chunk(sizeof(type)))
#define FREE(p)	(free_chunk((p), sizeof(*(p))))
/*\end*/

// IO functions

int set_line_no(int newnl);

/*** \struct
The structure for memory-mapped files. You can safely use its fields, but
don't ever try to modify them directly. See \see[functions][map_file]
\field[data] a pointer to mapped or loaded file contents.
\field[len] the length of the file
\field[hfile] file handle returned by \ref[open(2)]
\field[really_mapped] 1 if real mapping is used; 0 if emulated
*/
typedef struct mapping
{
	void *data;
	long len;
	int hfile;
	int really_mapped;
} mapping;

int xopen(const char *name, int mode, int rights);
FILE *xfopen(const char *name, const char *mode);

#define PATH_SEP (':')

/*** \typedef
The type of a function to open/create files found by \see[functions][find_filename]
\returns opaque data passed to the caller of \see[functions][find_filename]
*/
typedef void *(*ff_ioproc_t)(const char *name);
void *find_filename(const char *name, const char *path, const char *defext, 
					ff_ioproc_t ioproc, ff_ioproc_t cproc);

char *load_file(const char *name, const char *path, const char *defext);

mapping *map_file(const char *name, const char *path, const char *defext);
int is_map_eof(mapping *map, const char *pos);
void delete_mapping(mapping *map);


// Common parsing functions

void skip_spaces(const char *start, char **end);
void skip_spaces_nc(const char *start, char **end);
int parse_single_char(const char *start, char **end);
int parse_char(const char *start, char **end);
char *parse_string(const char *start, char **end);
char *parse_id(const char *start, char **end);
char *parse_plain_id(const char *start, char **end);
int parse_num_token(const char *start, char **end);
void skip_ifs(const char *start, char **end, int else_flag);

/*** \struct
Generic sequential-access table type for \see[functions][lookup_table].
Fields have obvious meaning.
*/
typedef struct table_t
{
	char *key;
	void *data;
} table_t;

void *lookup_table(table_t *table, const char *key);
int lookup_name(char **names, const char *key);

int enh_atexit(void (*func)(void));

/*** \macro[NUMOFITEMS]
\returns the number of items in a given array
*/
#define NUMOFITEMS(array) (sizeof(array) / sizeof(*(array)))

/*** \macro[ENDOF]
\returns a pointer to the place right behind the next item of an array 
*/
#define ENDOF(array) ((array) + NUMOFITEMS(array))

/***\endgroup */
#endif // UTIL_H
