/* -----------------------------------------------------------------------------
 * This file is part of SWIG, which is licensed as a whole under version 3
 * (or any later version) of the GNU General Public License. Some additional
 * terms also apply to certain portions of SWIG. The full details of the SWIG
 * license and copyrights can be found in the LICENSE and COPYRIGHT files
 * included with the SWIG source code as distributed by the SWIG developers
 * and at https://www.swig.org/legal.html.
 *
 * doh.h
 *
 *     This file describes of the externally visible functions in DOH.
 * ----------------------------------------------------------------------------- */

#ifndef SWIG_DOH_H
#define SWIG_DOH_H

#include "swigconfig.h"

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
/* Pull in <cstdio> here so that the "using ::sprintf" it performs happens before sprintf is
 * poisoned at the end of this header.  Otherwise a C++ translation unit which includes <cstdio>
 * afterwards, directly or via <string>, would fail to compile with DOH_POISON defined. */
#include <cstdio>
#endif

/* Set the namespace prefix for DOH API functions. This can be used to control
   visibility of the functions in libraries */

/* Set this macro if you want to change DOH linkage. You would do this if you
   wanted to hide DOH in a library using a different set of names.  Note: simply
   change "Doh" to a new name. */

/*
#define DOH_NAMESPACE(x) Doh ## x
*/

#ifdef DOH_NAMESPACE

/* Namespace control.  These macros define all of the public API names in DOH */

