WONKY



LOG | FILES | OVERVIEW


#ifndef WONKY_TOKEN_C
#define WONKY_TOKEN_C WONKY_TOKEN_C
#include <token.h>

struct token* get_small_token(enum LEXER_TYPE type,struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct token_identifier *ret;

	ret=wonky_malloc(sizeof(struct token_identifier));
	ret->type=type;
	ret->delta=get_source_location_delta(previous_location,current_location);

	return (struct token*)ret;
}
struct token* get_id_token(struct identifier *id,struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct token_identifier *ret;
	ret=wonky_malloc(sizeof(struct token_identifier));
	ret->type=KW_ID;
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->id=id;


	return (struct token*)ret;
}
struct token* get_keyword_token(enum LEXER_TYPE type,struct Source_Location *current_location,struct Source_Location *previous_location,struct identifier *id)
{
	struct token_keyword *ret;
	ret=wonky_malloc(sizeof(struct token_keyword));
	ret->type=type;
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->id=id;

	return (struct token*)ret;
}
struct token* get_punctuator_token(enum LEXER_TYPE type,struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct token_punctuator *ret;
	ret=wonky_malloc(sizeof(struct token_punctuator));
	ret->type=type;
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->punctuator_type=PUNCTUATOR_NORMAL;/*TODO*/

	return (struct token*)ret;
}
struct token* get_constant_token(enum LEXER_TYPE bare_type,struct Source_Location *current_location,struct Source_Location *previous_location,char *data,size_t size)
{
	struct token_constant *ret;
	ret=wonky_malloc(sizeof(struct token_constant));
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->type=KW_CONSTANT;

	switch(bare_type)
	{

		case KW_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_hex(data,size,TC_NONE,TSIGN_SIGNED);
			break;
		case KW_DECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_dec(data,size,TC_NONE,TSIGN_SIGNED);
			break;
		case KW_OCTAL_CONSTANT:
			ret->constant=extract_literal_integer_octal(data,size,TC_NONE,TSIGN_SIGNED);
			break;
		case KW_UNSIGNED_DECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_dec(data,size,TC_NONE,TSIGN_UNSIGNED);
			break;
		case KW_UNSIGNED_OCTAL_CONSTANT:
			ret->constant=extract_literal_integer_octal(data,size,TC_NONE,TSIGN_UNSIGNED);
			break;
		case KW_UNSIGNED_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_hex(data,size,TC_NONE,TSIGN_UNSIGNED);
			break;
		case KW_UNSIGNED_LONG_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_hex(data,size,TC_LONG,TSIGN_UNSIGNED);
			break;
		case KW_UNSIGNED_LONG_OCTAL_CONSTANT:
			ret->constant=extract_literal_integer_octal(data,size,TC_LONG,TSIGN_UNSIGNED);
			break;
		case KW_UNSIGNED_LONG_DECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_dec(data,size,TC_LONG,TSIGN_UNSIGNED);
			break;
		case KW_UNSIGNED_LONG_LONG_DECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_dec(data,size,TC_LONG_LONG,TSIGN_UNSIGNED);
			break;
		case KW_UNSIGNED_LONG_LONG_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_hex(data,size,TC_LONG_LONG,TSIGN_UNSIGNED);
			break;
		case KW_UNSIGNED_LONG_LONG_OCTAL_CONSTANT:
			ret->constant=extract_literal_integer_octal(data,size,TC_LONG_LONG,TSIGN_UNSIGNED);
			break;
		case KW_LONG_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_hex(data,size,TC_LONG,TSIGN_SIGNED);
			break;
		case KW_LONG_OCTAL_CONSTANT:
			ret->constant=extract_literal_integer_octal(data,size,TC_LONG,TSIGN_SIGNED);
			break;
		case KW_LONG_DECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_dec(data,size,TC_LONG,TSIGN_SIGNED);
			break;
		case KW_LONG_LONG_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_hex(data,size,TC_LONG_LONG,TSIGN_SIGNED);
			break;
		case KW_LONG_LONG_OCTAL_CONSTANT:
			ret->constant=extract_literal_integer_hex(data,size,TC_LONG_LONG,TSIGN_SIGNED);
			break;
		case KW_LONG_LONG_DECIMAL_CONSTANT:
			ret->constant=extract_literal_integer_dec(data,size,TC_LONG_LONG,TSIGN_SIGNED);
			break;
		case KW_DOUBLE_DECIMAL_CONSTANT:
			ret->constant=extract_literal_double_dec(data,size,TC_NONE);
			break;
		case KW_LONG_DOUBLE_DECIMAL_CONSTANT:
			ret->constant=extract_literal_double_dec(data,size,TC_LONG);
			break;
		case KW_FLOAT_DECIMAL_CONSTANT:
			ret->constant=extract_literal_float_dec(data,size);
			break;
		case KW_DOUBLE_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_double_hex(data,size,TC_NONE);
			break;
		case KW_LONG_DOUBLE_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_double_hex(data,size,TC_LONG);
			break;
		case KW_FLOAT_HEXADECIMAL_CONSTANT:
			ret->constant=extract_literal_float_hex(data,size);
			break;
		case KW_CHAR_CONSTANT:
			ret->constant=extract_literal_char(data,size);
			break;
		case KW_WIDE_CHAR_CONSTANT:
			ret->constant=extract_literal_wide_char(data,size);
			break;
		default:
			wonky_assert(SHOULD_NOT_REACH_HERE);
	}

