/* Generated by re2c 0.5 on Thu Oct  4 11:24:04 2001 */
#line 1 "ircg_scanner.re"
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2002 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.02 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available at through the world-wide-web at                           |
   | http://www.php.net/license/2_02.txt.                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Sascha Schumann <sascha@schumann.cx>                         |
   +----------------------------------------------------------------------+
 */

/* $Id: ircg_scanner.c,v 1.19 2002/02/28 08:26:18 sebastian Exp $ */

#include <ext/standard/php_smart_str.h>
#include <stdio.h>
#include <string.h>

static const char *color_list[] = {
    "white",
    "black",
    "blue",
    "green",
    "red",
    "brown",
    "purple",
    "orange",
    "yellow",
    "lightgreen",
    "teal",
    "lightcyan",
    "lightblue",
    "pink",
    "gray",
    "lightgrey"
};


enum {
	STATE_PLAIN,
	STATE_URL,
	STATE_COLOR_FG,
	STATE_COLOR_COMMA,
	STATE_COLOR_BG
};

typedef struct {
	int bg_code;
	int fg_code;
	int font_tag_open;
	int bold_tag_open;
	int underline_tag_open;
	int italic_tag_open;
	
	smart_str scheme;
	smart_str *result;
} ircg_msg_scanner;

#line 79


#define YYFILL(n) do { } while (0)
#define YYCTYPE unsigned char
#define YYCURSOR xp
#define YYLIMIT end
#define YYMARKER q

#define STD_PARA ircg_msg_scanner *ctx, const char *start, const char *YYCURSOR
#define STD_ARGS ctx, start, YYCURSOR

static inline void passthru(STD_PARA)
{
	smart_str_appendl_ex(ctx->result, start, YYCURSOR - start, 1);
}

static inline void handle_scheme(STD_PARA)
{
	ctx->scheme.len = 0;
	smart_str_appendl_ex(&ctx->scheme, start, YYCURSOR - start, 1);
	smart_str_0(&ctx->scheme);
}

static inline void handle_url(STD_PARA)
{
	smart_str_appends_ex(ctx->result, "<a target=blank href=\"", 1);
	smart_str_append_ex(ctx->result, &ctx->scheme, 1);
	smart_str_appendl_ex(ctx->result, start, YYCURSOR - start, 1);
	smart_str_appends_ex(ctx->result, "\">", 1);
	smart_str_append_ex(ctx->result, &ctx->scheme, 1);
	smart_str_appendl_ex(ctx->result, start, YYCURSOR - start, 1);
	smart_str_appends_ex(ctx->result, "</a>", 1);
}

static void handle_color_digit(STD_PARA, int mode)
{
	int len;
	int nr;

	len = YYCURSOR - start;
	switch (len) {
		case 2:
			nr = (start[0] - '0') * 10 + (start[1] - '0');
			break;
		case 1:
			nr = start[0] - '0';
			break;
	}
	
	switch (mode) {
		case 0: ctx->fg_code = nr; break;
		case 1: ctx->bg_code = nr; break;
	}
}

#define IS_VALID_CODE(n) (n >= 0 && n <= 15)

static void finish_color_stuff(STD_PARA)
{
	if (ctx->font_tag_open) {
		smart_str_appends_ex(ctx->result, "</font>", 1);
		ctx->font_tag_open = 0;
	}
}

static void handle_bold(STD_PARA, int final)
{
	switch (ctx->bold_tag_open) {
	case 0:
		if (!final) smart_str_appends_ex(ctx->result, "<b>", 1);
		break;
	case 1:
		smart_str_appends_ex(ctx->result, "</b>", 1);
		break;
	}

	ctx->bold_tag_open = 1 - ctx->bold_tag_open;
}

static void handle_underline(STD_PARA, int final)
{
	switch (ctx->underline_tag_open) {
	case 0:
		if (!final) smart_str_appends_ex(ctx->result, "<u>", 1);
		break;
	case 1:
		smart_str_appends_ex(ctx->result, "</u>", 1);
		break;
	}

	ctx->underline_tag_open = 1 - ctx->underline_tag_open;
}

static void handle_italic(STD_PARA, int final)
{
	switch (ctx->italic_tag_open) {
	case 0:
		if (!final) smart_str_appends_ex(ctx->result, "<i>", 1);
		break;
	case 1:
		smart_str_appends_ex(ctx->result, "</i>", 1);
		break;
	}

	ctx->italic_tag_open = 1 - ctx->italic_tag_open;
}

