MEGATRON



LOG | FILES | OVERVIEW


#ifndef AST_TO_C_C
#define AST_TO_C_C AST_TO_C_C
#include <ast_to_c.h>
#include <print.h>

void ast_to_c(char *output_name,struct AST_Translation_Unit *tree,struct Options *options)
{
	size_t output_name_length;
	char *hold_name;
	FILE *hold_out;

	if(output_name!=NULL)
	{
		output_name_length=strnlen(output_name,1000);

		hold_name=calloc(output_name_length+100,1);
		memcpy(hold_name,output_name,output_name_length);

		memcpy(hold_name+output_name_length,".h",sizeof(".h"));
		hold_out=fopen(hold_name,"w");
			ast_translation_unit_to_c_print_header_part(hold_out,output_name,(struct AST_Translation_Unit*)tree,options);
		fclose(hold_out);

		memcpy(hold_name+output_name_length,".c",sizeof(".c"));
		hold_out=fopen(hold_name,"w");
			ast_translation_unit_to_c_print_body_part(hold_out,output_name,(struct AST_Translation_Unit*)tree,options);
		fclose(hold_out);

		memcpy(hold_name+output_name_length,"_external.h",sizeof("_external.h"));
		hold_out=fopen(hold_name,"w");
			ast_translation_unit_to_c_print_external_part(hold_out,output_name,(struct AST_Translation_Unit*)tree,options);
		fclose(hold_out);

		free(hold_name);

	}else
	{
		ast_translation_unit_to_c_print_external_part(stdout,NULL,(struct AST_Translation_Unit*)tree,options);
		ast_translation_unit_to_c_print_header_part(stdout,NULL,(struct AST_Translation_Unit*)tree,options);
		ast_translation_unit_to_c_print_body_part(stdout,NULL,(struct AST_Translation_Unit*)tree,options);
	}

}
void ast_translation_unit_to_c_print_base_name(FILE *out, char *base_name)
{
	size_t i;
	for(i=0;i<1000 && base_name[i]!='\0';++i)
		fprintf(out,"%c",toupper(base_name[i]));
}
void ast_translation_unit_to_c_print_header_string(FILE *out,char *base_name,char *file_suffix)
{
	fprintf(out,"#ifndef ");
	ast_translation_unit_to_c_print_base_name(out,base_name);
	fprintf(out,"%s\n#define ",file_suffix);
	ast_translation_unit_to_c_print_base_name(out,base_name);
	fprintf(out,"%s ",file_suffix);
	ast_translation_unit_to_c_print_base_name(out,base_name);
	fprintf(out,"%s\n",file_suffix);
}
void ast_translation_unit_to_c_print_footer_string(FILE *out,char *base_name,char *file_suffix)
{
	fprintf(out,"\n#endif //#ifndef ");
	ast_translation_unit_to_c_print_base_name(out,base_name);
	fprintf(out,"%s",file_suffix);
}
void ast_translation_unit_to_c_print_header_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options)
{
	size_t i;
	if(base_name)
	{
		ast_translation_unit_to_c_print_header_string(out,base_name,"_H");
		fprintf(out,"#include<stdlib.h>\n\n");
	}

	ast_to_c_print_internal_stuff_for_header(out,translation_unit,options);

	for(i=0;i<translation_unit->number_of_machines;++i)
		ast_machine_to_c_make_header_part(out,translation_unit->machines[i],options);


	if(base_name)
		ast_translation_unit_to_c_print_footer_string(out,base_name,"_H");
}
void ast_translation_unit_to_c_print_body_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options)
{
	size_t i;

	if(base_name)
	{
		ast_translation_unit_to_c_print_header_string(out,base_name,"_C");
		fprintf(out,"#include \"%s.h\"\n",base_name);
		fprintf(out,"#include \"%s_external.h\"\n\n",base_name);
	}

	ast_to_c_print_internal_stuff_for_body(out,translation_unit,options);
	for(i=0;i<translation_unit->number_of_machines;++i)
		ast_machine_to_c_make_body_part(out,translation_unit->machines[i],options);


	if(base_name)
		ast_translation_unit_to_c_print_footer_string(out,base_name,"_C");
}
void ast_translation_unit_to_c_print_external_part(FILE *out,char *base_name,struct AST_Translation_Unit *translation_unit,struct Options *options)
{
	if(base_name)
	{
		ast_translation_unit_to_c_print_header_string(out,base_name,"_EXTERNAL_H");
		fprintf(out,"#include \"%s.h\"\n\n",base_name);
	}

	if(options->providing_own_queue_implementation)
	{
		if(options->has_context)
		{
			fprintf(out,	"extern void machine_push_to_event_queue(machine_conotext_t *context, machine_buffer_t *input,int event,enum MACHINES_ENUM target_machine);\n");
			fprintf(out,	"extern void machine_pop_from__event_queue(machine_context_t *context);\n");
		}else
		{
			fprintf(out,	"extern void machine_push_to_global_event_queue(machine_buffer_t *input,int event,enum MACHINES_ENUM target_machine);\n");
			fprintf(out,	"extern void machine_pop_from_global_event_queue();\n");
			fprintf(out, 	"extern struct machine_queue_t machine_queue_global;\n");
		}
	}
	if(options->providing_own_buffer_implementation)
	{
		fprintf(out,	"//extern machine_buffer_t* get_machine_buffer(void *content,size_t size);\n");
		fprintf(out,	"\nextern void delete_machine_buffer(machine_buffer_t *buffer);\n");
	}
	if(options->has_mutex)
	{
		fprintf(out,	"extern void machine_mutex_lock(machine_buffer_t *input,int event, enum MACHINES_ENUM target_machine); \n");
		fprintf(out,	"extern void machine_mutex_unlock(int event, enum MACHINES_ENUM target_machine); \n");
	}
	Map_Map_Extended(translation_unit->used_commands_map,(void (*)(void*,void*))ast_command_to_c_extern_declaration,out);

	if(base_name)
	{
		ast_translation_unit_to_c_print_footer_string(out,base_name,"_EXTERNAL_H");
	}
}
void ast_machine_to_c(FILE *out,struct AST_Machine *machine,struct Options *options)
{

	assert(out!=NULL && machine!=NULL && machine->type==AST_TYPE_MACHINE);


	ast_machine_to_c_make_header_part(out,machine,options);
	ast_machine_to_c_make_body_part(out,machine,options);

}
void ast_machine_to_c_make_body_part(FILE *out,struct AST_Machine *machine,struct Options *options)
{
	size_t i;
	struct State_And_Transitions **table;

	table=extract_transition_table(machine->states,machine->transitions);

	for(i=0;i<machine->states->number_of_states;++i)
	{
		ast_state_to_c_signature(out,machine,machine->states->states[i],options);
		fprintf(out,"\n{\n");
		ast_transitions_of_state_to_c(out,machine,table[i],options);
		fprintf(out,"\n}\n");
	}
}
void ast_machine_to_c_make_header_part(FILE *out,struct AST_Machine *machine,struct Options *options)
{
	ast_events_to_c(out,machine,options);
	ast_states_to_c(out,machine,options);
}
void ast_events_to_c(FILE *out,struct AST_Machine *machine,struct Options *options)
{
	size_t i;

	assert(out!=NULL && machine!=NULL && machine->type==AST_TYPE_MACHINE);

	fprintf(out,"enum ");
	ast_machine_enum_tag(out,machine);
	fprintf(out,"\n{\n");

	for(i=0;i<machine->events->number_of_events;++i)
	{
		fprintf(out,"\t");
		ast_event_to_c_enum(out,machine,machine->events->events[i]);
		fprintf(out,",\n");
	}
	fprintf(out,"};\n");
}
void ast_states_to_c(FILE *out,struct AST_Machine *machine,struct Options *options)
{
	size_t i;
	assert(out!=NULL && machine!=NULL && machine->type==AST_TYPE_MACHINE);
	for(i=0;i<machine->states->number_of_states;++i)
	{
		fprintf(out,"extern ");
		ast_state_to_c_signature(out,machine,machine->states->states[i],options);
		fprintf(out,";\n");
	}
}
void ast_transitions_of_state_to_c(FILE *out,struct AST_Machine *machine,struct State_And_Transitions *vector,struct Options *options)
{
	size_t i;
	short indentation=3;
	const char *context_arrow="";
	if(options->has_context)
		context_arrow="context->";

	//fprintf(out,"\tmachine_buffer_t *hold_buffer;\n\thold_buffer=input;\n\n");
	
	if(vector->number_of_transitions>0)
	{
		fprintf(out,"\n\t%smachine_states_lock=1;\n\n",context_arrow);
		ast_statement_to_c(out,1,vector->state->on_exit_statement,options);
		fprintf(out,"\n");
		fprintf(out,"\tswitch(event)\n\t{\n");
		for(i=0;i<vector->number_of_transitions;++i)
		{
			fprintf(out,"\t\tcase ");
			ast_event_to_c_enum(out,machine,vector->transitions[i]->event);

			fprintf(out,":\n");
			if(vector->transitions[i]->granted)
			{
				fprintf(out,"\t\t\tif(");
				ast_expression_to_c(out,vector->transitions[i]->granted,options);
				fprintf(out,")\n\t\t\t{\n");
				indentation++;
			}

			//ast_pipeline_to_c(out,3,vector->transitions[i]->pipeline);
			ast_statement_to_c(out,indentation,vector->transitions[i]->statement,options);
			ast_statement_to_c(out,indentation,vector->transitions[i]->to->on_entry_statement,options);
			ast_to_c_print_tabs(out,indentation);
			fprintf(out,"%smachine_states[",context_arrow);
			ast_token_to_c(out,machine->id);
			fprintf(out,"]=");
			ast_state_to_c_function_name(out,machine,vector->transitions[i]->to);
			fprintf(out,";\n");
			ast_to_c_print_tabs(out,indentation);
			fprintf(out,"break;\n");
			if(vector->transitions[i]->granted)
			{
				fprintf(out,"\t\t\t}\n");
			}
		}
		fprintf(out,"\t}\n");
	}
	fprintf(out,"\tdelete_machine_buffer(input);\n");
	fprintf(out,"\n\t%smachine_states_lock=0;\n",context_arrow);

}
/*prints the enum tag for the given machine*/
void ast_machine_enum_tag(FILE *out,struct AST_Machine *machine)
{
	fprintf(out,"MACHINE_");
	ast_token_to_c(out,machine->id);
	fprintf(out,"_EVENTS_ENUM");
}
void ast_state_to_c_signature(FILE *out,struct AST_Machine *machine,struct AST_State *state,struct Options *options)
{
	fprintf(out,"void ");
	ast_state_to_c_function_name(out,machine,state);
	fprintf(out,"(%sint event,machine_buffer_t *input)",(options->has_context?"machine_context_t *context,":""));
}
void ast_token_to_c(FILE *out,struct token *token)
{
	size_t i;

	assert(out!=NULL && token!=NULL);

	for(i=0;i<token->size;++i)
		fprintf(out,"%c",token->data[i]);
}
void ast_pipeline_to_c(FILE *out,size_t indentation,struct AST_Pipeline *pipeline)
{
	size_t i;

	if(pipeline==NULL) return;

	for(i=0;i<pipeline->size;++i)
	{
		ast_to_c_print_tabs(out,indentation);
		fprintf(out,"input=");
		ast_command_to_c(out,pipeline->pipeline[i],"input");
		fprintf(out,";\n");
	}
	//ast_to_c_print_tabs(out,indentation);
}
void ast_command_to_c(FILE *out,struct AST_Command *command,char *hold_buffer)
{
	ast_token_to_c(out,command->function_name);
	fprintf(out,"(");
	if(command->argument==NULL)
		fprintf(out,"NULL");
	else
	{
		fprintf(out,"get_machine_buffer(\"");
		ast_token_to_c(out,command->argument);
		fprintf(out,"\",sizeof(\"");
		ast_token_to_c(out,command->argument);
		fprintf(out,"\"))");
	}
	fprintf(out,",%s)",hold_buffer);
}