#define DohCheck             DOH_NAMESPACE(Check)
#define DohIntern            DOH_NAMESPACE(Intern)
#define DohDelete            DOH_NAMESPACE(Delete)
#define DohCopy              DOH_NAMESPACE(Copy)
#define DohClear             DOH_NAMESPACE(Clear)
#define DohStr               DOH_NAMESPACE(Str)
#define DohData              DOH_NAMESPACE(Data)
#define DohDump              DOH_NAMESPACE(Dump)
#define DohLen               DOH_NAMESPACE(Len)
#define DohHashval           DOH_NAMESPACE(Hashval)
#define DohCmp               DOH_NAMESPACE(Cmp)
#define DohEqual             DOH_NAMESPACE(Equal)
#define DohIncref            DOH_NAMESPACE(Incref)
#define DohCheckattr         DOH_NAMESPACE(Checkattr)
#define DohSetattr           DOH_NAMESPACE(Setattr)
#define DohDelattr           DOH_NAMESPACE(Delattr)
#define DohKeys              DOH_NAMESPACE(Keys)
#define DohSortedKeys        DOH_NAMESPACE(SortedKeys)
#define DohGetInt            DOH_NAMESPACE(GetInt)
#define DohGetDouble         DOH_NAMESPACE(GetDouble)
#define DohGetChar           DOH_NAMESPACE(GetChar)
#define DohSetChar           DOH_NAMESPACE(SetChar)
#define DohSetInt            DOH_NAMESPACE(SetInt)
#define DohSetDouble         DOH_NAMESPACE(SetDouble)
#define DohSetVoid           DOH_NAMESPACE(SetVoid)
#define DohGetVoid           DOH_NAMESPACE(GetVoid)
#define DohGetitem           DOH_NAMESPACE(Getitem)
#define DohSetitem           DOH_NAMESPACE(Setitem)
#define DohDelitem           DOH_NAMESPACE(Delitem)
#define DohInsertitem        DOH_NAMESPACE(Insertitem)
#define DohDelslice          DOH_NAMESPACE(Delslice)
#define DohWrite             DOH_NAMESPACE(Write)
#define DohRead              DOH_NAMESPACE(Read)
#define DohSeek              DOH_NAMESPACE(Seek)
#define DohTell              DOH_NAMESPACE(Tell)
#define DohGetc              DOH_NAMESPACE(Getc)
#define DohPutc              DOH_NAMESPACE(Putc)
#define DohUngetc            DOH_NAMESPACE(Ungetc)
#define DohGetline           DOH_NAMESPACE(Getline)
#define DohSetline           DOH_NAMESPACE(Setline)
#define DohGetfile           DOH_NAMESPACE(Getfile)
#define DohSetfile           DOH_NAMESPACE(Setfile)
#define DohReplace           DOH_NAMESPACE(Replace)
#define DohChop              DOH_NAMESPACE(Chop)
#define DohGetmeta           DOH_NAMESPACE(Getmeta)
#define DohSetmeta           DOH_NAMESPACE(Setmeta)
#define DohDelmeta           DOH_NAMESPACE(Delmeta)
#define DohEncoding          DOH_NAMESPACE(Encoding)
#define DohPrintf            DOH_NAMESPACE(Printf)
#define DohvPrintf           DOH_NAMESPACE(vPrintf)
#define DohPrintv            DOH_NAMESPACE(Printv)
#define DohReadline          DOH_NAMESPACE(Readline)
#define DohIsMapping         DOH_NAMESPACE(IsMapping)
#define DohIsSequence        DOH_NAMESPACE(IsSequence)
#define DohIsString          DOH_NAMESPACE(IsString)
#define DohIsFile            DOH_NAMESPACE(IsFile)
#define DohNewString         DOH_NAMESPACE(NewString)
#define DohNewStringEmpty    DOH_NAMESPACE(NewStringEmpty)
#define DohNewStringWithSize DOH_NAMESPACE(NewStringWithSize)
#define DohNewStringf        DOH_NAMESPACE(NewStringf)
#define DohStrcmp            DOH_NAMESPACE(Strcmp)
#define DohStrncmp           DOH_NAMESPACE(Strncmp)
#define DohStrstr            DOH_NAMESPACE(Strstr)
#define DohStrchr            DOH_NAMESPACE(Strchr)
#define DohNewFile           DOH_NAMESPACE(NewFile)
#define DohNewFileFromFile   DOH_NAMESPACE(NewFileFromFile)
#define DohNewFileFromFd     DOH_NAMESPACE(NewFileFromFd)
#define DohFileErrorDisplay  DOH_NAMESPACE(FileErrorDisplay)
#define DohCopyto            DOH_NAMESPACE(Copyto)
#define DohNewList           DOH_NAMESPACE(NewList)
#define DohNewHash           DOH_NAMESPACE(NewHash)
#define DohNewVoid           DOH_NAMESPACE(NewVoid)
#define DohSplit             DOH_NAMESPACE(Split)
#define DohSplitLines        DOH_NAMESPACE(SplitLines)
#define DohNone              DOH_NAMESPACE(None)
#define DohCall              DOH_NAMESPACE(Call)
#define DohObjMalloc         DOH_NAMESPACE(ObjMalloc)
#define DohObjFree           DOH_NAMESPACE(ObjFree)
#define DohMemoryDebug       DOH_NAMESPACE(MemoryDebug)
#define DohStringType        DOH_NAMESPACE(StringType)
#define DohListType          DOH_NAMESPACE(ListType)
#define DohHashType          DOH_NAMESPACE(HashType)
#define DohFileType          DOH_NAMESPACE(FileType)
#define DohVoidType          DOH_NAMESPACE(VoidType)
#define DohIterator          DOH_NAMESPACE(Iterator)
#define DohFirst             DOH_NAMESPACE(First)
#define DohNext              DOH_NAMESPACE(Next)
#define DohMalloc            DOH_NAMESPACE(Malloc)
#define DohRealloc           DOH_NAMESPACE(Realloc)
#define DohCalloc            DOH_NAMESPACE(Calloc)
#define DohFree              DOH_NAMESPACE(Free)
#define DohSetExitHandler    DOH_NAMESPACE(SetExitHandler)
#define DohExit              DOH_NAMESPACE(Exit)
#endif

#define DOH_MAJOR_VERSION 0
#define DOH_MINOR_VERSION 1

typedef void DOH;

/*
 * With dynamic typing, all DOH objects are technically of type 'void *'.
 * However, to clarify the reading of source code, the following symbolic
 * names are used.
 */

#define DOHString         DOH
#define DOHList           DOH
#define DOHHash           DOH
#define DOHFile           DOH
#define DOHVoid           DOH
#define DOHString_or_char DOH
#define DOHObj_or_char    DOH

typedef const DOHString_or_char *const_String_or_char_ptr;
typedef const DOHString_or_char *DOHconst_String_or_char_ptr;

#define DOH_BEGIN   -1
#define DOH_END     -2
#define DOH_CUR     -3
#define DOH_CURRENT -3

/* Iterator objects */

typedef struct {
  void *key;      /* Current key (if any)       */
  void *item;     /* Current item               */
  void *object;   /* Object being iterated over */
  void *_current; /* Internal use */
  int _index;     /* Internal use */
} DohIterator;

/* Memory management */