static void commit_color_stuff(STD_PARA)
{
	finish_color_stuff(STD_ARGS);

	if (IS_VALID_CODE(ctx->fg_code)) {
		smart_str_appends_ex(ctx->result, "<font color=\"", 1);
		smart_str_appends_ex(ctx->result, color_list[ctx->fg_code], 1);
		smart_str_appends_ex(ctx->result, "\">", 1);
		ctx->font_tag_open = 1;
	}
}

static void add_entity(STD_PARA, const char *entity)
{
	smart_str_appends_ex(ctx->result, entity, 1);
}

void ircg_mirc_color(const char *msg, smart_str *result, size_t msg_len, int auto_links, int gen_br) 
{
	const char *end, *xp, *q, *start;
	ircg_msg_scanner mctx, *ctx = &mctx;

	mctx.result = result;
	mctx.scheme.c = NULL;
	mctx.italic_tag_open = mctx.font_tag_open = mctx.bold_tag_open = mctx.underline_tag_open = 0;
	
	if (msg_len == -1)
		msg_len = strlen(msg);
	end = msg + msg_len;
	xp = msg;
	

state_plain:
	if (xp >= end) goto stop;
	start = YYCURSOR;
{
	YYCTYPE yych;
	unsigned int yyaccept;
	static unsigned char yybm[] = {
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128,   0,   0,   0,   0,   0,   0, 
	  0, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128,   0,   0,   0,   0,   0, 
	  0, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	};
	goto yy0;
yy1:	++YYCURSOR;
yy0:
	if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
	yych = *YYCURSOR;
	if(yych <= ';'){
		if(yych <= '\026'){
			if(yych <= '\002'){
				if(yych <= '\000')	goto yy2;
				if(yych <= '\001')	goto yy23;
				goto yy17;
			} else {
				if(yych <= '\003')	goto yy5;
				if(yych <= '\025')	goto yy23;
				goto yy21;
			}
		} else {
			if(yych <= '\037'){
				if(yych <= '\035')	goto yy23;
				if(yych <= '\036')	goto yy15;
				goto yy19;
			} else {
				if(yych == '&')	goto yy11;
				goto yy23;
			}
		}
	} else {
		if(yych <= '`'){
			if(yych <= '>'){
				if(yych <= '<')	goto yy7;
				if(yych <= '=')	goto yy23;
				goto yy9;
			} else {
				if(yych <= '@')	goto yy23;
				if(yych <= 'Z')	goto yy3;
				goto yy23;
			}
		} else {
			if(yych <= '\204'){
				if(yych <= 'z')	goto yy3;
				if(yych <= '\203')	goto yy23;
				goto yy13;
			} else {
				if(yych <= '\222')	goto yy23;
				if(yych <= '\224')	goto yy13;
				goto yy23;
			}
		}
	}
yy2:	YYCURSOR = YYMARKER;
	switch(yyaccept){
	case 0:	goto yy4;
	}
yy3:	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if(yych <= '@'){
		if(yych <= '/')	goto yy4;
		if(yych <= ':')	goto yy25;
	} else {
		if(yych <= 'Z')	goto yy25;
		if(yych <= '`')	goto yy4;
		if(yych <= 'z')	goto yy25;
	}
yy4:
#line 232
	{ passthru(STD_ARGS); goto state_plain; }
yy5:	yych = *++YYCURSOR;
yy6:
#line 223
	{ mctx.fg_code = mctx.bg_code = -1; goto state_color_fg; }
yy7:	yych = *++YYCURSOR;
yy8:
#line 224
	{ add_entity(STD_ARGS, "&lt;"); goto state_plain; }
yy9:	yych = *++YYCURSOR;
yy10:
#line 225
	{ add_entity(STD_ARGS, "&gt;"); goto state_plain; }
yy11:	yych = *++YYCURSOR;
yy12:
#line 226
	{ add_entity(STD_ARGS, "&amp;"); goto state_plain; }
yy13:	yych = *++YYCURSOR;
yy14:
#line 227
	{ add_entity(STD_ARGS, "&quot;"); goto state_plain; }
yy15:	yych = *++YYCURSOR;
yy16:
#line 228
	{ if (gen_br) smart_str_appendl_ex(ctx->result, "<br>", 4, 1); goto state_plain; }
yy17:	yych = *++YYCURSOR;
yy18:
#line 229
	{ handle_bold(STD_ARGS, 0); goto state_plain; }
yy19:	yych = *++YYCURSOR;
yy20:
#line 230
	{ handle_underline(STD_ARGS, 0); goto state_plain; }
yy21:	yych = *++YYCURSOR;
yy22:
#line 231
	{ handle_italic(STD_ARGS, 0); goto state_plain; }
yy23:	yych = *++YYCURSOR;
	goto yy4;
yy24:	++YYCURSOR;
	if(YYLIMIT == YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
yy25:	if(yybm[0+yych] & 128)	goto yy24;
	if(yych != ':')	goto yy2;
yy26:	yych = *++YYCURSOR;
	if(yych != '/')	goto yy2;
yy27:	yych = *++YYCURSOR;
	if(yych != '/')	goto yy2;
yy28:	yych = *++YYCURSOR;
yy29:
#line 222
	{ if (auto_links) { handle_scheme(STD_ARGS); goto state_url; } else { passthru(STD_ARGS); goto state_plain; } }
}
#line 233


state_url:		
	start = YYCURSOR;
{
	YYCTYPE yych;
	unsigned int yyaccept;
	static unsigned char yybm[] = {
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0, 128,   0, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128,   0, 128,   0, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128,   0,   0,   0,   0, 128, 
	  0, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128, 128, 128, 128, 128, 128, 
	128, 128, 128,   0,   0,   0, 128,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	  0,   0,   0,   0,   0,   0,   0,   0, 
	};
	goto yy30;
yy31:	++YYCURSOR;
yy30:
	if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if(yych <= '>'){
		if(yych <= '"'){
			if(yych != '!')	goto yy34;
		} else {
			if(yych == '<')	goto yy34;
			if(yych >= '>')	goto yy34;
		}
	} else {
		if(yych <= '`'){
			if(yych <= 'Z')	goto yy32;
			if(yych != '_')	goto yy34;
		} else {
			if(yych <= 'z')	goto yy32;
			if(yych != '~')	goto yy34;
		}
	}
yy32:	yych = *++YYCURSOR;
	goto yy37;
yy33:
#line 238
	{ handle_url(STD_ARGS); goto state_plain; }
yy34:	yych = *++YYCURSOR;
yy35:
#line 239
	{ passthru(STD_ARGS); goto state_plain; }
yy36:	++YYCURSOR;
	if(YYLIMIT == YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
yy37:	if(yybm[0+yych] & 128)	goto yy36;
	goto yy33;
}
#line 240



state_color_fg:		
	start = YYCURSOR;
{
	YYCTYPE yych;
	unsigned int yyaccept;
	goto yy38;
yy39:	++YYCURSOR;
yy38:
	if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if(yych <= '/')	goto yy42;
	if(yych >= ':')	goto yy42;
yy40:	yych = *++YYCURSOR;
	if(yych <= '/')	goto yy41;
	if(yych <= '9')	goto yy44;
yy41:
#line 246
	{ handle_color_digit(STD_ARGS, 0); goto state_color_comma; }
yy42:	yych = *++YYCURSOR;
yy43:
#line 247
	{ finish_color_stuff(STD_ARGS); passthru(STD_ARGS); goto state_plain; }
yy44:	yych = *++YYCURSOR;
	goto yy41;
}
#line 248


		
state_color_comma:	
	start = YYCURSOR;
{
	YYCTYPE yych;
	unsigned int yyaccept;
	goto yy45;
yy46:	++YYCURSOR;
yy45:
	if(YYLIMIT == YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if(yych != ',')	goto yy49;
yy47:	yych = *++YYCURSOR;
yy48:
#line 254
	{ goto state_color_bg; }
yy49:	yych = *++YYCURSOR;
yy50:
#line 255
	{ YYCURSOR--; commit_color_stuff(STD_ARGS); goto state_plain; }
}
#line 256



state_color_bg:
	start = YYCURSOR;
{
	YYCTYPE yych;
	unsigned int yyaccept;
	goto yy51;
yy52:	++YYCURSOR;
yy51:
	if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if(yych <= '/')	goto yy55;
	if(yych >= ':')	goto yy55;
yy53:	yych = *++YYCURSOR;
	if(yych <= '/')	goto yy54;
	if(yych <= '9')	goto yy57;
yy54:
#line 262
	{ handle_color_digit(STD_ARGS, 1); commit_color_stuff(STD_ARGS); goto state_plain; }
yy55:	yych = *++YYCURSOR;
yy56:
#line 263
	{ commit_color_stuff(STD_ARGS); goto state_plain; }
yy57:	yych = *++YYCURSOR;
	goto yy54;
}
#line 264


stop:
	smart_str_free_ex(&ctx->scheme, 1);

	finish_color_stuff(STD_ARGS);
	handle_bold(STD_ARGS, 1);
	handle_underline(STD_ARGS, 1);
	handle_italic(STD_ARGS, 1);
}