void ast_command_to_c_extern_declaration(struct AST_Command *command,FILE *out)
{
	fprintf(out,"extern machine_buffer_t* ");
	ast_token_to_c(out,command->function_name);
	fprintf(out,"(machine_buffer_t *arguments,machine_buffer_t *input);\n");
}
void ast_to_c_print_tabs(FILE *out,size_t number_of_tabs)
{
	size_t i;
	for(i=0;i<number_of_tabs;++i)
		fprintf(out,"\t");
}
void ast_machines_to_c_array(FILE *out,struct AST_Translation_Unit *translation_unit,struct Options *options,short indent)
{
	size_t i;

	ast_to_c_print_tabs(out,indent);
	fprintf(out,"void (*machine_states[%zu])(%sint,machine_buffer_t*)",translation_unit->number_of_machines,(options->has_context?"machine_context_t *context,":""));
	if(options->has_context==0)
	{
		fprintf(out,"={ ");
		for(i=0;i<translation_unit->number_of_machines;++i)
		{
			ast_state_to_c_function_name(out,translation_unit->machines[i],translation_unit->machines[i]->starting_state);
			fprintf(out,",");
		}	
		fprintf(out,"}");
	}
	fprintf(out,";\n");

	ast_to_c_print_tabs(out,indent);
	fprintf(out,"_Bool machine_states_lock");
	if(options->has_context==0)
		fprintf(out,"=0");
	fprintf(out,";\n");
}
void ast_machines_to_c_enum(FILE *out,struct AST_Translation_Unit *translation_unit)
{
	size_t i;
	fprintf(out,"enum MACHINES_ENUM\n{\n");
	for(i=0;i<translation_unit->number_of_machines;++i)
	{
		fprintf(out,"\t");
		ast_token_to_c(out,translation_unit->machines[i]->id);
		fprintf(out,",\n");
	}

	fprintf(out,"\tMACHINES_ENUM_END\n};\n");
}
void ast_state_to_c_function_name(FILE *out,struct AST_Machine *machine,struct AST_State *state)
{
	fprintf(out,"machine_");
	ast_token_to_c(out,machine->id);	
	fprintf(out,"_state_");
	ast_token_to_c(out,state->name);
}
void ast_event_to_c_enum(FILE *out,struct AST_Machine *machine,struct AST_Event *event)
{
	ast_token_to_c(out,machine->id);
	fprintf(out,"_EVENT_");
	ast_token_to_c(out,event->name);
}
void ast_to_c_print_internal_stuff_for_header(FILE *out,struct AST_Translation_Unit *translation_unit,struct Options *options)
{
	fprintf(out,"\n\n");
	ast_machines_to_c_enum(out,translation_unit);
	fprintf(out,"\n\n");


	if(options->providing_own_buffer_implementation)
	{
		fprintf(out,"typedef struct machine_buffer_t machine_buffer_t;\n");
	}else
	{
		ast_print_machine_buffer_declarations(out);
	}

	if(!options->providing_own_queue_implementation)
		ast_to_c_print_event_struct_queue_declaration(out,options);
	
	/*the context struct should go here*/
	if(options->has_context)
	{
		fprintf(out,"typedef struct machine_context_s machine_context_t;\n");
		fprintf(out, "struct machine_context_s\n{\n");
		ast_machines_to_c_array(out,translation_unit,options,1);
		fprintf(out,"\tstruct machine_queue_t machine_queue;\n");
		fprintf(out, "};\n\n");
		fprintf(out, "void machine_context_init(machine_context_t *context);\n");
		fprintf(out, "void machine_context_destroy(machine_context_t *context);\n");

	}
	ast_to_c_print_event_functions_queue_declaration(out,options);


	ast_to_c_print_comment(out,	"\tuse this function to pass an event to a machine\n"
					"\tthe input buffer is passed to the first executed function if any\n"
					"\tany remaining buffer after the pipeline has finished is passed\n"
					"\tto the delete_machine_buffer function\n"
					"\tinput can be NULL"

			);
	if(options->has_context)
		fprintf(out,"extern void push_event_to_machine(machine_context_t *context,enum MACHINES_ENUM machine,int event,machine_buffer_t *input);\n\n");
	else
		fprintf(out,"extern void push_event_to_machine(enum MACHINES_ENUM machine,int event,machine_buffer_t *input);\n\n");





}
void ast_to_c_print_internal_stuff_for_body(FILE *out,struct AST_Translation_Unit *translation_unit,struct Options *options)
{
	const char *context_arrow="";
	const char *context_comma="";
	const char *context="";
	const char *global="_global";

	if(options->has_context==0)
	{
		ast_machines_to_c_array(out,translation_unit,options,0);
		fprintf(out,"struct machine_queue_t machine_queue_global = { .first=NULL,.last=NULL,.size=0};\n");
	}else
	{
		size_t which_machine;

		context_comma="context,";
		context="context";
		context_arrow="context->";
		global="";
		fprintf(out, "void machine_context_init(machine_context_t *context)\n{\n\tcontext->machine_queue=(struct machine_queue_t){ .first=NULL,.last=NULL,.size=0};\n");
		fprintf(out, "\tcontext->machine_states_lock=0;\n");
		for(which_machine=0;which_machine<translation_unit->number_of_machines;++which_machine)
		{
			fprintf(out,"\tcontext->machine_states[%zu]=",which_machine);
			ast_state_to_c_function_name(out,translation_unit->machines[which_machine],translation_unit->machines[which_machine]->starting_state);
			fprintf(out,";\n");
		}
		fprintf(out,"\n}\n");
		fprintf(out,	"void machine_context_destroy(machine_context_t *context)\n{\n\t"
				"\tstruct machine_queue_node_t *hold_node;\n"
				"\thold_node=context->machine_queue.first;\n"
				"\twhile(hold_node!=NULL)\n"
				"\t{\n"
				"\t\tcontext->machine_queue.first=context->machine_queue.first->prev;\n"
				"\t\tfree(hold_node);\n"
				"\t\thold_node=context->machine_queue.first;\n"
				"\t}\n"
				"\n}\n"	
				);

	}
	if(!options->providing_own_queue_implementation)
		ast_to_c_print_event_queue_definition(out,options);
	if(!options->providing_own_buffer_implementation)
		ast_print_machine_buffer_definitions(out);

	if(options->has_context)
		fprintf(out,"void push_event_to_machine(machine_context_t *context,enum MACHINES_ENUM machine,int event,machine_buffer_t *input)\n");
	else
		fprintf(out,"void push_event_to_machine(enum MACHINES_ENUM machine,int event,machine_buffer_t *input)\n");

	fprintf(out, "{\n"	
			"\tif(machine<MACHINES_ENUM_END)"	
			"\n\t{"	
	       );
	if(options->has_mutex)
		fprintf(out,"\t\tmachine_mutex_lock(input,event,machine);\n");
	fprintf(out,
			"\n\t\tif(%smachine_states_lock)"
			"\n\t\t{"
				"\n\t\t\tmachine_push_to%s_event_queue(%sinput,event,machine);"
			"\n\t\t}else"
			"\n\t\t{"
			"\n\t\t\t%smachine_states[machine](%sevent,input);"	
			"\n\t\t\twhile(%smachine_queue%s.size>0)machine_pop_from%s_event_queue(%s);"
			"\n\t\t}"
			"\n\t}"	
			,context_arrow,global,context_comma,context_arrow,(options->has_context?"context,":""),context_arrow,global,global,context
	       );
	if(options->has_mutex)
		fprintf(out,"\t\tmachine_mutex_unlock(event,machine);\n");
	fprintf(out,
			"\n}\n"	
		);

}
void ast_to_c_print_comment(FILE *out,char *comment)
{
	fprintf(out,"/*\n");
	fprintf(out,"%s\n",comment);
	fprintf(out,"*/\n");
}
void ast_statement_to_c(FILE *out,size_t indentation,struct AST *statement,struct Options *options)
{
	if(statement==NULL)return;
	if(statement->type==AST_TYPE_PIPELINE)
		ast_pipeline_to_c(out,indentation,(struct AST_Pipeline*)statement);
	else if(statement->type==AST_TYPE_IF)
		ast_if_to_c(out,indentation,(struct AST_If_Statement*)statement,options);
	else
		assert(0);

}
void ast_if_to_c(FILE *out,size_t indentation,struct AST_If_Statement *statement,struct Options *options)
{
	ast_to_c_print_tabs(out,indentation);
	fprintf(out,"if");
	ast_expression_to_c(out,statement->condition,options);
	fprintf(out,"\n");

	ast_to_c_print_tabs(out,indentation);
	fprintf(out,"{\n");

		ast_statement_to_c(out,indentation+1,statement->body,options);

	ast_to_c_print_tabs(out,indentation);
	fprintf(out,"}");
	if(statement->else_statement)
	{
		fprintf(out,"else{\n");

		ast_statement_to_c(out,indentation+1,statement->else_statement,options);

		ast_to_c_print_tabs(out,indentation);
		fprintf(out,"}");
	}
	fprintf(out,"\n");
}
void ast_expression_to_c(FILE *out,struct AST *expression,struct Options *options)
{
	fprintf(out,"(");	
	switch(expression->type)
	{
		case AST_TYPE_OP_OR:
			ast_expression_to_c(out,AS_BIN_EXPR_PTR(expression)->left,options);
			fprintf(out,"||");
			ast_expression_to_c(out,AS_BIN_EXPR_PTR(expression)->right,options);
			break;
		case AST_TYPE_OP_NOT:
			fprintf(out,"!");
			ast_expression_to_c(out,AS_UN_EXPR_PTR(expression)->operand,options);
			break;
		case AST_TYPE_OP_AND:
			ast_expression_to_c(out,AS_BIN_EXPR_PTR(expression)->left,options);
			fprintf(out,"&&");
			ast_expression_to_c(out,AS_BIN_EXPR_PTR(expression)->right,options);
			break;
		case AST_TYPE_STATE:
			ast_expression_state_to_c(out,(struct AST_State*)expression,options);
			break;
		case AST_TYPE_OP_SELECTOR:
			assert(!"selector in final product!\n");
		default:
			assert(0);
	}
	fprintf(out,")");	
}
void ast_expression_state_to_c(FILE *out,struct AST_State *state,struct Options *options)
{
	fprintf(out,"%smachine_states[",(options->has_context?"context->":""));
	ast_token_to_c(out,state->parent->id);
	fprintf(out,"]==");
	ast_state_to_c_function_name(out,state->parent,state);

}
void ast_to_c_print_event_struct_queue_declaration(FILE *out,struct Options *options)
{
	const char *queue="global_event_queue";
	ast_to_c_print_comment(out,	"\tthis queue is used when an event is received for a machine that is\n"
					"\tcurrently in transit\n"
					"\tdoes not guarantee any thread safety,\n"
					"\tbut preserves intuitive order of execution\n"
					"\tdo not use these manually"
			);
	fprintf(out,	"struct machine_queue_node_t\n"
			"{\n"	
			"\tstruct machine_queue_node_t *prev;\n"
			"\tmachine_buffer_t *input;\n"
			"\tint event;\n"
			"\tenum MACHINES_ENUM target_machine;\n"
			"};\n"	
			);
	fprintf(out,	"struct machine_queue_t\n"
			"{\n"
			"\tstruct machine_queue_node_t *first,*last;\n"
			"\tsize_t size;\n"
			"};\n"
	       );
}
void ast_to_c_print_event_functions_queue_declaration(FILE *out,struct Options *options)
{
	const char *queue="global_event_queue";
	if(options->has_context)
		queue="event_queue";
	fprintf(out,	"extern void machine_push_to_%s(",queue);
	if(options->has_context)
		fprintf(out,"machine_context_t *context,");
	fprintf(out,"machine_buffer_t *input,int event,enum MACHINES_ENUM target_machine);\n");
	fprintf(out,"extern void machine_pop_from_%s(",queue);
	if(options->has_context)
		fprintf(out,"machine_context_t *context");
	fprintf(out,");\n");
}
void ast_to_c_print_event_queue_definition(FILE *out,struct Options *options)
{
	const char *queue="machine_queue_global";
	const char *machines_stuff="";

	fprintf(out,	"void machine_push_to_");
	if(options->has_context)
	{
		fprintf(out,"event_queue(machine_context_t *context,");
		queue="context->machine_queue";
		machines_stuff="context->";
	}else
	{
		fprintf(out,"global_event_queue(");
	}

	fprintf(out,	"machine_buffer_t *input,int event,enum MACHINES_ENUM target_machine)\n"
			"{\n"	
			"\tif(%s.size==0)\n"	
			"\t{\n"
				"\t\t%s.first=%s.last=malloc(sizeof(struct machine_queue_node_t));\n"
				"\t\t%s.last->input=input;\n"
				"\t\t%s.last->event=event;\n"
				"\t\t%s.last->target_machine=target_machine;\n"
				"\t\t%s.size=1;\n"
			"\t}else\n"
			"\t{\n"
				"\t\t%s.last=%s.last->prev=malloc(sizeof(struct machine_queue_node_t));\n"
				"\t\t%s.last->input=input;\n"
				"\t\t%s.last->event=event;\n"
				"\t\t%s.last->target_machine=target_machine;\n"
				"\t\t++%s.size;\n"
			"\t}\n"
			"}\n",queue,queue,queue,queue,queue,queue,queue,queue,queue,queue,queue,queue,queue,queue,queue
			);

	fprintf(out,	"void machine_pop_from");
	if(options->has_context)
	{
		fprintf(out,"_event_queue(machine_context_t *context)\n");
	}else
	{
		fprintf(out,"_global_event_queue()\n");
	}
	fprintf(out,	"{\n"		
			"\tstruct machine_queue_node_t *hold_node;\n"
				"\thold_node=%s.first;\n"
				"\t%s.first=%s.first->prev;\n"
				"\tif(--%s.size==0)\n"
					"\t\t%s.last=NULL;\n"
				"\t%smachine_states[hold_node->target_machine](%shold_node->event,hold_node->input);\n"
				"\tfree(hold_node);\n"
			"}\n",queue,queue,queue,queue,queue,machines_stuff,(options->has_context?"context,":"")
			);
}
void ast_print_machine_buffer_declarations(FILE *out)
{
	ast_to_c_print_comment(out,"\tthis is the structure that facilitates data exchange");
	fprintf(out,"typedef struct machine_buffer_t \n{"
		       "\n\tsize_t size;\n\tunsigned char buffer[];\n} machine_buffer_t;\n\n");

	ast_to_c_print_comment(out,	"\tthis function creates a buffer structure in the heap\n"
					"\tit COPIES the contents of content \n"	
					"\tsize is in bytes"
			);

	fprintf(out,"extern machine_buffer_t* get_machine_buffer(void *content,size_t size);\n\n");
	ast_to_c_print_comment(out,"\tfrees the buffer from the heap");
	fprintf(out,"extern void delete_machine_buffer(machine_buffer_t *buffer);\n\n");
}
void ast_print_machine_buffer_definitions(FILE *out)
{
	fprintf(out,	"machine_buffer_t* get_machine_buffer(void *content,size_t size)\n"
			"{\n"
			"\tmachine_buffer_t *ret;\n"
			"\tsize_t i;\n"
			"\t\n"
			"\tret=malloc(sizeof(machine_buffer_t)+size);\n"
			"\tret->size=size;\n"
			"\tfor(i=0;i<size;++i)\n"
			"\t\tret->buffer[i]=((unsigned char*)content)[i];\n"
			"\treturn ret;\n"
			"}\n");

	fprintf(out,	"\nvoid delete_machine_buffer(machine_buffer_t *buffer)\n"
			"{\n"
			"\tif(buffer)\n"
			"\t{\n"
			"\t\tfree(buffer);\n"
			"\t}\n}\n"
			);
}
#endif