/* Wrappers around malloc(), realloc() and calloc() which never return NULL. */
extern void *DohMalloc(size_t size);
extern void *DohRealloc(void *ptr, size_t size);
extern void *DohCalloc(size_t n, size_t size);

#ifndef DohFree
#define DohFree free
#endif

extern int DohCheck(const DOH *ptr); /* Check if a DOH object */
extern void DohIntern(DOH *);        /* Intern an object      */

/* Basic object methods.  Common to most objects */

extern void DohDelete(DOH *obj); /* Delete an object      */
extern DOH *DohCopy(const DOH *obj);
extern void DohClear(DOH *obj);
extern DOHString *DohStr(const DOH *obj);
extern void *DohData(const DOH *obj);
extern int DohDump(const DOH *obj, DOHFile *out);
extern int DohLen(const DOH *obj);
extern int DohHashval(const DOH *obj);
extern int DohCmp(const DOH *obj1, const DOH *obj2);
extern int DohEqual(const DOH *obj1, const DOH *obj2);
extern void DohIncref(DOH *obj);

/* Mapping methods */

extern DOH *DohGetattr(DOH *obj, const DOHString_or_char *name);
extern int DohSetattr(DOH *obj, const DOHString_or_char *name, const DOHObj_or_char *value);
extern int DohDelattr(DOH *obj, const DOHString_or_char *name);
extern int DohCheckattr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *value);
extern DOH *DohKeys(DOH *obj);
extern DOH *DohSortedKeys(DOH *obj, int (*cmp)(const DOH *, const DOH *));
extern int DohGetInt(DOH *obj, const DOHString_or_char *name);
extern void DohSetInt(DOH *obj, const DOHString_or_char *name, int);
extern double DohGetDouble(DOH *obj, const DOHString_or_char *name);
extern void DohSetDouble(DOH *obj, const DOHString_or_char *name, double);
extern char *DohGetChar(DOH *obj, const DOHString_or_char *name);
extern void DohSetChar(DOH *obj, const DOH *name, char *value);
extern void *DohGetFlagAttr(DOH *obj, const DOHString_or_char *name);
extern int DohGetFlag(DOH *obj, const DOHString_or_char *name);
extern void DohSetFlagAttr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *attr);
extern void DohSetFlag(DOH *obj, const DOHString_or_char *name);
extern void *DohGetVoid(DOH *obj, const DOHString_or_char *name);
extern void DohSetVoid(DOH *obj, const DOHString_or_char *name, void *value);

/* Sequence methods */

extern DOH *DohGetitem(DOH *obj, int index);
extern int DohSetitem(DOH *obj, int index, const DOHObj_or_char *value);
extern int DohDelitem(DOH *obj, int index);
extern int DohInsertitem(DOH *obj, int index, const DOHObj_or_char *value);
extern int DohDelslice(DOH *obj, int sindex, int eindex);

/* File methods */

extern int DohWrite(DOHFile *obj, const void *buffer, int length);
extern int DohRead(DOHFile *obj, void *buffer, int length);
extern int DohSeek(DOHFile *obj, long offset, int whence);
extern long DohTell(DOHFile *obj);
extern int DohGetc(DOHFile *obj);
extern int DohPutc(int ch, DOHFile *obj);
extern int DohUngetc(int ch, DOHFile *obj);

/* Iterators */
extern DohIterator DohFirst(DOH *obj);
extern DohIterator DohNext(DohIterator x);

/* Positional */

extern int DohGetline(const DOH *obj);
extern void DohSetline(DOH *obj, int line);
extern DOH *DohGetfile(const DOH *obj);
extern void DohSetfile(DOH *obj, DOH *file);

/* String Methods */

extern int DohReplace(DOHString *src, const DOHString_or_char *token, const DOHString_or_char *rep, int flags);
extern void DohChop(DOHString *src);

/* Meta-variables */
extern DOH *DohGetmeta(DOH *, const DOH *);
extern int DohSetmeta(DOH *, const DOH *, const DOH *value);
extern int DohDelmeta(DOH *, const DOH *);

/* Utility functions */

extern void DohEncoding(const char *name, DOH *(*fn)(DOH *s));
extern int DohPrintf(DOHFile *obj, const char *format, ...);
extern int DohvPrintf(DOHFile *obj, const char *format, va_list ap);
extern int DohPrintv(DOHFile *obj, ...);
extern DOH *DohReadline(DOHFile *in);

/* Miscellaneous */