	return (struct token*)ret;
}
struct token* get_constant_long_long_int_token(struct Source_Location *current_location,struct Source_Location *previous_location,long long int number)
{
	struct token_constant *ret;
	ret=wonky_malloc(sizeof(struct token_constant));
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->type=KW_CONSTANT;
	ret->constant=get_long_long_int_constant(number);
	return (struct token*)ret;
}
struct token* get_string_token(enum LEXER_TYPE bare_type,struct Source_Location *current_location,struct Source_Location *previous_location,char *data,size_t size)
{
	struct token_string *ret;	
	ret=wonky_malloc(sizeof(struct token_string));
	ret->type=bare_type;
	ret->delta=get_source_location_delta(previous_location,current_location);
	
	if(bare_type==KW_STRING)
	{
		ret->constant=extract_literal_string(data,size);
	}else if(bare_type==KW_WIDE_STRING)
	{
		ret->constant=extract_literal_wide_string(data,size);
	}else
	{
		wonky_assert(SHOULD_NOT_REACH_HERE);
	}

	return (struct token*)ret;
}
struct token* get_include_directive_token(struct Source_Location *current_location,struct Source_Location *previous_location,struct Queue *tokens)
{
	struct token_include_directive *ret;
	ret=wonky_malloc(sizeof(struct token_string));
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->tokens=tokens;
	ret->type=PKW_INCLUDE;
	return (struct token*)ret;
}
struct token* get_hashtag_hashtag_operator(struct Source_Location *current_location,struct Source_Location *previous_location,struct Queue *operands)
{
	struct token_hashtag_hastag_operator *ret;
	ret=wonky_malloc(sizeof(struct token_hashtag_hastag_operator));
	ret->type=PKW_HASHTAG_HASHTAG_OP;
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->operands=operands;

	return (struct token*)ret;
}
struct token* get_error_token(const char *msg,struct Source_Location *current_location,struct Source_Location *previous_location,struct Program *program,...)
{
	struct token_error *ret;
	va_list args;
	struct wonky_str hold_err;

	hold_err=wonky_string_make();

	va_start(args,program);
	wonky_string_vprintf(&hold_err,msg,args);
	va_end(args);

	ret=wonky_malloc(sizeof(struct token_error));
	ret->type=LT_ERROR;
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->error=get_wonky_message(WONKY_MESSAGE_TYPE_ERROR,WONKY_MESSAGE_SOURCE_PREPROCESSING,current_location->line,current_location->column,current_location->src->src_name->name,current_location->src->src_name->name_size,"%s",hold_err.cs);

	return (struct token*)ret;
}
struct token* get_eof_token()
{
	struct token *ret;
	ret=wonky_malloc(sizeof(struct token));
	ret->type=LT_EOF;
	ret->delta=wonky_malloc(sizeof(struct Source_Location_Delta));
	ret->delta->line_offset=0;
	ret->delta->column=0;
	ret->delta->location=&start_of_file;

