/* %Z%%M% %I% %E% */

/*
 * Copyright (c) 1990, 1991, 1992, 1993, 1995 by Wayne C. Gramlich.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * for any purpose is hereby granted without fee provided that the above
 * copyright notice and this permission are retained.  The author makes
 * no representations about the suitability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 */

#ifndef FILE_DEFS_H
#include "file_defs.h"
#endif

#ifndef LINT_H
#include "lint.h"
#endif

#ifndef TOKEN_DEFS_H
#include "token_defs.h"
#endif

#ifdef UNUSED
/*
 * token_equal(token1, token2)
 *	This routine will return 1 if "token1" equals "token2"; otherwise
 *	0 is returned.
 */
int
token_equal(
	Token		token1,
	Token		token2)
{
	if (token1->type != token2->type) {
		return 0;
	}
	switch (token1->type) {
	    case Token_type_integer:
		return (token1->value.integer == token2->value.integer);
	    case Token_type_symbol:
		return (strcmp(token1->value.symbol,
			       token2->value.symbol) == 0);
	    case Token_type_string:
		return (strcmp(token1->value.string,
			       token2->value.string) == 0);
	    case Token_type_text:
		return (strcmp(token1->value.text,
			       token2->value.text) == 0);
	    default:
		return 1;
	}
}

/*
 * token_hash(token)
 *	This routine will return a hash value for "token".
 */
int
token_hash(
	Token		token)
{
	switch (token->type) {
	    case Token_type_integer:
		return token->value.integer;
	    case Token_type_symbol:
		return strhash(token->value.symbol);
	    case Token_type_string:
		return strhash(token->value.string);
	    case Token_type_text:
		return strhash(token->value.text);
	    default:
		return (int)token->type;
	}
}

/*
 * token_read(in_file, heap)
 *	This routine will read read in a token from "in_file" allocated from
 *	"heap".
 */
/* VARARGS2 */
Token
token_read(
	Stdio		in_file,
	Heap		heap)
{
	Token		token;

	token = heap_allocate(heap, Token);
	token->type = Token_type_symbol;
	token->value.symbol = strread(in_file, heap);
	token->position = -1;
	return token;
}

/*
 * token_unparse(token, heap)
 *	This routine will return string version of "token".
 */
Str
token_unparse(
	Token		token,
	Heap		heap)
{
	char		chr;
	int		index;
	char		quote;
	int		size;
	String		string;
	Str		text;
	static Strvec	unparse = (Strvec)0;

	strvec_print(unparse, "[pos:%d line:%d col:%d] ", token->position,
		      token->line_number, token->line_column);
	switch (token->type) {
	    case Token_type_add:
		return "+";
	    case Token_type_add_assign:
		return ":+="
	    case Token_type_add_result:
		return "::+=";
	    case Token_type_and:
		return "&";
	    case Token_type_and_assign:
		return ":&=";
	    case Token_type_and_if:
		return "&&";
	    case Token_type_and_result:
		return "::&=";
	    case Token_type_at:
		return "@";
	    case Token_type_at_parenthesis:
		return "@(";
	    case Token_type_assign:
		return ":=";
	    case Token_type_colon:
		return ":";
	    case Token_type_comma:
		return ",";
	    case Token_type_decrement:
		return "--";
	    case Token_type_define:
		return "::";
	    case Token_type_define_assign:
		return ":@=";
	    case Token_type_define_result:
		return "::@=";
	    case Token_type_dot:
		return ".";
	    case Token_type_divide:
		return "/";
	    case Token_type_divide_assign:
		return ":/=";
	    case Token_type_divide_result:
		return "::/=";
	    case Token_type_eol:
		return "End-of-line";
	    case Token_type_equal:
		return "=";
	    case Token_type_greater_than:
		return ">";
	    case Token_type_greater_than_or_equal:
		return ">=";
	    case Token_type_identical:
		return "==";
	    case Token_type_increment:
		return "++";
	    case Token_type_integer:
		return strprintf(heap, "Integer: %d", token->value.integer);
	    case Token_type_if:
		return "?";
	    case Token_type_left_bracket:
		return "[";
	    case Token_type_left_paren:
		return "(";
	    case Token_type_left_shift:
		return "<<";
	    case Token_type_left_shift_assign:
		return ":<<=";
	    case Token_type_left_shift_result:
		return "::<<=";
	    case Token_type_less_than:
		return "<";
	    case Token_type_less_than_or_equal:
		return "<=";
	    case Token_type_not:
		return "!";
	    case Token_type_not_equal:
		return "!=";
	    case Token_type_multiply:
		return "*";
	    case Token_type_multiply_assign:
		return ":*=";
	    case Token_type_multiply_result:
		return "::*=";
	    case Token_type_or:
		return "|";
	    case Token_type_or_assign:
		return ":|=";
	    case Token_type_or_if:
		return "||";
	    case Token_type_or_result:
		return "::|=";
	    case Token_type_power:
		return "**";
	    case Token_type_power_assign:
		return ":**=";
	    case Token_type_power_result:
		return "::**=";
	    case Token_type_remainder:
		return "%";
	    case Token_type_remainder_assign:
		return ":%=";
	    case Token_type_remainder_result:
		return "::%=";
	    case Token_type_right_bracket:
		return "]";
	    case Token_type_right_paren:
		return ")";
	    case Token_type_right_shift:
		return ">>";
	    case Token_type_right_shift_assign:
		return ":>>=";
	    case Token_type_right_shift_result:
		return "::>>=";
	    case Token_type_result:
		return "::=";
	    case Token_type_string:
		quote = '"';
		string = token->value.string;
		goto unparse_string;
	    case Token_type_subtract:
		return "-";
	    case Token_type_subtract_assign:
		return ":-=";
	    case Token_type_subtract_result:
		return "::-=";
	    case Token_type_symbol:
		return strprintf(heap, "Symbol: %s", token->value.symbol);
	    case Token_type_text:
		quote = '\'';
		string = token->value.text;
	unparse_string:
		if (unparse == (Strvec)0) {
			unparse = strvec_create(heap);
		} else {
			strvec_trim(unparse, 0);
		}
		string_chr_append(unparse, quote);
		size = strlen(string);
		text = string;
		for (index = 0; index < size; index++) {
			char	buffer[20];

			chr = text[index];
			switch (chr) {
			    case '\t':
				(void)strcpy(buffer, "\\t");
			    case '\n':
				(void)strcpy(buffer, "\\n");
			    case '\\':
				(void)strcpy(buffer, "\\\\");
			    case '\'':
			    case '"':
				if (chr == quote) {
					(void)sprintf(buffer, "\\%c", chr);
				} else {
					(void)sprintf(buffer, "%c", chr);
				}
			    default:
				if (isprint(chr)) {
					(void)sprintf(buffer, "%c", chr);
				} else {
					(void)sprintf(unparse, "\0o3", chr);
				}
			}
			strvec_str_append(unparse, buffer);
		}
		return strvec_str_get(unparse);
	    case Token_type_twiddle:
		return "~";
	    case Token_type_xor:
		return "^";
	    case Token_type_xor_assign:
		return ":^=";
	    case Token_type_xor_result:
		return "::^=";
	    default:
		return "<Unknown>";
	}
	/* NOTREACHED */
}

/*
 * token_write(token, out_file)
 *	This routine will write "token" to "out_file".  0 is always returned.
 */
/* VARARGS2 */
int
token_write(
	Token		token,
	Stdio		out_file)
{
	(void)strwrite(token->value.symbol, out_file);
	return 0;
}
#endif /* UNUSED */
