/*  Functions from hack's utils library.
    Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003
    Free Software Foundation, Inc.

    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 3, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */

#include <stdio.h>

#include "basicdefs.h"

#include <fcntl.h>
#ifndef O_BINARY
# ifdef _O_BINARY
#  define O_BINARY _O_BINARY
#  define setmode  _setmode
# endif
#endif

#ifdef O_BINARY
# include <io.h>
# include <sys/types.h>
# include <sys/stat.h>
# ifndef S_ISCHR
#  define S_ISCHR(m)  (((m) & S_IFMT) == S_IFCHR)
# endif
# if __DJGPP__
#  include <crt0.h>
extern int _crt0_startup_flags;
#  undef  IS_DIR_SEPARATOR
#  define IS_DIR_SEPARATOR(c)  ((c) == '/' || (c) == '\\' || (c) == ':')
#  include <libc/unconst.h>
#  define STRIP_EXTENSION(file_name)                   \
   (__extension__                                      \
     ({                                                \
        char *_begin, *_end;                           \
        _begin = _end = unconst((file_name), char *);  \
        while (*_end++)                                \
          ;                                            \
        while ((_end - _begin) && (*--_end != '.'))    \
          ;                                            \
        if (*_end == '.')                              \
          *_end = '\0';                                \
        (file_name);                                   \
     })                                                \
   )

   /*
    *  For some non posix systems where multiple cmds
    *  separated by semicolon must be explicitly
    *  enabled before calling system().
    */
#  define system_flags   __system_flags
#  define system_allow_multiple_cmds  __system_allow_multiple_cmds
#  define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING  1
#  define IS_TMPDIR(dirname)                       (!((dirname) == NULL || access((dirname), D_OK)))
extern int __system_flags;

void xfree (void *ptr);
# else /*  !__DJGPP__  */
#  define STRIP_EXTENSION(file_name)               (file_name)
#  define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING  0
#  define IS_TMPDIR(dirname)                       ((dirname) != NULL)
# endif /*  !__DJGPP__  */
# define IS_SLASH(C)                               ((C) == '/' || (C) == '\\')
# define LAST_SLASH(filename)           \
  ({                                    \
     char *_pb, *_ps;                   \
     _pb = strrchr((filename), '\\');   \
     _ps = strrchr((filename), '/');    \
     if (!_pb && !_ps)                  \
       _ps = strrchr((filename), ':');  \
     else if (_pb > _ps) _ps = _pb;     \
     _ps;                               \
  })
#else /*  !O_BINARY  */
  /*  posix  */
# define STRIP_EXTENSION(file_name)                (file_name)
# define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING   0
# define IS_TMPDIR(dirname)                        ((dirname) != NULL)
# define IS_SLASH(C)                               ((C) == '/')
# define LAST_SLASH(filename)                      (strrchr((filename), '/'))
#endif

#define LFN_FILE_SYSTEM(filename)  (pathconf((filename), _PC_NAME_MAX) > 12)


void panic (const char *str, ...);

void set_read_mode (FILE *stream);
FILE *ck_fopen (const char *name, const char *mode, int fail);
FILE *ck_fdopen (int fd, const char *name, const char *mode, int fail);
void ck_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t ck_fread (void *ptr, size_t size, size_t nmemb, FILE *stream);
void ck_fflush (FILE *stream);
void ck_fclose (FILE *stream);
const char *follow_symlink (const char *path);
size_t ck_getdelim (char **text, size_t *buflen, char buffer_delimiter, FILE *stream);
FILE * ck_mkstemp (char **p_filename, const char *tmpdir, const char *base,
		   const char *mode);
void ck_rename (const char *from, const char *to, const char *unlink_if_fail);

void *ck_malloc (size_t size);
void *xmalloc (size_t size);
void *ck_realloc (void *ptr, size_t size);
char *ck_strdup (const char *str);
void *ck_memdup (const void *buf, size_t len);

struct buffer *init_buffer (void);
char *get_buffer (struct buffer *b);
size_t size_buffer (struct buffer *b);
char *add_buffer (struct buffer *b, const char *p, size_t n);
char *add1_buffer (struct buffer *b, int ch);
void free_buffer (struct buffer *b);

extern const char *myname;
