/*
 * Copyright (c) 2002, Douwe Kiela All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * - Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 
 * - Neither name of author nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific
 * prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <asm2html.h>

int
is_ok(char c)
{
	if (isalpha(c) || (c == '%') || (c == '_'))
		return 1;
	else
		return 0;
}

int
process_line(FILE * fp, char *string)
{

	char           *reg[] = {
		"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
		"ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
		"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
		"es", "cs", "ss", "ds", "fs", "gs",
		"st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7",
		"mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
		"cr0", "cr2", "cr3", "cr4",
		"dr0", "dr1", "dr2", "dr3", "dr6", "dr7",
	"tr3", "tr4", "tr5", "tr6", "tr7"};

	char           *predicate[] = {
		"eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord"
	};
	char           *statusflag[] = {
		"cf", "pf", "af", "zf", "sf", "of"
	};
	char           *instruction[] = {
		"aaa", "aas", "aad", "aam",
		"adc", "add", "addpd", "addps", "addsd", "addss",
		"and", "andnpd", "andnps", "andpd", "andps",
		"arpl", "bound", "bsf", "bsr", "bswap",
		"bt", "btc", "btr", "bts", "call",
		"cbw", "cwd", "cdq", "cwde", "clc", "cld", "cli", "clts",
		"clflush", "cmc", "cmp", "cmpsb", "cmpsw", "cmpsd",
		"cmpexchg", "cmpexchg486", "cmpexchg8b", "comisd",
		"comiss", "cpuid",
		"cvtdq2pd", "cvtdq2ps", "cvtpd2pq", "cvtpd2pi", "cvtpd2ps",
		"cvtpi2pd", "cvtpi2ps", "cvtps2dq", "cvtps2pd", "cvtps2pi",
		"cvtsd2si", "cvtsd2ss", "cvtsi2sd", "cvtsi2ss", "cvtss2sd",
		"cvtss2si", "cvttpd2dq", "cvttpd2pi", "cvttps2dq", "cvttps2pi",
		"cvttsd2si",
		"daa", "das", "dec", "div", "divpd", "divps", "divsd", "divss",
		"emms", "enter", "f2xm1", "fabs", "fadd", "faddp",
		"fbld", "fbstp", "fchs", "fclex", "enclex", "fcmov",
		"fcom", "fcomp", "fcompp", "fcomi", "fcomip", "fcos",
		"fdecstp", "fdisi", "fndisi", "feni", "fneni",
		"fdiv", "fdivp", "fdivr", "fdivrp", "femms", "ffree",
		"fiadd", "ficom", "ficomp", "fidiv", "fidivr", "fild",
		"fist", "fistp", "fimul", "fincstp", "finit", "fninit",
		"fisub", "fld", "fldcw", "fldenv", "fmul", "fmulp", "fnop",
		"fpatan", "fptan", "fprem", "fprem1", "frndint",
		"fsave", "frstor", "fscale", "fsetpm", "fsin", "fsincos",
		"fsqrt", "fst", "fstp", "fstvw", "fstenv", "fstsw", "fsub",
		"fsubp", "fsubr", "fsubrp", "ftst", "fxam", "fxch",
		"fxrstor", "fxsave", "fxtract", "fyl2x", "fyl2xp1",
		"hlt", "ibts", "idiv", "imul", "in", "inc", "insb",
		"insw", "insd", "int", "int3", "int1", "icebp", "int01",
		"int0", "invd", "invlpg", "iret", "iretw", "iretd",
		"jcc", "jcxz", "jecxz", "jmp", "lahf", "lar", "ldmxcsr",
		"lds", "les", "lfs", "lgs", "lss", "lea", "leave", "lfence",
		"lgdt", "lidt", "lldt", "lmsw", "loadall", "loadall286",
		"lodsb", "lodsw", "lodsd", "loop", "loope", "loopz", "loopne",
		"loopnz", "lsl", "ltr", "maskmovdqu", "masmovq", "maxpd",
		"maxps", "maxsd", "maxss", "mfence", "minpd", "minps", "minsd",
		"minss", "mov", "movapd", "movars", "movd", "movdq2q", "movdqa",
		"movdqu", "movhlps", "movhpd", "movhps", "movlhps", "movlpd",
		"movlps", "movmskpd", "movmskps", "movntdq", "movnti", "mvntpd",
		"movntps", "movntq", "movq", "movq2dq", "movsb", "movsw", "movsd",
		"movss", "movsx", "movzx", "movupd", "movups", "mul", "mulpd",
		"mulps", "mulsd", "mulss", "neg", "not", "nop",
		"or", "orpd", "orps", "out", "outsb", "outsw", "outsd",
		"packssdw", "packsswb", "packuswb", "paddb", "paddw", "paddd",
		"paddq", "paddsb", "paddsw", "paddsiw", "paddusb", "paddusw",
		"pand", "pandn", "pause", "paveb", "pavgb", "pavgw", "pavgusb",
		"pcmp", "pdistib", "pextrw", "pf2id", "pf2iw", "pfacc", "pfadd",
		"pfcmp", "pfmax", "pfmin", "pfmul", "pfnacc", "pfpnacc", "pfrcp",
		"pfrcpit1", "pfrcpit2", "pfrsqit1", "pfrsqrt", "pfsub", "pfsubr",
		"pi2fd", "pf2iw", "pinsrw", "pmachriw", "pmaddwd", "pmagw", "pmaxsw",
		"pmaxub", "pminsw", "pminub", "pmovmskb", "pmulhrwc",
		"pmulhriq", "pmulhrwa", "pmulhuw", "pmulhq", "pmullw", "pmuludq",
		"pmv", "pop", "popa", "popf", "por", "prefetch", "psadbw",
		"pshufhw", "pshuflw", "pshufw", "psll", "psra", "psrl", "psub",
		"psubs", "psubus", "psubsiw", "pswapd", "punpck", "push", "pusha",
		"pushf", "pxor", "rcl", "rcr", "rcpps", "rcpss", "rdmsr", "rdpmc",
		"rdshr", "rdtsc", "ret", "retf", "retn", "rol", "ror", "rsdc", "rsldt",
		"rsm", "rsqrtps", "rsqrtss", "rsts", "sahf", "sal", "sar", "salc", "sbb",
		"scasb", "scasw", "scasd", "set", "sfence", "sgdt", "sidt", "sldt",
		"shl", "shr", "shld", "shrd", "shufpd", "shufps", "smi", "smint",
		"smintold", "smsw", "sqrtpd", "sqrtps", "sqrtsd", "sqrtss",
		"stc", "std", "sti", "stmxcsr", "stosb", "stosw", "stosd",
		"str", "sub", "subpd", "subps", "subsd", "subss", "svdc",
		"svldt", "svts", "syscall", "sysenter", "sysexit", "sysret",
		"test", "ucomisd", "ucomiss", "ud0", "ud1", "ud2",
		"umov", "unpckhpd", "unpckhps", "unpcklps", "verr", "verw",
		"wait", "wbinvd", "wrmsr", "wrshr", "xadd", "xbts", "xchg",
		"xlatb", "xor", "xorpd", "xorps", "jc", "jz", "je", "jnc", "jnz", "jne", "js",
		"struc", "endstruc", "istruc", "ath", "iend", "align", "alignb"
	};

	char           *pseudo[] = {
		"db", "dw", "dd", "dq", "dt", "resb", "resw", "resq", "equ", "incbin", "times", "strict"
	};

	char           *directive[] = {
		"bits", "use16", "use32", "section", "segment", "__sect__", "absolute", "extern", "global",
		"common", "cpu", "org"
	};

	char           *preprocessor[] = {
		"%define", "%xdefine", "%undef", "%assign", "%strlen", "%substr", "%macro", "%0", "%rotate",
		"%ifdef", "%ifmacro", "%ifctx", "%if", "%ifidn", "%ifidni", "%ifid", "%ifnum", "%ifstr", "%error",
		"%push", "%pop", "%repl", "%include", "%arg", "%stacksize", "%local", "%line"
	};

	char           *macro[] = {
		"__NASM_MAJOR__", "__NASM_MINOR__", "__NASM_SUBMINOR__", "NASM_PATCHLEVEL__",
		"__NASM_VERSION_ID__", "__NASM_VER__", "__FILE__", "__LINE__"
	};

	char           *section[] = {
		".bss", ".code", ".text", ".data"
	};

	char           *keyword[] = {
		"word", "dword", "byte", "far", "short", "long", "near"
	};

	char            buf[4096];
	int             len, i;

	len = strlen(string);

	bzero(buf, 4096);

	for (i = 0; i <= len; i++) {
		if (string[i] != ' ')
			//we filter out spaces
		{
			buf[i] = string[i];
		}
	}
	buf[strlen(buf) + 1] = '\0';

	for (i = 0; i <= 62; i++) {
		if (!strcasecmp(buf, reg[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_REGISTER, buf);
			return 0;
		}
	}

	for (i = 0; i <= 9; i++) {
		if (!strcasecmp(buf, predicate[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_PREDICATE, buf);
			return 0;
		}
	}


	for (i = 0; i <= 7; i++) {
		if (!strcasecmp(buf, statusflag[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_STATUSFLAG, buf);
			return 0;
		}
	}

	for (i = 0; i <= (sizeof(instruction) / sizeof(char *)); i++) {
		if (!strcasecmp(buf, instruction[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_INSTRUCTION, buf);
			return 0;
		}
	}

	for (i = 0; i <= (sizeof(pseudo) / sizeof(char *)); i++) {
		if (!strcasecmp(buf, pseudo[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_PSEUDO, buf);
			return 0;
		}
	}

	for (i = 0; i <= (sizeof(directive) / sizeof(char *)); i++) {
		if (!strcasecmp(buf, directive[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_DIRECTIVE, buf);
			return 0;
		}
	}

	for (i = 0; i <= (sizeof(preprocessor) / sizeof(char *)); i++) {
		if (!strcasecmp(buf, preprocessor[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_PREPROCESSOR, buf);
			return 0;
		}
	}

	for (i = 0; i <= (sizeof(macro) / sizeof(char *)); i++) {
		if (!strcasecmp(buf, macro[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_MACRO, buf);
			return 0;
		}
	}

	for (i = 0; i <= (sizeof(section) / sizeof(char *)); i++) {
		if (!strcasecmp(buf, section[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_SECTION, buf);
			return 0;
		}
	}

	for (i = 0; i <= (sizeof(keyword) / sizeof(char *)); i++) {
		if (!strcasecmp(buf, keyword[i])) {
			fprintf(fp, "<b><font color=\"%s\">%s</font></b>", CLR_KEYWORD, buf);
			return 0;
		}
	}


	fprintf(fp, string);

	return 0;
}
