/* Generated by re2c 0.5 on Tue Jan 28 15:32:52 2003 */
#line 1 "ircg_scanner.re"
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 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.1.1.4 2003/07/18 18:07:34 zarzycki 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;
	goto yy0;
yy1:	++YYCURSOR;
yy0:
	if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
	yych = *YYCURSOR;
	switch(yych){
	case '\000':	goto yy2;
	case '\002':	goto yy17;
	case '\003':	goto yy5;
	case '\026':	goto yy21;
	case '\036':	goto yy15;
	case '\037':	goto yy19;
	case '&':	goto yy11;
	case '<':	goto yy7;
	case '>':	goto yy9;
	case 'A':
	case 'B':
	case 'C':
	case 'D':
	case 'E':
	case 'F':
	case 'G':
	case 'H':
	case 'I':
	case 'J':
	case 'K':
	case 'L':
	case 'M':
	case 'N':
	case 'O':
	case 'P':
	case 'Q':
	case 'R':
	case 'S':
	case 'T':
	case 'U':
	case 'V':
	case 'W':
	case 'X':
	case 'Y':
	case 'Z':	case 'a':
	case 'b':
	case 'c':
	case 'd':
	case 'e':
	case 'f':
	case 'g':
	case 'h':
	case 'i':
	case 'j':
	case 'k':
	case 'l':
	case 'm':
	case 'n':
	case 'o':
	case 'p':
	case 'q':
	case 'r':
	case 's':
	case 't':
	case 'u':
	case 'v':
	case 'w':
	case 'x':
	case 'y':
	case 'z':	goto yy3;
	case '\204':	case '\223':
	case '\224':	goto yy13;
	default:	goto yy23;
	}
yy2:	YYCURSOR = YYMARKER;
	switch(yyaccept){
	case 0:	goto yy4;
	}
yy3:	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	switch(yych){
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	case ':':	case 'A':
	case 'B':
	case 'C':
	case 'D':
	case 'E':
	case 'F':
	case 'G':
	case 'H':
	case 'I':
	case 'J':
	case 'K':
	case 'L':
	case 'M':
	case 'N':
	case 'O':
	case 'P':
	case 'Q':
	case 'R':
	case 'S':
	case 'T':
	case 'U':
	case 'V':
	case 'W':
	case 'X':
	case 'Y':
	case 'Z':	case 'a':
	case 'b':
	case 'c':
	case 'd':
	case 'e':
	case 'f':
	case 'g':
	case 'h':
	case 'i':
	case 'j':
	case 'k':
	case 'l':
	case 'm':
	case 'n':
	case 'o':
	case 'p':
	case 'q':
	case 'r':
	case 's':
	case 't':
	case 'u':
	case 'v':
	case 'w':
	case 'x':
	case 'y':
	case 'z':	goto yy25;
	default:	goto yy4;
	}
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:	switch(yych){
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':	case 'A':
	case 'B':
	case 'C':
	case 'D':
	case 'E':
	case 'F':
	case 'G':
	case 'H':
	case 'I':
	case 'J':
	case 'K':
	case 'L':
	case 'M':
	case 'N':
	case 'O':
	case 'P':
	case 'Q':
	case 'R':
	case 'S':
	case 'T':
	case 'U':
	case 'V':
	case 'W':
	case 'X':
	case 'Y':
	case 'Z':	case 'a':
	case 'b':
	case 'c':
	case 'd':
	case 'e':
	case 'f':
	case 'g':
	case 'h':
	case 'i':
	case 'j':
	case 'k':
	case 'l':
	case 'm':
	case 'n':
	case 'o':
	case 'p':
	case 'q':
	case 'r':
	case 's':
	case 't':
	case 'u':
	case 'v':
	case 'w':
	case 'x':
	case 'y':
	case 'z':	goto yy24;
	case ':':	goto yy26;
	default:	goto yy2;
	}
yy26:	yych = *++YYCURSOR;
	switch(yych){
	case '/':	goto yy27;
	default:	goto yy2;
	}
yy27:	yych = *++YYCURSOR;
	switch(yych){
	case '/':	goto yy28;
	default:	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;
	goto yy30;
yy31:	++YYCURSOR;
yy30:
	if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	switch(yych){
	case '!':	case '#':
	case '$':
	case '%':
	case '&':
	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case '-':
	case '.':
	case '/':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	case ':':
	case ';':	case '=':	case '?':
	case '@':
	case 'A':
	case 'B':
	case 'C':
	case 'D':
	case 'E':
	case 'F':
	case 'G':
	case 'H':
	case 'I':
	case 'J':
	case 'K':
	case 'L':
	case 'M':
	case 'N':
	case 'O':
	case 'P':
	case 'Q':
	case 'R':
	case 'S':
	case 'T':
	case 'U':
	case 'V':
	case 'W':
	case 'X':
	case 'Y':
	case 'Z':	case '_':	case 'a':
	case 'b':
	case 'c':
	case 'd':
	case 'e':
	case 'f':
	case 'g':
	case 'h':
	case 'i':
	case 'j':
	case 'k':
	case 'l':
	case 'm':
	case 'n':
	case 'o':
	case 'p':
	case 'q':
	case 'r':
	case 's':
	case 't':
	case 'u':
	case 'v':
	case 'w':
	case 'x':
	case 'y':
	case 'z':	case '~':	goto yy32;
	default:	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:	switch(yych){
	case '!':	case '#':
	case '$':
	case '%':
	case '&':
	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case '-':
	case '.':
	case '/':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	case ':':
	case ';':	case '=':	case '?':
	case '@':
	case 'A':
	case 'B':
	case 'C':
	case 'D':
	case 'E':
	case 'F':
	case 'G':
	case 'H':
	case 'I':
	case 'J':
	case 'K':
	case 'L':
	case 'M':
	case 'N':
	case 'O':
	case 'P':
	case 'Q':
	case 'R':
	case 'S':
	case 'T':
	case 'U':
	case 'V':
	case 'W':
	case 'X':
	case 'Y':
	case 'Z':	case '_':	case 'a':
	case 'b':
	case 'c':
	case 'd':
	case 'e':
	case 'f':
	case 'g':
	case 'h':
	case 'i':
	case 'j':
	case 'k':
	case 'l':
	case 'm':
	case 'n':
	case 'o':
	case 'p':
	case 'q':
	case 'r':
	case 's':
	case 't':
	case 'u':
	case 'v':
	case 'w':
	case 'x':
	case 'y':
	case 'z':	case '~':	goto yy36;
	default:	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;
	switch(yych){
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':	goto yy40;
	default:	goto yy42;
	}
yy40:	yych = *++YYCURSOR;
	switch(yych){
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':	goto yy44;
	default:	goto yy41;
	}
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;
	switch(yych){
	case ',':	goto yy47;
	default:	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;
	switch(yych){
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':	goto yy53;
	default:	goto yy55;
	}
yy53:	yych = *++YYCURSOR;
	switch(yych){
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':	goto yy57;
	default:	goto yy54;
	}
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);
}
