#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