	return ret;
}
struct token* get_token_from_two_adjacent_strings(struct token_string *first,struct token_string *second)
{
	struct token_string *ret;
	ret=wonky_malloc(sizeof(struct token_string));
	ret->type=KW_STRING;
	ret->delta=first->delta;
	ret->constant=concatenate_string_literals(first->constant,second->constant);

	return (struct token*)ret;
}
struct token* get_token_from_two_strings_with_a_space_between(struct token_string *first,struct token_string *second)
{
	struct token_string *ret;
	ret=wonky_malloc(sizeof(struct token_string));
	ret->type=KW_STRING;
	ret->delta=first->delta;
	ret->constant=concatenate_string_literals_with_space_between(first->constant,second->constant);

	return (struct token*)ret;
}
struct token* get_file_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct token *ret;
	ret=wonky_malloc(sizeof(struct token));
	ret->type=PKW_FILE_MACRO;
	ret->delta=get_source_location_delta(previous_location,current_location);

	return ret;
}

static char *ascdate(const struct tm *timeptr)
{
	static const char mon_name[12][3] = {
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
	};
	static char result[30];

	if(timeptr==NULL || timeptr->tm_mday>=33 || timeptr->tm_mon>=12 || timeptr->tm_year>=9999)
	{
		wonky_assert(SHOULD_NOT_REACH_HERE);
		return "Could not determine the date";
	}

	sprintf(result, "%.3s %s%d %d",
			mon_name[timeptr->tm_mon],
			(timeptr->tm_mday<10?" ":""),
			timeptr->tm_mday,
			1900 + timeptr->tm_year);
	return result;
}
struct token* get_date_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct tm *tm;
	time_t t;
	char *ret;
	size_t size;

	t=time(NULL);

	if((time_t)(-1)==t)
		goto error;

	tm=gmtime(&t);

	if(tm==NULL)
		goto error;


	ret=ascdate(tm);
	size=gstrnlen(ret,27);
	return (struct token*)get_string_token(KW_STRING,current_location,previous_location,ret,size);

error:
	
	return (struct token*)get_string_token(
			KW_STRING,
			current_location,
			current_location,
			"Time could not be determined",
			sizeof("Time could not be determined"));
}
struct token* get_line_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct token *ret;
	ret=wonky_malloc(sizeof(struct token));
	ret->type=PKW_LINE_MACRO;
	ret->delta=get_source_location_delta(previous_location,current_location);;

	return ret;
}
struct token* get_stdc_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct token *ret;
	ret=wonky_malloc(sizeof(struct token));
	ret->type=PKW_STDC_MACRO;
	ret->delta=get_source_location_delta(previous_location,current_location);;

	return ret;
}
struct token* get_stdc_hosted_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct token *ret;
	ret=wonky_malloc(sizeof(struct token));
	ret->type=PKW_STDC_HOSTED_MACRO;
	ret->delta=get_source_location_delta(previous_location,current_location);;

	return ret;
}
struct token* get_stdc_version_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct token *ret;
	ret=wonky_malloc(sizeof(struct token));
	ret->type=PKW_STDC_VERSION_MACRO;
	ret->delta=get_source_location_delta(previous_location,current_location);;

	return ret;
}
static char *asctime_for_macro(const struct tm *timeptr)
{
	static char result[30];

	if(timeptr==NULL || timeptr->tm_hour>24 || timeptr->tm_sec>60 || timeptr->tm_min>60)
	{
		wonky_assert(SHOULD_NOT_REACH_HERE);
		return "Could not determine the date";
	}

	sprintf(result, "%.2d:%.2d:%.2d",
			timeptr->tm_hour,
			timeptr->tm_min,
			timeptr->tm_sec
	       );
	return result;
}
struct token* get_time_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
	struct tm *tm;
	time_t t;
	char *ret;
	size_t size;

	t=time(NULL);

	if((time_t)(-1)==t)
		goto error;

	tm=gmtime(&t);

	if(tm==NULL)
		goto error;


	ret=asctime_for_macro(tm);
	size=gstrnlen(ret,27);
	return (struct token*)get_string_token(
			KW_STRING,
			current_location,
			previous_location,
			ret,size);

