/* main.c ************************************************** Anubis. Main function and initialization. ***********************************************************/ /* Here, we start and initialize the Anubis compiler. */ #include #include #include #include #ifndef WIN32 #include #endif #ifdef _LINUX_ #include #endif #include "compil.h" #include "minver.h" #include "AnubisSupport.h" #include "IniFile.h" #include "MultiPath.h" #include "CMString.h" #include "FileIO.h" USING_NAMESPACE(CM); #ifdef __cplusplus extern "C" { #endif extern void yyrestart(FILE *); #ifdef __cplusplus } #endif #define buf_size (1000) static char buf[buf_size+5]; char * source_file_name= ""; #ifdef _LINUX_ char * home_directory; // for author usage only #endif char start_dir[205]; char * anubis_directory = NULL; // /home/georges/anubis or /usr/share/anubis char * my_anubis_directory = NULL; // /home/georges/my_anubis char * my_shells_directory = NULL; // /home/georges/my_anubis/shells char * library_directory = NULL; // /home/georges/anubis/library char * my_library_directory = NULL; // /home/georges/my_anubis/library char * awp_directory = NULL; // /home/georges/anubis/server/awp char * ssl_awp_directory = NULL; // /home/georges/anubis/server/ssl_awp char * djed = NULL; char * Ipaths = NULL; int stop_after = 1; int symcode_option = 0; int no_preemption = 0; int dct = 0; int make_dep = 0; int dcti = 0; int dump_implems = 0; int gindex = 0; int warn_alert = 0; int dump_used = 0; int dump_unused = 0; int check_all = 1; int initializing = 1; int configure = 0; int no_config_file_found = 0; int make_awp = 1; int read1 = 1; int phase = 1; int check_only = 0; int standard_error_output = 0; IniFile * configFile = NULL; MultiPath includePaths; int anb_exit(int n) { exit(n); } /* normalize directory path (remove trailing slash or backslash) */ static char *normalize_directory_path(char *s) { int i = 0; char *result; result = strdupz(s); while (result[i] != 0) i++; i--; if (i < 0) return(result); if (result[i] == '\\' || result[i] == '/') result[i] = 0; return result; } /* reading an option from the command line */ static void read_option(char *opt) { if (!strcmp(opt,"alert")) { warn_alert = 1; } else if (!strcmp(opt,"en")) language = 1; else if (!strcmp(opt,"fr")) language = 0; else if (!strncmp(opt,"board",5)) { board_option = 1; if (opt[5] != 0) board_option_threshold = atoi(opt+5); } else if (!strcmp(opt,"c")) check_only = 1; else if (!strcmp(opt,"index")) { gindex = 1; } else if (!strncmp(opt,"mpl",3)) max_pair_limit = sup(10000,atoi(opt+3)); else if (!strncmp(opt,"tab",3)) tab_width = inf(20,sup(0,atoi(opt+3))); else if (!strcmp(opt,"used")) { dump_used = 1; } else if (!strcmp(opt,"unused")) { dump_unused = 1; } else if (!strcmp(opt,"seo")) standard_error_output = 1; else if (!strcmp(opt,"v")) verbose = 1; else if (!strncmp(opt,"I",1)) Ipaths = opt+1; else if (!strcmp(opt,"publics")) public_decs_src_file = 1; #ifndef _CRYPTADM_ else if (!strcmp(opt,"sb")) show_brackets = 1; else if (!strcmp(opt,"cv")) cverbose = 1; else if (!strcmp(opt,"read1")) read1 = 1; else if (!strcmp(opt,"to")) types_only = 1; else if (!strcmp(opt,"predef")) { reading_predef = 1; source_file_name = "predefined.anubis"; } else if (!strcmp(opt,"checkall")) { check_all = 1; } else if (!strcmp(opt,"nopre")) { no_preemption = 1; } else if (!strcmp(opt,"dumpimplems")) { dump_implems = 1; } else if (!strncmp(opt,"cdir:",5)) anubis_directory = opt+5; else if (!strncmp(opt,"pdir:",5)) my_anubis_directory = opt+5; else if (!strcmp(opt,"dct")) dct = 1; else if (!strcmp(opt,"dep")) make_dep = 1; else if (!strcmp(opt,"dcti")) dct = dcti = 1; else if (!strcmp(opt,"symcode")) symcode_option = 1; else if (!strcmp(opt,"sc")) symcode_option = 1; else if (!strcmp(opt,"pol")) pre_polish = 1; else if (!strcmp(opt,"reads")) show_reads = 1; else if (!strcmp(opt,"config")) configure = 1; #endif else { fprintf(stderr,"Invalid option: -%s \n",opt); anb_exit(1); } } /* reading the command line */ static void read_command_line(int argc, char **argv) { int i; for (i = 1; i < argc; i++) if (argv[i][0] == '-') read_option(argv[i]+1); else source_file_name = argv[i]; } static char getsbuf[1000]; static char *mygets(void) { int i = 0; if (fgets(getsbuf,990,stdin)) { while (getsbuf[i] != 0 && getsbuf[i] != '\n') i++; getsbuf[i] = 0; return getsbuf; } else return ""; } void set_language(void) { int result; printf(msgtext_set_language[language]); result = atoi(mygets()); switch (result) { case 1: language = 0; // french case 2: language = 1; // english } } void set_stop_after(void) { int result; printf(msgtext_set_stop_after[language]); result = atoi(mygets()); if (result > 0) stop_after = result; } void set_verbose(void) { char *result; printf(msgtext_set_verbose[language]); result = mygets(); if (toupper(result[0]) == msgtext_Y[language][0]) verbose = 1; if (toupper(result[0]) == msgtext_N[language][0]) verbose = 0; } //void set_djed(void) //{ // char *result; // printf(msgtext_set_djed[language]); // result = mygets(); // if (fopen(result,"rt") != NULL) djed = strdupz(result); //} void save_config(void) { if (configFile) { configFile->WriteInt32("COMPILER", "StopAfterErrors", stop_after); configFile->WriteInt32("COMPILER", "VerboseLevel", verbose); configFile->WriteInt32("COMPILER", "Language", language); configFile->Update(); } } char *language_string(void) { switch (language) { case 0: return "Français"; case 1: return "English"; default: assert(0); return ""; } return ""; } void configure_compiler(void) { char *response; int number; if (no_config_file_found) printf(msgtext_no_config_file_found[language]); else printf(msgtext_configure_welcome[language]); while (1) { printf("-----------------------------------------\n"); printf(msgtext_configuration_board[language], language_string(), stop_after, verbose ? msgtext_yes[language] : msgtext_no[language], djed != NULL ? djed : msgtext_not_defined[language] ); response = mygets(); number = atoi(response); switch (number) { case 1: set_language(); continue; case 2: set_stop_after(); continue; case 3: set_verbose(); continue; default: if (response[0] == 'q' || response[0] == 'Q') anb_exit(0); if (response[0] == 's' || response[0] == 'S') { save_config(); anb_exit(0); } continue; } } anb_exit(0); } /* initialization process */ static void init(int argc, char **argv) { char *actual_source_file_name = source_file_name; /* allocate the various arrays needed by the compiler */ pairs = (struct Pair_struct *)mallocz(max_pair*sizeof(struct Pair_struct)); ppairs = (struct Pair_struct *)mallocz(max_ppair*sizeof(struct Pair_struct)); strings = (char **)mallocz(max_string*sizeof(char *)); compiled_strings = (struct Compiled_string_struct *) mallocz(max_compiled_string*sizeof(struct Compiled_string_struct)); types = (struct Type_struct *)mallocz(max_type*sizeof(struct Type_struct)); operations = (struct Operation_struct *)mallocz(max_operation*sizeof(struct Operation_struct)); closure_codes = (struct ClosureCode_struct *)mallocz(max_closure_code*sizeof(struct ClosureCode_struct)); mctxt_del_codes = (struct MCtxtDelCode_struct *)mallocz(max_mctxt_del_code*sizeof(struct MCtxtDelCode_struct)); variables = (struct Variable_struct *)mallocz(max_variable*sizeof(struct Variable_struct)); //expr_buffer = (Expr *)mallocz(expr_buffer_size*sizeof(Expr)); utvar_names = (char **)mallocz(max_utvar*sizeof(char *)); compiled_ops = (struct Compiled_op_struct *)mallocz(max_compiled_op*sizeof(struct Compiled_op_struct)); del_codes = (struct Del_code_struct *)mallocz(max_del_code*sizeof(struct Del_code_struct)); implems = (struct Implem_struct *)mallocz(max_implem*sizeof(struct Implem_struct)); init_label_index(); init_symbol_index(); /* initialize predefined strings */ #define item(sym,str) pdstr_##sym = new_string(str); predef_strings #undef item /* make predefined types and operations */ source_file_name = "predefined.anubis"; add_to_already_included(source_file_name); do_predefinitions1(); if (!reading_predef) { do_predefinitions2(); if(configFile) { configFile->ReadInteger("COMPILER", "StopAfterErrors", 1, &stop_after); configFile->ReadInteger("COMPILER", "VerboseLevel", 0, &verbose); configFile->ReadInteger("COMPILER", "Language", 0, &language); /* reread the command line which must supersede the config file */ read_command_line(argc,argv); } /* read configuration file */ // { // char buf[1000]; // snprintf(buf,990,"%s/configuration/compiler.conf",my_anubis_directory); // //printf("Configuration read from '%s'.\n",buf); // yyin = fopen(buf,"rt"); // if (yyin != NULL) // { // char *old_source_file_name = source_file_name; // // source_file_name = buf; // yyrestart(yyin); // begin_CONFCOM(); // yyparse(); // fclose(yyin); // source_file_name = old_source_file_name; // lineno = 1; // colno = 0; // /* reread the command line which must supersede the config file */ // read_command_line(argc,argv); // } // else // { // no_config_file_found = 1; // unput_token = 0; // required when config file not read in // } // } if (configure) configure_compiler(); #ifdef _no_predef_dat_ #else read_predef_dat(); #endif } source_file_name = actual_source_file_name; } /* sometimes we need to recall the syntax to the user */ static void syntax(void) { #ifdef _CRYPTADM_ fprintf(stderr,msgtext_syntax_perso[language],min_version,rel_version); #else fprintf(stderr,msgtext_syntax_standard[language],min_version,rel_version); #endif fprintf(stderr,msgtext_syntax[language]); anb_exit(1); } int check_anubis_file(char *name) { FILE *fp; sprintf(buf,"%s/%s", my_library_directory,name); if ((fp = fopen(buf,"rt")) == NULL) { sprintf(buf,"%s/%s", library_directory,name); if ((fp = fopen(buf,"rt")) == NULL) { return 0; } else { fclose(fp); return 1; } } else { fclose(fp); return 1; } } String anubisRootDirectory; /* main function (Anubis compiler) */ int main(int argc, char **argv) { String tmpStr; /* check if we don't have too many virtual machine instructions */ assert(i_dummy <= 255); //printf("argv[0] %s\n",argv[0]); anubisRootDirectory = GetProgramRootDir(argv[0]); //printf("ANUBIS ROOT DIR %s argv %s",anubisRootDirectory.Cstr(),argv[0]); /* if only compiler name on command line, recall the syntax. */ if (argc <= 1) syntax(); /* read the command line */ read_command_line(argc,argv); if (gindex) { mkdirz("comments"); ext_com = (char *)mallocz(ext_com_size); } configFile = new IniFile( anubisRootDirectory + "/anubis.conf"); if(configFile->InitCheck() != B_NO_ERROR) { fprintf(stderr, "Can't find anubis.conf file"); exit(1); } if (anubis_directory == NULL) { configFile->ReadString("PATH", "ANUBIS", ".", tmpStr); if (tmpStr.Length()) { anubis_directory = strdup(tmpStr.Cstr()); } } // anubis_directory = getenv("ANUBIS"); if (my_anubis_directory == NULL) { configFile->ReadString("PATH", "MY_ANUBIS", ".", tmpStr); if (tmpStr.Length()) { my_anubis_directory = strdup(tmpStr.Cstr()); } } // my_anubis_directory = getenv("MY_ANUBIS"); if (anubis_directory == NULL) { fprintf(stderr,msgtext_anubis_shell_variable_not_set[language]); syntax(); } else if (my_anubis_directory == NULL) { fprintf(stderr,msgtext_my_anubis_shell_variable_not_set[language]); syntax(); } else { NormalizeFileName(anubis_directory); // make a copy and remove trailing '/' my_anubis_directory = normalize_directory_path(my_anubis_directory); djed = (char *)mallocz(30+strlen(my_anubis_directory)); sprintf(djed,"%s/Anubis_1_%d.djed",my_anubis_directory,min_version); my_shells_directory = (char *)mallocz(20+strlen(my_anubis_directory)); sprintf(my_shells_directory,"%s/shells",my_anubis_directory); library_directory = (char *)mallocz(20+strlen(anubis_directory)); sprintf(library_directory,"%s/library",anubis_directory); my_library_directory = (char *)mallocz(20+strlen(my_anubis_directory)); sprintf(my_library_directory,"%s/library",my_anubis_directory); } if (Ipaths != NULL) { includePaths.AddPaths(Ipaths,";"); } configFile->ReadString("COMPILER", "includeDir", "", tmpStr); if (tmpStr.Length()) { includePaths.AddPaths(tmpStr.Cstr(),";"); } includePaths.AddPath(my_library_directory); includePaths.AddPath(library_directory); board_headers(); //if need, create missing directories mkdirz(my_anubis_directory); snprintf(buf,990,"%s/configuration",my_anubis_directory); mkdirz(buf); snprintf(buf,990,"%s/library",my_anubis_directory); mkdirz(buf); snprintf(buf,990,"%s/modules",my_anubis_directory); mkdirz(buf); snprintf(buf,990,"%s/shells",my_anubis_directory); mkdirz(buf); if(verbose) printf(msgtext_welcome[language],1,min_version,rel_version); if(verbose) printf("Number of virtual machine instructions: %d\n",(unsigned int)i_dummy); /* do a special stuff for MS-Windows */ //#ifdef WIN32 // errfile = stderr; // to avoid a NULL file in all cases // if (standard_error_output) // { // //errfile = stderr; // } // else // { // if (source_file_name[0] != 0) //// anb_exit(1); // { // int i = 0; // int j = 0; // while (source_file_name[i] != 0) // { // buf[i] = source_file_name[i]; i++; // } // while (buf[i] != '.' && i > 0) i--; // i++; // while (err_file_name[j] != 0) // { // buf[i++] = err_file_name[j++]; // } // buf[i] = 0; // errfile = fopenz(buf,"wt"); /* if file cannot be opened 'fopenz' will print into // 'errfile' making a violation if errfile has no default // value. Fortunately the default value is 'stderr' */ // } // } //#else errfile = stderr; //#endif /* this is to allow nested file include instructions */ { include_names[0] = source_file_name; include_dir[0] = (char *)mallocz(205); if (getcwd(include_dir[0],200) == NULL || getcwd(start_dir,200) == NULL) { fprintf(errfile,"Cannot get current directory.\n"); anb_exit(1); } include_lines[0] = 1; } /* initialize */ init(argc,argv); /* initialization depends on command line */ if (errors) { finish_show_reads(); return 1; /* errors in predefinitions */ } /* the following is used only by the index */ first_user_op = next_operation; first_user_type = next_type; #ifdef myanubis if (reading_predef) { /* read 'predef.anubis' */ assert(check_all); unput_token = 0; snprintf(buf,buf_size,"predef.aux"); predef_aux = fopenz(buf,"wt"); snprintf(buf,buf_size,"predef_npd.aux"); predef_npd_aux = fopenz(buf,"wt"); snprintf(buf,buf_size,"predef_1_%d.dat",min_version); predef_dat = fopenz(buf,"wb"); put32(predef_dat,condensate_version(1,min_version,0)); yyin = fopensrc("predef.anubis"); source_file_name = "predefined.anubis"; file_id = 0; include_names[0] = already_included[0] = "predefined.anubis"; begin_INITIAL(); yyparse(); fclose(yyin); fclose(predef_aux); fclose(predef_npd_aux); fclose(predef_dat); if (dct) dump_C_types(); if (board_option) fprintf(stderr,"\n"); anb_exit(0); } #endif /* making a global index */ if (gindex) { make_global_index(argc,argv); anb_exit(0); } /* if no source file given on command line */ if (source_file_name[0] == 0 || !strcmp(source_file_name,"predefined.anubis")) syntax(); if (verbose) printf(msgtext_compiling_file[language],source_file_name); /* open the source file, read and check it */ add_to_already_included(source_file_name); assert(next_already_included == 2); file_id = get_file_id(source_file_name); if (show_reads) if (show_reads_file == NULL) { show_reads_file = fopenz("reads.txt","wt"); fprintf(show_reads_file,msgtext_show_reads_file_header[language],source_file_name); } initialize_visibility(); yyin = fopensrc(source_file_name); if (pre_polish) polish = 1; unput_token = 0; initializing = 0; yyrestart(yyin); begin_INITIAL(); yyparse(); fclose(yyin); if (check_only) return 0; phase = 2; if (show_reads) show_missing_reads(); if (incorrect_pars) { if (tab_seen) fprintf(errfile,msgtext_tab_seen[language],tab_width); finish_show_reads(); return 1; } errors = 0; /* check if all types are completed */ check_incomplete_types(); /* do some work before generating the code */ find_infinite_types(); infinite_flags_reliable = 1; find_determinism(); if (dct) dump_C_types(); /* dump_absolute_types(); */ /* generate the code */ dump_dynamic_modules(); if (dump_implems) { int i; for (i = 0; i < next_implem; i++) { printf("\n\n[%d] (at label %d) Implementation of ",i,integer_value(implems[i].addr)); show_type(stdout,implems[i].type,implems[i].env); printf(":\n "); print_expr(stdout,implems[i].implem); } printf("\n"); } /* statistics */ clean_up_pairs(); if (verbose) { printf("\n\nNumber of permanent pairs used: %d.\n",next_ppair); printf("Maximal number of temporary pairs used: %d.\n",sup(max_tpair_load,next_pair)); } if (board_option) printf("\n"); if (0) { int i,j; printf("Labels:\n\n"); for (i = 0; i < 256; i++) { printf("hash: %d\n",i); for (j = 0; j < (int)label_index[i].next; j++) { printf(" label %d: index: %d\n", integer_value(((label_index[i].array)[j]).label), ((label_index[i].array)[j]).index); } } } if (0) { int i,j; SymbolIndexEntry entry; printf("Symbols:\n\n"); for (i = 0; i < 256; i++) { printf("hash: %d\n",i); for (j = 0; j < (int)symbol_index[i].next; j++) { entry = ((symbol_index[i].array)[j]); switch (entry.sort) { case syms_type: printf(" %-35s %6d (Type) %s line %6d\n", string_content(entry.symbol), entry.index, string_content(types[entry.index].file_name), integer_value(types[entry.index].line)); break; case syms_operation: printf(" %-35s %6d (Datum) %s line %6d\n", string_content(entry.symbol), entry.index, string_content(operations[entry.index].file_name), integer_value(operations[entry.index].line)); break; case syms_variable: printf(" %-35s %6d (Var) %s line %6d\n", string_content(entry.symbol), entry.index, file_in(variables[entry.index].lc), line_in(variables[entry.index].lc)); break; default: assert(0); } } } } if (public_decs_src_file) { FILE *fp = fopenz("_publics.anubis","wt"); make_public_decs_src_file(fp); } if (errors) { if (tab_seen) fprintf(errfile,msgtext_tab_seen[language],tab_width); finish_show_reads(); return 1; } else { finish_show_reads(); return 0; } } #ifdef __cplusplus extern "C" { #endif extern char *fopensrc_abs_path; void includePathsCheckFile(char * fileToCheck) { String resultPath; resultPath = includePaths.CheckFile(String(fileToCheck)); if(resultPath.Length()) { fopensrc_abs_path = strdupz((char *)resultPath.Cstr()); return; } fopensrc_abs_path = strdupz(""); return; } #ifdef __cplusplus } #endif