/* $Id: util.h,v 1.20 2003/05/18 21:59:03 aa5779 Exp $ */
/* utils.h -- declarations related to `util.c' */
/*
 	Copyright (C) 2001, 2002, 2003 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
*/

#ifndef UTIL_H
#define UTIL_H

#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <stdarg.h>
#if defined(USE_OBJC_API) || defined(nil)
#include <objc/objc.h>
#include <objc/objc-api.h>
#endif

#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define LIKE_PRINTF __attribute__ ((format (printf, 1, 2)))
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5)
#define NORETURN __attribute__ ((noreturn))
#define CONST_FUNC __attribute__ ((const))
#else
#define NORETURN
#define CONST_FUNC
#endif
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
#define LIKE_MALLOC __attribute__ ((malloc))
#define PURE_FUNC __attribute__ ((pure))
#else
#define LIKE_MALLOC
#define PURE_FUNC
#endif
#else
#define NORETURN
#define LIKE_PRINTF
#define LIKE_MALLOC
#define CONST_FUNC
#define PURE_FUNC
#endif

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

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

const char *translate_cvs_date(const char *date);

int lock_file(int fd, int writing);
int unlock_file(int fd);

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

char *set_current_filename(char *fname);

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

void register_error_handler(void *arg);
void print_error_msg(const char *fmt, ...) LIKE_PRINTF;
void recover_error(const char *fmt, ...) NORETURN LIKE_PRINTF;
void recover_errorv(const char *fmt, va_list args) NORETURN;
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

#if defined(USE_OBJC_API) || defined(nil)
#define xmalloc(size) objc_malloc(size)
#define xcalloc(n, size) objc_calloc(n, size)
#define xrealloc(addr, ns) objc_realloc(addr, ns)
#else
void *xmalloc(size_t size) LIKE_MALLOC;
void *xcalloc(size_t n, size_t size) LIKE_MALLOC;
void *xrealloc(void *addr, size_t news) LIKE_MALLOC;
#endif
char *xstrdup(const char *str) LIKE_MALLOC;

void *alloc_chunk(int size) LIKE_MALLOC;
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) PURE_FUNC;
int lookup_name(char **names, const char *key) PURE_FUNC;

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


syntax highlighted by Code2HTML, v. 0.9.1