/* Copyright (C) 2006-2007 G.P. Halkes
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3, as
   published by the Free Software Foundation.

   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, see <http://www.gnu.org/licenses/>.
*/

#ifndef DEFINITIONS_H
#define DEFINITIONS_H
#include <stdio.h>

#ifdef USE_GETTEXT
#	include <locale.h> 
#	include <libintl.h>
#	define _(String) gettext(String)
#else
#	define _(String) (String)
#endif
#define N_(String) String

#ifdef __GNUC__
void fatal(const char *fmt, ...) __attribute__((format (printf, 1, 2))) __attribute__((noreturn));
#else
/*@noreturn@*/void fatal(const char *fmt, ...);
#endif

#define PANIC() fatal(_("Program logic error at %s:%d\n"), __FILE__, __LINE__)
#define ASSERT(_condition) do { if (!(_condition)) PANIC(); } while(0)

/* Define a bool type if not already defined (C++ and C99 do)*/
#if !(defined(__cplusplus) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 19990601L))
/*@-incondefs@*/
typedef enum {false, true} bool;
/*@+incondefs@*/
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 19990601L
#include <stdbool.h>
#endif

#define TEMPLATE "/tmp/dwdiffXXXXXXXX"
#define TEMPLATE_LENGTH sizeof(TEMPLATE)

typedef struct {
	FILE *file;
	char name[TEMPLATE_LENGTH];
} TempFile;

typedef struct {
	const char *name;
	FILE *input;
	TempFile *tokens;
	TempFile *whitespace;
	int lastPrinted;
} InputFile;

#ifndef DIFF
#	define DIFF "diff"
#endif

#ifdef NO_MINUS_A
#	define MINUS_A ""
#else
#	define MINUS_A " -a"
#endif

#define DIFF_COMMAND DIFF MINUS_A
/* Note: for the case that NO_MINUS_I is declared,
   this one is simply never used */
#define DIFF_COMMAND_CI DIFF_COMMAND " -i"

void doDiff(void);

typedef struct {
	int added,
		deleted,
		oldChanged,
		newChanged,
		oldTotal,
		newTotal;
} Statistics;
extern Statistics statistics;
extern int differences;

int yylex(void);
extern FILE *yyin;


TempFile *tempFile(void);

#define DEFAULT_LINENUMBER_WIDTH 4
#define BITMASK_SIZE 64
struct {
	InputFile oldFile,
		newFile;
	const char *delStart,
		*delStop,
		*addStart,
		*addStop,
		*delColor,
		*addColor;
	size_t delStartLen,
		delStopLen,
		addStartLen,
		addStopLen,
		delColorLen,
		addColorLen;
	char delimiters[BITMASK_SIZE],
		whitespace[BITMASK_SIZE];
	bool printDeleted,
		printAdded,
		printCommon,
		needMarkers,
		needStartStop;
	bool printer,
		less,
		statistics,
		ignoreCase,
		colorMode;
	bool transliterate;
	int whitespaceDelimiter;
	const char *diffOption;
	int lineNumbers;
	bool context;
	int contextLines;
} option;

#define SET_BIT(x, b) do { (x)[(b)>>3] |= 1 << ((b) & 0x7); } while (0);
#define RESET_BIT(x, b) do { (x)[(b)>>3] &= ~(1 << ((b) & 0x7)); } while (0);
#define TEST_BIT(x, b) ((x)[(b)>>3] & (1 << ((b) & 0x7)))

void parseCmdLine(int argc, char *argv[]);

void initContextBuffers(void);
void addchar(char c, bool common);
void printLineNumbers(int oldLineNumber, int newLineNumber);
void writeString(const char *string, size_t bytes);

#endif