extern int DohIsMapping(const DOH *obj);
extern int DohIsSequence(const DOH *obj);
extern int DohIsString(const DOH *obj);
extern int DohIsFile(const DOH *obj);

extern void DohSetMaxHashExpand(int count);
extern int DohGetMaxHashExpand(void);
extern void DohSetmark(DOH *obj, int x);
extern int DohGetmark(DOH *obj);

/* Set the function for DohExit() to call instead of exit().
 *
 * The registered function can perform clean up, etc.  It should simply
 * return when done and then exit() will get called.  Bear in mind that
 * the handler function can be called after malloc() has failed, so it's
 * a good idea for it to avoid allocating additional memory.
 *
 * The registered handler function is unregistered by DohExit() before calling
 * it to avoid the potential for infinite loops.
 *
 * Note: This is sort of like C's atexit(), only for DohExit().  However
 * only one function can be registered (setting a new function overrides the
 * previous one) and the registered function is passed the exit status so can
 * vary its actions based on that.
 */
extern void DohSetExitHandler(void (*new_handler)(int));
extern void DohExit(int status);

/* -----------------------------------------------------------------------------
 * Strings.
 * ----------------------------------------------------------------------------- */

extern DOHString *DohNewStringEmpty(void);
extern DOHString *DohNewString(const DOHString_or_char *c);
extern DOHString *DohNewStringWithSize(const DOHString_or_char *c, int len);
extern DOHString *DohNewStringf(const DOHString_or_char *fmt, ...);

extern int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2);
extern int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n);
extern char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2);
extern char *DohStrchr(const DOHString_or_char *s1, int ch);

/* String replacement flags */

#define DOH_REPLACE_ANY        0x01
#define DOH_REPLACE_NOQUOTE    0x02
#define DOH_REPLACE_NOCOMMENT  0x04
#define DOH_REPLACE_ID         0x08
#define DOH_REPLACE_FIRST      0x10
#define DOH_REPLACE_ID_BEGIN   0x20
#define DOH_REPLACE_ID_END     0x40
#define DOH_REPLACE_NUMBER_END 0x80

#define Replaceall(s, t, r)    DohReplace(s, t, r, DOH_REPLACE_ANY)
#define Replaceid(s, t, r)     DohReplace(s, t, r, DOH_REPLACE_ID)

/* -----------------------------------------------------------------------------
 * Files
 * ----------------------------------------------------------------------------- */

extern DOHFile *DohNewFile(DOHString *filename, const char *mode, DOHList *outfiles);
extern DOHFile *DohNewFileFromFile(FILE *f);
extern DOHFile *DohNewFileFromFd(int fd);
extern void DohFileErrorDisplay(DOHString *filename);
extern int DohCopyto(DOHFile *input, DOHFile *output);
extern void DohCloseAllOpenFiles(void);

/* -----------------------------------------------------------------------------
 * List
 * ----------------------------------------------------------------------------- */

extern DOHList *DohNewList(void);
extern void DohSortList(DOH *lo, int (*cmp)(const DOH *, const DOH *));

/* -----------------------------------------------------------------------------
 * Hash
 * ----------------------------------------------------------------------------- */

extern DOHHash *DohNewHash(void);

/* -----------------------------------------------------------------------------
 * Void
 * ----------------------------------------------------------------------------- */

extern DOHVoid *DohNewVoid(void *ptr, void (*del)(void *));
extern DOHList *DohSplit(DOHFile *input, char ch, int nsplits);
extern DOHList *DohSplitLines(DOHFile *input);
extern DOH *DohNone;

/* Helper union for converting between function and object pointers. */
typedef union DohFuncPtr {
  void *p;
  DOH *(*func)(DOH *);
} DohFuncPtr_t;

extern void DohMemoryDebug(void);

#ifndef DOH_LONG_NAMES
/* Macros to invoke the above functions.  Includes the location of
   the caller to simplify debugging if something goes wrong */

#define Delete            DohDelete
#define Copy              DohCopy
#define Clear             DohClear
#define Str               DohStr
#define Dump              DohDump
#define Getattr           DohGetattr
#define Setattr           DohSetattr
#define Delattr           DohDelattr
#define Checkattr         DohCheckattr
#define Hashval           DohHashval
#define Getitem           DohGetitem
#define Setitem           DohSetitem
#define Delitem           DohDelitem
#define Insert            DohInsertitem
#define Delslice          DohDelslice
#define Append(s, x)      DohInsertitem(s, DOH_END, x)
#define Push(s, x)        DohInsertitem(s, DOH_BEGIN, x)
#define Len               DohLen
#define Data              DohData
#define Char(X)           ((char *)Data(X))
#define Cmp               DohCmp
#define Equal             DohEqual
#define Setline           DohSetline
#define Getline           DohGetline
#define Setfile           DohSetfile
#define Getfile           DohGetfile
#define Write             DohWrite
#define Read              DohRead
#define Seek              DohSeek
#define Tell              DohTell
#define Printf            DohPrintf
#define Printv            DohPrintv
#define Getc              DohGetc
#define Putc              DohPutc
#define Ungetc            DohUngetc

