F diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txtinclude_directories(parse)include_directories(semantics)include_directories(lex)+ include_directories(code_generation/js)set(SOURCES main.cparse/parse_declaration.csemantics/scope.csemantics/semantics.csemantics/gcc_error.c+ code_generation/js/transpile_to_js.c)add_executable(wonky ${SOURCES})F diff --git a/README b/README --- a/README +++ b/READMEprints the tokens after preprocessing--print-astprints 'ast' of the program after parsing+ --transpile-to-js || -js+ tries to transpile C code to JS+ --add-html+ Encases resulting JS in simple html+ -o FILENAME+ specifies output filenameF diff --git a/code_generation/js/transpile_to_js.c b/code_generation/js/transpile_to_js.c new file mode 100644 --- /dev/null +++ b/code_generation/js/transpile_to_js.c+ #ifndef GCC_TRANSPILE_TO_JS_C+ #define GCC_TRANSPILE_TO_JS_C GCC_TRANSPILE_TO_JS_C+ #include <transpile_to_js.h>+++ void transpile_to_javascript(FILE* out,struct Program *program,struct Command_Arguments *command_arguments)+ {+ struct Queue_Node *it;++ if(command_arguments->insert_html)+ {+ fprintf(out,"<DOCTYPE! html> <html> <head> <title>asdf</title> <script>");+ }+ to_js_print_externs(out,program,command_arguments);++ for(it=program->translation_units->first;it!=NULL;it=it->prev)+ {+ fprintf(out,"{");+ to_js_print_translation_unit_tree(out,(struct AST_Translation_Unit*)it->data,program);+ fprintf(out,"\n}\n");+ }++ if(command_arguments->insert_html)+ {+ fprintf(out,"</script> </head> <body> </body> </html>");+ }++ }++ void _to_js_print_externs(void *denoted,void *args)+ {+ #define ARGS(x) ((struct Command_Arguments*)x)+ #define DENOTED(x) ((struct Denoted*)x)+ #define DFUNC(x) ((struct Denoted_Function*)x)+ #define DOBJ(x) ((struct Denoted_Object*)x)+ if(DENOTED(denoted)->denotation==DT_Function)+ {+ fprintf(ARGS(args)->output_file,"var ");+ print_token(ARGS(args)->output_file,DFUNC(denoted)->id);+ fprintf(ARGS(args)->output_file,"; /*FUNCTION*/ ");+ if(DFUNC(denoted)->body==NULL)+ {+ fprintf(ARGS(args)->output_file,"/*UNDEFINED*/");+ }+ fprintf(ARGS(args)->output_file,"\n");++ }else if(DENOTED(denoted)->denotation==DT_Object)+ {+ fprintf(ARGS(args)->output_file,"var ");+ print_token(ARGS(args)->output_file,DFUNC(denoted)->id);+ fprintf(ARGS(args)->output_file,"; /*VARIABLE*/");+ }++ #undef DOBJ+ #undef DFUNC+ #undef ARGS+ #undef DENOTED+ }+ void to_js_print_externs(FILE* out,struct Program *program,struct Command_Arguments *command_arguments)+ {+ fprintf(out,"\n/*EXTERNS START*/\n");+ Map_Map_Extended(+ &((struct Normal_Scope*)program->externs)->ordinary+ ,_to_js_print_externs+ ,command_arguments);+ fprintf(out,"\n/*EXTERNS END*/\n");+ }+ void to_js_print_ast(FILE* out,struct AST *tree,struct Program *program)+ {+ if(tree==NULL)+ {+ return ;+ }+ switch(tree->type)+ {+ case OP_MEMBER_TROUGH_PTR:+ case OP_MEMBER:+ case OP_BITWISE_AND:+ case OP_BITWISE_XOR:+ case OP_BITWISE_NOT:+ case OP_LOGICAL_AND:+ case OP_LOGICAL_OR:+ case OP_XOR_ASSIGN:+ case OP_PIPE_ASSIGN:+ case OP_SHIFT_RIGHT_ASSIGN:+ case OP_ADD_ASSIGN:+ case OP_SUBTRACT_ASSIGN:+ case OP_MULTIPLY_ASSIGN:+ case OP_REMAINDER_ASSIGN:+ case OP_DIV_ASSIGN:+ case OP_SUBTRACTION:+ case OP_MUL:+ case OP_DIV:+ case OP_REMAINDER:+ case OP_EQUAL:+ case OP_LESS:+ case OP_LESS_EQ:+ case OP_SHIFT_LEFT:+ case OP_BITWISE_OR:+ case OP_AND_ASSIGN:+ case OP_ARR_SUBSCRIPT:+ case OP_SHIFT_LEFT_ASSIGN:+ case OP_ASSIGN:+ case OP_ADDITION:+ case OP_COMMA:+ case OP_SHIFT_RIGHT:+ case OP_GREATER_EQ:+ case OP_GREATER:+ case OP_NOT_EQUAL:+ to_js_print_binary_expression_tree(out,(struct AST_Binary_Expression*)tree,program);+ break;+ case OP_COND:+ to_js_print_conditional_expression_tree(out,(struct AST_Conditional_Expression*)tree,program);+ break;+ case OP_FUNCTION:+ to_js_print_function_expression_tree(out,(struct AST_Function_Expression*)tree,program);+ break;+ case OP_LOGICAL_NOT:+ case OP_UNARY_MINUS:+ case OP_SIZEOF:+ case OP_ADDR_OF:+ case OP_DEREFERENCE:+ case OP_POSTFIX_INC:+ case OP_PREFIX_INC:+ case OP_UNARY_PLUS:+ case OP_POSTFIX_DEC:+ case OP_PREFIX_DEC:+ case OP_CAST:+ to_js_print_unary_expression_tree(out,(struct AST_Unary_Expression*)tree,program);+ break;+ case OP_LVALUE:+ to_js_print_lvalue_expression_tree(out,(struct AST_Lvalue_Expression*)tree,program);+ break;+ case OP_RVALUE:+ to_js_print_rvalue_expression_tree(out,(struct AST_Rvalue_Expression*)tree,program);+ break;+ case OP_NOP:+ fprintf(out,"NOP");+ break;++ case ST_SWITCH:+ to_js_print_switch_statement_tree(out,(struct AST_Switch_Statement*)tree,program);+ break;+ case ST_IF:+ to_js_print_if_statement_tree(out,(struct AST_If_Statement*)tree,program);+ break;+ case ST_WHILE:+ to_js_print_while_statement_tree(out,(struct AST_While_Statement*)tree,program);+ break;+ case ST_DO_WHILE:+ to_js_print_do_while_statement_tree(out,(struct AST_Do_While_Statement*)tree,program);+ break;+ case ST_GOTO:+ to_js_print_goto_statement_tree(out,(struct AST_Goto_Statement*)tree,program);+ break;+ case ST_DEFAULT:+ case ST_LABEL:+ case ST_CASE:+ to_js_print_labeled_statement_tree(out,(struct AST_Labeled_Statement*)tree,program);+ break;+ case ST_CONTINUE:+ fprintf(out,"continue");+ break;+ case ST_BREAK:+ fprintf(out,"break");+ break;+ case ST_RETURN:+ to_js_print_return_statement_tree(out,(struct AST_Return_Statement*)tree,program);+ break;+ case ST_FOR:+ to_js_print_for_statement_tree(out,(struct AST_For_Statement*)tree,program);+ break;+ case ST_COMPOUND:+ to_js_print_compound_statement_tree(out,(struct AST_Compound_Statement*)tree,program);+ break;+ case ST_OBJECT_DECLARATION:+ to_js_print_object_declaration_tree(out,((struct AST_Object_Declaration*)tree),program);+ if(((struct AST_Object_Declaration*)tree)->initializer!=NULL)+ {+ fprintf(out,"=");+ to_js_print_ast(out,((struct AST_Object_Declaration*)tree)->initializer,program);+ }+ break;+ case ST_FUNCTION_DECLARATION:+ to_js_print_function_declaration_tree(out,((struct AST_Function_Declaration*)tree),program);+ break;+ case ST_FUNCTION_DEFINITION:+ to_js_print_function_definition(out,((struct AST_Function_Definition*)tree),program);+ break;+ case TRANSLATION_UNIT:+ to_js_print_translation_unit_tree(out,(struct AST_Translation_Unit*)tree,program);+ break;+ case ERROR:+ default:+ /*TODO error*/+ return;+ }+ }+ void to_js_print_translation_unit_tree(FILE* out,struct AST_Translation_Unit *translation_unit,struct Program *program)+ {+ struct Queue_Node *it;+ struct AST* hold;+ for(it=translation_unit->components.first;it!=NULL;it=it->prev)+ {+ hold=(struct AST*)(it->data);+ to_js_print_ast(out,hold,program);++ fprintf(out,";\n");+ }+ }+ void to_js_print_binary_expression_tree(FILE* out,struct AST_Binary_Expression *bin,struct Program *program)+ {+ if(bin->type==OP_ARR_SUBSCRIPT)+ {+ to_js_print_ast(out,bin->left,program);+ fprintf(out,"[");+ to_js_print_ast(out,bin->right,program);+ fprintf(out,"]");+ }else+ {+ fprintf(out,"(");+ to_js_print_ast(out,bin->left,program);+ print_ast_enum(out,bin->type);+ to_js_print_ast(out,bin->right,program);+ fprintf(out,")");+ }+ }++ void to_js_print_conditional_expression_tree(FILE* out,struct AST_Conditional_Expression *cond,struct Program *program)+ {+ fprintf(out,"(");+ to_js_print_ast(out,cond->left,program);+ fprintf(out,"?");+ to_js_print_ast(out,cond->center,program);+ fprintf(out,":");+ to_js_print_ast(out,cond->right,program);+ fprintf(out,")");+ }+ void to_js_print_function_expression_tree(FILE* out,struct AST_Function_Expression *function_call,struct Program *program)+ {+ struct Queue_Node *it;+ to_js_print_ast(out,function_call->id,program);+ fprintf(out,"(");+ if(function_call->arguments.size>0)+ {+ fprintf(out,"\n");+ for(it=function_call->arguments.first;it!=function_call->arguments.last;it=it->prev)+ {+ to_js_print_ast(out,(struct AST*)(it->data),program);+ fprintf(out,",\n");+ }+ if(it!=NULL)+ {+ to_js_print_ast(out,(struct AST*)(it->data),program);+ }++ }+ fprintf(out,")");+ }+ void to_js_print_rvalue_expression_tree(FILE* out,struct AST_Rvalue_Expression *rval,struct Program *program)+ {+ print_token(out,rval->id);+ }+ void to_js_print_lvalue_expression_tree(FILE* out,struct AST_Lvalue_Expression *lval,struct Program *program)+ {+ print_token(out,lval->id);+ }+ void to_js_print_unary_expression_tree(FILE* out,struct AST_Unary_Expression *unary,struct Program *program)+ {+ print_ast_enum(out,unary->type);+ to_js_print_ast(out,unary->operand,program);+ }+ void to_js_print_labeled_statement_tree(FILE* out,struct AST_Labeled_Statement *label,struct Program *program)+ {+ if(label->type!=ST_LABEL)+ print_ast_enum(out,label->type);+ if(label->label!=NULL)+ {+ fprintf(out,"case");+ print_token(out,label->label);+ }+ fprintf(out,":\n");+ to_js_print_ast(out,label->statement,program);+ }+ void to_js_print_compound_statement_tree(FILE* out,struct AST_Compound_Statement *compound,struct Program *program)+ {+ struct Queue_Node *it;+ fprintf(out,"{");+ for(it=compound->components.first;it!=NULL;it=it->prev)+ {+ fprintf(out,"\n");+ to_js_print_ast(out,(struct AST*)it->data,program);+ fprintf(out,";");+ }+ fprintf(out,"\n}");+ }+ void to_js_print_for_statement_tree(FILE* out,struct AST_For_Statement *for_statement,struct Program *program)+ {+ fprintf(out,"for(\n");+ if(for_statement->initialisation!=NULL)+ to_js_print_ast(out,for_statement->initialisation,program);+ fprintf(out,";\n");+ if(for_statement->condition!=NULL)+ to_js_print_ast(out,for_statement->condition,program);+ fprintf(out,";\n");+ if(for_statement->update!=NULL)+ to_js_print_ast(out,for_statement->update,program);+ fprintf(out,")\n");+ print_ast(out,for_statement->body_statement);+ }+ void to_js_print_while_statement_tree(FILE* out,struct AST_While_Statement *while_statement,struct Program *program)+ {+ fprintf(out,"while(");+ to_js_print_ast(out,while_statement->condition,program);+ fprintf(out,")\n");+ to_js_print_ast(out,while_statement->body_statement,program);+ }+ void to_js_print_do_while_statement_tree(FILE* out,struct AST_Do_While_Statement *do_while_statement,struct Program *program)+ {+ fprintf(out,"do\n");+ to_js_print_ast(out,do_while_statement->body_statement,program);+ fprintf(out,"while(");+ to_js_print_ast(out,do_while_statement->condition,program);+ fprintf(out,")\n");+ }+ void to_js_print_if_statement_tree(FILE* out,struct AST_If_Statement *if_statement,struct Program *program)+ {+ fprintf(out,"if(");+ to_js_print_ast(out,if_statement->condition,program);+ fprintf(out,")\n");+ to_js_print_ast(out,if_statement->body_statement,program);++ if(if_statement->else_statement!=NULL)+ {+ fprintf(out,"\nelse");+ to_js_print_ast(out,if_statement->else_statement,program);+ }+ }+ void to_js_print_goto_statement_tree(FILE* out,struct AST_Goto_Statement *goto_statement,struct Program *program)+ {+ /*TODO something here, be it error or not*/+ }+ void to_js_print_switch_statement_tree(FILE* out,struct AST_Switch_Statement *switch_statement,struct Program *program)+ {+ fprintf(out,"switch(");+ to_js_print_ast(out,switch_statement->condition,program);+ fprintf(out,")\n");+ to_js_print_ast(out,switch_statement->body_statement,program);+ }+ void to_js_print_return_statement_tree(FILE* out,struct AST_Return_Statement *return_statement,struct Program *program)+ {+ fprintf(out,"return ");+ to_js_print_ast(out,return_statement->return_expression,program);+ }+ void to_js_print_object_declaration_tree(FILE* out,struct AST_Object_Declaration *object_declaration,struct Program *program)+ {+ if(object_declaration->object->object->storage_class!=SC_EXTERN)+ {+ fprintf(out,"let ");+ print_token(out,object_declaration->object->id);+ }++ }+ void to_js_print_function_definition(FILE* out,struct AST_Function_Definition *function_definition,struct Program *program)+ {+ size_t i;+ struct Type_Function *cache_type;++ cache_type=(struct Type_Function*)function_definition->function->type;++ if((struct Type_Function*)function_definition->function->storage_class==SC_EXTERN)+ {+ // fprintf(out,"var ");+ print_token(out,function_definition->function->id);+ fprintf(out,"= function");+ }else+ {+ fprintf(out,"function ");+ print_token(out,function_definition->function->id);+ }++ /*print parameters*/+ fprintf(out,"(");+ print_token(out,cache_type->arguments[0]->id);+ for(i=1;i<cache_type->number_of_arguments;++i)+ {+ fprintf(out,",");+ print_token(out,cache_type->arguments[i]->id);+ }++ fprintf(out,")");++ /*print body*/+ to_js_print_compound_statement_tree(out,function_definition->function->body,program);+++ }+ void to_js_print_function_declaration_tree(FILE* out,struct AST_Function_Declaration *function_declaration,struct Program *program)+ {+ /*TODO probably leave it empty*/+ }++++ #endifF diff --git a/code_generation/js/transpile_to_js.h b/code_generation/js/transpile_to_js.h new file mode 100644 --- /dev/null +++ b/code_generation/js/transpile_to_js.h+ #ifndef GCC_TRANSPILE_TO_JS_H+ #define GCC_TRANSPILE_TO_JS_H GCC_TRANSPILE_TO_JS_H+ #include <program.h>+ #include <gcc_arguments.h>+ #include <stdio.h>+ #include <print.h>+++ void transpile_to_javascript(FILE* out,struct Program *program,struct Command_Arguments *command_arguments);+ void to_js_print_externs(FILE* out,struct Program *program,struct Command_Arguments *command_arguments);++ void to_js_print_ast(FILE* out,struct AST *tree,struct Program *program);+ void to_js_print_translation_unit_tree(FILE* out,struct AST_Translation_Unit *translation_unit,struct Program *program);+ void to_js_print_binary_expression_tree(FILE* out,struct AST_Binary_Expression *bin,struct Program *program);+ void to_js_print_conditional_expression_tree(FILE* out,struct AST_Conditional_Expression *cond,struct Program *program);+ void to_js_print_function_expression_tree(FILE* out,struct AST_Function_Expression *function_call,struct Program *program);+ void to_js_print_rvalue_expression_tree(FILE* out,struct AST_Rvalue_Expression *rval,struct Program *program);+ void to_js_print_lvalue_expression_tree(FILE* out,struct AST_Lvalue_Expression *lval,struct Program *program);+ void to_js_print_unary_expression_tree(FILE* out,struct AST_Unary_Expression *unary,struct Program *program);+ void to_js_print_labeled_statement_tree(FILE* out,struct AST_Labeled_Statement *label,struct Program *program);+ void to_js_print_compound_statement_tree(FILE* out,struct AST_Compound_Statement *compound,struct Program *program);+ void to_js_print_for_statement_tree(FILE* out,struct AST_For_Statement *for_statement,struct Program *program);+ void to_js_print_while_statement_tree(FILE* out,struct AST_While_Statement *while_statement,struct Program *program);+ void to_js_print_do_while_statement_tree(FILE* out,struct AST_Do_While_Statement *do_while_statement,struct Program *program);+ void to_js_print_if_statement_tree(FILE* out,struct AST_If_Statement *if_statement,struct Program *program);+ void to_js_print_goto_statement_tree(FILE* out,struct AST_Goto_Statement *goto_statement,struct Program *program);+ void to_js_print_switch_statement_tree(FILE* out,struct AST_Switch_Statement *switch_statement,struct Program *program);+ void to_js_print_return_statement_tree(FILE* out,struct AST_Return_Statement *return_statement,struct Program *program);+ void to_js_print_object_declaration_tree(FILE* out,struct AST_Object_Declaration *object_declaration,struct Program *program);+ void to_js_print_function_definition(FILE* out,struct AST_Function_Definition *function_definition,struct Program *program);+ void to_js_print_function_declaration_tree(FILE* out,struct AST_Function_Declaration *function_declaration,struct Program *program);+ void to_js_print_denoted(FILE* out,struct Denoted* denoted,struct Program *program);++++ #endifF diff --git a/lex/preprocessing.c b/lex/preprocessing.c --- a/lex/preprocessing.c +++ b/lex/preprocessing.cif(hold_macro!=NULL){delete_macro(hold_macro);+ Map_Remove(translation_data->macros,id->data,id->data_size);}}chase_new_line(src,translation_data);F diff --git a/main.c b/main.c --- a/main.c +++ b/main.cstruct Program *program;command_arguments=parse_command_arguments(argv);+ if(command_arguments->error_message!=NULL)+ {+ fprintf(stderr,command_arguments->error_message);+ return 1;+ }if(command_arguments->print_tokens && !command_arguments->is_quiet){return print_tokens_of_program(stdout,command_arguments->source_names);}else if(command_arguments->print_ast && !command_arguments->is_quiet){print_program_ast(stdout,program);+ }else if(command_arguments->transpile_to_js)+ {+ transpile_to_javascript(command_arguments->output_file,program,command_arguments);}}F diff --git a/misc/all.h b/misc/all.h --- a/misc/all.h +++ b/misc/all.h#include <scope.h>#include <semantics.h>#include <type.h>+ #include <transpile_to_js.h>#include <queue.h>#include <map.h>F diff --git a/misc/gcc_arguments.c b/misc/gcc_arguments.c --- a/misc/gcc_arguments.c +++ b/misc/gcc_arguments.cstruct Queue *source_names;ret=malloc(sizeof(struct Command_Arguments));- ret->print_ast=ret->print_tokens=0;+ ret->print_ast=ret->print_tokens=ret->transpile_to_js=0;+ ret->output_file=ret->javascript_extern_file=NULL;source_names=malloc(sizeof(struct Queue));Queue_Init(source_names);+ ret->error_message=NULL;/*we skip the first element(the program name)*/for(++argv;*argv;++argv)}else if(gstr_cmp(*argv,"--quiet") || gstr_cmp(*argv,"-q")){ret->is_quiet=1;+ if(ret->print_ast || ret->print_tokens)+ {+ ret->error_message="print and quiet conflict. Aborting";+ break;+ }+ }else if(gstr_cmp(*argv,"--transpile_to_js") || gstr_cmp(*argv,"-js"))+ {+ ret->transpile_to_js=1;+ }else if(gstr_cmp(*argv,"-o"))+ {+ ++argv;+ if(*argv==NULL)+ {+ ret->error_message="expected a filename after -o. Aborting";+ break;+ }else+ {+ ret->output_file=fopen(*argv,"w");+ if(ret->output_file==NULL)+ {+ ret->error_message="Couldn't open file for output. Aborting";+ break;+ }+ }+ }else if(gstr_cmp(*argv,"--make-extern-file"))+ {+ ret->javascript_extern_file=fopen(*argv,"w");+ if(ret->javascript_extern_file==NULL)+ {+ ret->error_message="Couldn't open file for extern dump. Aborting";+ break;+ }+ }else if(gstr_cmp(*argv,"--add-html"))+ {+ ret->insert_html=1;}else{Queue_Push(source_names,*argv);Queue_Pop(source_names);}free(source_names);+ if(ret->transpile_to_js && ret->output_file==NULL)+ {+ ret->output_file=fopen("a.js","w");+ if(ret==NULL)+ ret->error_message="Couldn't open file for output. Aborting";+ }return ret;}F diff --git a/misc/gcc_arguments.h b/misc/gcc_arguments.h --- a/misc/gcc_arguments.h +++ b/misc/gcc_arguments.h#include <gcc_arguments.hh>#include <queue.h>#include <gcc_string.h>+ #include <stdio.h>struct Command_Argumentschar print_tokens:1;char print_ast:1;char is_quiet:1;+ char transpile_to_js:1;+ char insert_html:1;+++ FILE* output_file;+ FILE* javascript_extern_file;+++ char *error_message;};struct Command_Arguments* parse_command_arguments(char **argv);F diff --git a/misc/map.c b/misc/map.c --- a/misc/map.c +++ b/misc/map.c}}+ /*first argument of map is the node id , the second is pass_data*/+ void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data)+ {+ if(tree->is_final==1)map(tree->ID,pass_data);+ for(int i=0;i<256;++i)+ {+ if(tree->delta[i]!=NULL)+ {+ Map_Map_Extended(tree->delta[i],map,pass_data);+ }+ }+ }/*this does not destroy(free) any memory pointed to by a node in the Map. This does not free() the root (Map *tree) */F diff --git a/misc/map.h b/misc/map.h --- a/misc/map.h +++ b/misc/map.hvoid* Map_Check(Map *tree, void *str,size_t size);void Map_Remove(Map *tree, void *str,size_t size);void Map_Map(Map *tree,void (*map)(void*));+ void Map_Map_Extended(Map *tree,void (*map)(void*,void*),void* pass_data);void Map_Destroy(Map *tree);struct Condensed_Map* Map_Condense(Map* tree);F diff --git a/misc/print.c b/misc/print.c --- a/misc/print.c +++ b/misc/print.ccase OP_ASSIGN:fprintf(out,"=");break;case OP_ADD_ASSIGN:- fprintf(out,"&=");break;+ fprintf(out,"+=");break;case OP_SUBTRACT_ASSIGN:fprintf(out,"-=");break;case OP_MULTIPLY_ASSIGN:fprintf(out,"denotation error");return;case DT_Prototype:fprintf(out,"denotation prototyep");return;+ default:+ assert(0);}}if(func->number_of_arguments==0)return;- print_type(out,func->arguments[0],0);+ print_denoted(out,(struct Denoted*)func->arguments[0]);for(i=1;i<func->number_of_arguments;++i){fprintf(out,", ");- print_type(out,func->arguments[i],0);+ print_denoted(out,(struct Denoted*)func->arguments[i]);}}#undef TOKF diff --git a/parse/parse_declaration.c b/parse/parse_declaration.c --- a/parse/parse_declaration.c +++ b/parse/parse_declaration.cif(get_and_check(translation_data,KW_OPEN_CURLY)){((struct Denoted_Function*)hold)->body=(struct AST_Compound_Statement*)parse_finish_compound_statement(translation_data,scope);+ ((struct Denoted_Function*)hold)->storage_class=(prototype->storage_class==SC_NONE?+ SC_EXTERN:+ prototype->storage_class);++++Queue_Push(where_to_push,get_function_definition_tree(scope,(struct Denoted_Function*)hold));Scope_Push(scope,hold);free(prototype);hold=extract_denoted(base,prototype,1);Scope_Push((struct Scope*)function_prototype_scope,hold);- Queue_Push(parameters,((struct Denoted_Object*)hold)->object->type);+ Queue_Push(parameters,((struct Denoted_Object*)hold));- delete_denoted(hold);delete_denoted_prototype(prototype);delete_denoted_base(base);F diff --git a/semantics/denoted.c b/semantics/denoted.c --- a/semantics/denoted.c +++ b/semantics/denoted.cret->type=return_type;ret->function_specifier=fs;ret->body=NULL;+ ret->storage_class=SC_NONE;return (struct Denoted*)ret;}{delete_denoted(denoted);}+++++#endifF diff --git a/semantics/denoted.h b/semantics/denoted.h --- a/semantics/denoted.h +++ b/semantics/denoted.henum Function_Specifier function_specifier;+ enum Storage_Class storage_class;+struct AST_Compound_Statement *body;};struct Denoted_Objectvoid delete_denoted_base(struct Denoted_Base *base);+ enum Storage_Class get_denoted_function_storage_class(struct Denoted_Function *function);#endifF diff --git a/semantics/scope.c b/semantics/scope.c --- a/semantics/scope.c +++ b/semantics/scope.creturn 1;*/case DT_Function:- case DT_Typedef:+ if(((struct Denoted_Function*)declarator)->storage_class==SC_EXTERN)+ {+ while(scope->type!=EXTERN_SCOPE)+ scope=scope->parent;+ }+ goto hack;case DT_Object:+ if(((struct Denoted_Object*)declarator)->object->storage_class==SC_EXTERN)+ {+ while(scope->type!=EXTERN_SCOPE)+ scope=scope->parent;+ }+ goto hack;+ case DT_Typedef:case DT_Enum_Constant:case DT_Struct_Union_Member:+ hack:push_ordinary(scope,((struct Denoted_Object*)declarator)->id,declarator);return;case DT_Enum:F diff --git a/semantics/type.c b/semantics/type.c --- a/semantics/type.c +++ b/semantics/type.cret->number_of_arguments=parameters->size;- ret->arguments=malloc(sizeof(struct Type*)*ret->number_of_arguments);+ ret->arguments=malloc(sizeof(struct Denoted_Object*)*ret->number_of_arguments);for(i=0;parameters->size>0;++i){- ret->arguments[i]=(struct Type*)Queue_Pop(parameters);+ ret->arguments[i]=(struct Denoted_Object*)Queue_Pop(parameters);}ret=(struct Type_Function*)type_check_and_push((struct Type*)ret,return_type->node,sizeof(struct Type_Function));F diff --git a/semantics/type.h b/semantics/type.h --- a/semantics/type.h +++ b/semantics/type.hstruct Type *return_type;/*types*/size_t number_of_arguments;- /*array of pointers to Type*/- struct Type** arguments;++ struct Denoted_Object** arguments;struct Normal_Scope *function_prototype_scope;};F diff --git a/tests/test3.c b/tests/test3.c --- a/tests/test3.c +++ b/tests/test3.cint err;#endif+ #undef VERSION#ifdef VERSION- char charimander;+ char asdf;#endif++ extern int external_int;+ static int fib(int n)+ {+ int a=1,b=1,c;+ for(n;n>0;--n)+ {+ c=a;+ a+=b;+ b=c;+ }+ return a;++ }+ int main(int argc,char *argv[])+ {+ int k[10*10];+ a=b=c=d;+ external_int++;+ fib(10);+ return 0;+ }