/*
 * Copyright (C) 2018 Red Hat, Inc. (www.redhat.com)
 *
 * This library is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation.
 *
 * This library 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 Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

#include "evolution-data-server-config.h"

#include <stdio.h>

#define CHARS_LWSP	" \t\n\r"
#define CHARS_TSPECIAL	"()<>@,;:\\\"/[]?="
#define CHARS_SPECIAL	"()<>@,;:\\\".[]"
#define CHARS_CSPECIAL	"()\\\r"		/* not in comments */
#define CHARS_DSPECIAL	"[]\\\r \t"		/* not in domains */
#define CHARS_ATTRCHAR	"*\'% "			/* extra non-included attribute-chars */

enum {
	CAMEL_MIME_IS_CTRL	= 1 << 0,
	CAMEL_MIME_IS_LWSP	= 1 << 1,
	CAMEL_MIME_IS_TSPECIAL	= 1 << 2,
	CAMEL_MIME_IS_SPECIAL	= 1 << 3,
	CAMEL_MIME_IS_SPACE	= 1 << 4,
	CAMEL_MIME_IS_DSPECIAL	= 1 << 5,
	CAMEL_MIME_IS_QPSAFE	= 1 << 6,
	CAMEL_MIME_IS_ESAFE	= 1 << 7, /* encoded word safe */
	CAMEL_MIME_IS_PSAFE	= 1 << 8, /* encoded word in phrase safe */
	CAMEL_MIME_IS_ATTRCHAR	= 1 << 9  /* attribute-char safe (rfc2184) */
};

/* set bit in character positions */
static void
add_bits (unsigned short table[256],
	  unsigned short bit,
	  const char *chars)
{
	while (*chars) {
		unsigned short pos = (unsigned short) (*chars);
		table[pos] |= bit;
		chars++;
	}
}

/* remove bit in character positions */
static void
rem_bits (unsigned short table[256],
	  unsigned short bit,
	  const char *chars)
{
	while (*chars) {
		unsigned short pos = (unsigned short) (*chars);
		table[pos] = (table[pos]) & (~bit);
		chars++;
	}
}

int
main (int argc,
      char *argv[])
{
	unsigned short table[256];
	int ii;

	/* set up base ranges */
	for (ii = 0; ii < 256; ii++) {
		table[ii] = 0;
		if (ii < 32 || ii == 127) {
			table[ii] |= CAMEL_MIME_IS_CTRL | CAMEL_MIME_IS_TSPECIAL;
		} else if (ii < 127) {
			table[ii] |= CAMEL_MIME_IS_ATTRCHAR;
		}
		if ((ii >= 32 && ii <= 60) || (ii >= 62 && ii <= 126) || ii == 9) {
			table[ii] |= CAMEL_MIME_IS_QPSAFE | CAMEL_MIME_IS_ESAFE;
		}
		if ((ii >= 0x30 && ii <= 0x39) || (ii >= 0x61 && ii <= 0x7a) || (ii >= 0x41 && ii <= 0x5a)) {
			table[ii] |= CAMEL_MIME_IS_PSAFE;
		}
	}

	table[0x20] |= CAMEL_MIME_IS_SPACE;

	add_bits (table, CAMEL_MIME_IS_LWSP, CHARS_LWSP);
	add_bits (table, CAMEL_MIME_IS_TSPECIAL, CHARS_TSPECIAL);
	add_bits (table, CAMEL_MIME_IS_SPECIAL, CHARS_SPECIAL);
	/* not in domains */
	add_bits (table, CAMEL_MIME_IS_DSPECIAL, CHARS_DSPECIAL);

	/* list of characters that must be encoded.
	 * encoded word in text specials: rfc 2047 5(1) */
	rem_bits (table, CAMEL_MIME_IS_ESAFE, "()<>@,;:\"/[]?.=_");

	/* non-included attribute-chars (tspecial + extra) */
	rem_bits (table, CAMEL_MIME_IS_ATTRCHAR, CHARS_ATTRCHAR CHARS_TSPECIAL);

	/* list of additional characters that can be left unencoded.
	 * encoded word in phrase specials: rfc 2047 5(3) */
	add_bits (table, CAMEL_MIME_IS_PSAFE, "!*+-/");

	/* output */
	printf ("/* This file is generated by camel-gen-tables. DO NOT EDIT */\n\n");
	printf ("const unsigned short camel_mime_special_table[256] = {\n\t");
	for (ii = 0; ii < 256; ii++) {
		printf ("0x%04x,", table[ii]);
		if ((ii & 0x7) == 0x7) {
			printf ("\n");
			if (ii != 0xff) {
				printf ("\t");
			}
		} else {
			printf (" ");
		}
	}
	printf ("};\n");

	return 0;
}