/* #define StringPutc         DohStringPutc */
/* #define StringGetc         DohStringGetc */
/* #define StringUngetc       DohStringUngetc */
/* #define StringAppend       Append */
/* #define StringLen          DohStringLen */
/* #define StringChar         DohStringChar */
/* #define StringEqual        DohStringEqual */

#define vPrintf           DohvPrintf
#define GetInt            DohGetInt
#define GetDouble         DohGetDouble
#define GetChar           DohGetChar
#define GetVoid           DohGetVoid
#define GetFlagAttr       DohGetFlagAttr
#define GetFlag           DohGetFlag
#define SetInt            DohSetInt
#define SetDouble         DohSetDouble
#define SetChar           DohSetattr
#define SetVoid           DohSetVoid
#define SetFlagAttr       DohSetFlagAttr
#define SetFlag           DohSetFlag
#define UnsetFlag(o, n)   DohSetFlagAttr(o, n, NULL)
#define ClearFlag(o, n)   DohSetFlagAttr(o, n, "")
#define Readline          DohReadline
#define Replace           DohReplace
#define Chop              DohChop
#define Getmeta           DohGetmeta
#define Setmeta           DohSetmeta
#define Delmeta           DohDelmeta
#define NewString         DohNewString
#define NewStringEmpty    DohNewStringEmpty
#define NewStringWithSize DohNewStringWithSize
#define NewStringf        DohNewStringf
#define NewHash           DohNewHash
#define NewList           DohNewList
#define NewFile           DohNewFile
#define NewFileFromFile   DohNewFileFromFile
#define NewFileFromFd     DohNewFileFromFd
#define FileErrorDisplay  DohFileErrorDisplay
#define NewVoid           DohNewVoid
#define Keys              DohKeys
#define SortedKeys        DohSortedKeys
#define Strcmp            DohStrcmp
#define Strncmp           DohStrncmp
#define Strstr            DohStrstr
#define Strchr            DohStrchr
#define Copyto            DohCopyto
#define CloseAllOpenFiles DohCloseAllOpenFiles
#define Split             DohSplit
#define SplitLines        DohSplitLines
#define Setmark           DohSetmark
#define Getmark           DohGetmark
#define SetMaxHashExpand  DohSetMaxHashExpand
#define GetMaxHashExpand  DohGetMaxHashExpand
#define None              DohNone
#define Call              DohCall
#define First             DohFirst
#define Next              DohNext
#define Iterator          DohIterator
#define SortList          DohSortList
#define Malloc            DohMalloc
#define Realloc           DohRealloc
#define Calloc            DohCalloc
#define Free              DohFree
#define SetExitHandler    DohSetExitHandler
#define Exit              DohExit
#endif

#ifdef NIL
#undef NIL
#endif

#define NIL                  (char *)NULL

/* Defines to allow use of poisoned identifiers.
 *
 * For DOH-internal use only!
 */
#define doh_internal_calloc  calloc
#define doh_internal_exit    exit
/* doh_internal_free not needed as Free() is a macro defined above. */
#define doh_internal_malloc  malloc
#define doh_internal_realloc realloc

#if defined __GNUC__ && defined DOH_POISON
/* Use Malloc(), Realloc(), Calloc(), and Free() instead (which will exit with
 * an error rather than return NULL).
 */
#ifndef DOH_NO_POISON_MALLOC_FREE
/* This works around bison's template checking if malloc and free are defined,
 * which triggers GCC's poison checks.
 */
#pragma GCC poison malloc free
#endif
#pragma GCC poison realloc calloc
/* Use Exit() instead (which will remove output files on error). */
#pragma GCC poison abort exit
/* Use snprintf() instead - sprintf() has no bounds checking and is deprecated on some
 * platforms, such as macOS. */
#pragma GCC poison sprintf
#endif

#endif /* SWIG_DOH_H */