error:
	
	return (struct token*)get_string_token(KW_STRING,current_location,current_location,"Time could not be determined",sizeof("Time could not be determined"));
}
char* get_string_from_token(struct token* token,size_t *size)
{
	char *ret;

	if(token->type==KW_ID)
	{
		ret=((struct token_identifier*)token)->id->data;
		*size=((struct token_identifier*)token)->id->size;
	}else if(token_is_keyword(token))
	{
		ret=((struct token_keyword*)token)->id->data;
		*size=((struct token_keyword*)token)->id->size;
	}else if(token->type==KW_CONSTANT)
	{
		ret=="constant";
		*size=sizeof("constant")-1;
	}else
	{
		#warning hack
		ret=(char*)lexer_type_to_string_map[token->type]; 
		if(ret==NULL) ret="";
		*size=gstrnlen(ret,100);
	}
	return ret;
}
void delete_token(struct token* token)
{
	wonky_free(token);
}
_Bool token_is_keyword(struct token *token)
{
	switch(token->type)
	{
			case KW_AUTO:
			case KW_DO:
			case KW_DOUBLE:
			case KW_INT:
			case KW_STRUCT:
			case KW_BREAK:
			case KW_ELSE:
			case KW_LONG:
			case KW_SWITCH:
			case KW_CASE:
			case KW_ENUM:
			case KW_REGISTER:
			case KW_TYPEDEF:
			case KW_CHAR:
			case KW_EXTERN:
			case KW_RETURN:
			case KW_UNION:
			case KW_CONST:
			case KW_FLOAT:
			case KW_SHORT:
			case KW_UNSIGNED:
			case KW_CONTINUE:
			case KW_FOR:
			case KW_SIGNED:
			case KW_VOID:
			case KW_DEFAULT:
			case KW_GOTO:
			case KW_SIZEOF:
			case KW_VOLATILE:
			case KW_IF:
			case KW_STATIC:
			case KW_WHILE:
			case KW_INLINE:
			case KW_RESTRICT:
			case KW_BOOL:
			case KW_COMPLEX:
			case KW_IMAGINARY:
				return 1;
			default:
				return 0;

	}

}
struct token* get_normal_define_directive_token(struct Source_Location *current_location,struct Source_Location *previous_location,struct identifier *id)
{
	struct token_normal_define_directive *ret;
	ret=wonky_malloc(sizeof(struct token_normal_define_directive));
	ret->type=PKW_DEFINE;
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->define=get_normal_define_directive(id);

	return (struct token*)ret;
}
struct token* get_functionlike_define_directive_token(struct Source_Location *current_location,struct Source_Location *previous_location,struct identifier *id)
{
	struct token_functionlike_define_directive *ret;

	ret->type=PKW_FUNCTIONLIKE_DEFINE;
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->define=get_functionlike_define_directive(id);

	return (struct token*)ret;
}
struct token* get_functionlike_define_directive_argument_token(struct Source_Location *current_location,struct Source_Location *previous_location,struct functionlike_define_directive_argument *argument)
{
	struct token_functionlike_define_argument *ret;	
	ret=wonky_malloc(sizeof(struct token_functionlike_define_argument));
	ret->type=PKW_MACRO_ARGUMENT;
	ret->delta=get_source_location_delta(previous_location,current_location);
	ret->argument=argument;


	return (struct token*)ret;

}
_Bool token_is_identifier_in_preprocessing(struct token *token)
{
	wonky_assert(token!=NULL);
	return token->type==KW_ID || token_is_a_special_macro(token) || token_is_keyword(token);
}
_Bool token_is_a_special_macro(struct token *token)
{
	enum LEXER_TYPE type;

	wonky_assert(token!=NULL);

	type=token->type;
	return type==PKW_FILE_MACRO || type==PKW_DATE_MACRO || type==PKW_LINE_MACRO || type==PKW_STDC_MACRO || type==PKW_STDC_HOSTED_MACRO || type==PKW_STDC_VERSION_MACRO ||
		type==PKW_TIME_MACRO;
}
_Bool token_is_a_macro(struct token *token,size_t translation_unit_number)
{
	wonky_assert(token!=NULL);

	if(token->type==KW_ID)
		return id_is_a_macro(((struct token_identifier*)token)->id,translation_unit_number);
	else if(token_is_keyword(token))
		return id_is_a_macro(((struct token_keyword*)token)->id,translation_unit_number);
	else
		return token_is_a_special_macro(token) || token_is_keyword(token);
}
#endif