home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ppcsmalleiffel / lib_se / small_eiffel.e < prev    next >
Encoding:
Text File  |  1998-01-16  |  24.4 KB  |  1,068 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class SMALL_EIFFEL
  17.  
  18. inherit GLOBALS; 
  19.    
  20. creation {GENERAL}
  21.    make
  22.    
  23. feature 
  24.    
  25.    copyright: STRING is
  26.       "-- SmallEiffel The GNU Eiffel Compiler -- Release (- 0.82)      --%N%
  27.       %-- Copyright (C), 1994-98 - LORIA - UHP - CRIN - INRIA - FRANCE --%N%
  28.       %-- Dominique COLNET and Suzanne COLLIN -    colnet@loria.fr     --%N%
  29.       %--                 http://www.loria.fr/SmallEiffel              --%N";
  30.       
  31.    make is do end;
  32.    
  33.    loading_path: ARRAY[STRING] is
  34.       local
  35.      path: STRING;
  36.      file: STD_FILE_READ;
  37.       once
  38.      !!Result.make(1,10);
  39.      Result.clear;
  40.      !!file.connect_to("loadpath.se");
  41.      if file.is_connected then
  42.         from
  43.         until
  44.            file.end_of_input
  45.         loop
  46.            file.read_line;
  47.            Result.add_last(file.last_string.twin);
  48.         end;
  49.         file.disconnect;
  50.      end;
  51.      path := small_eiffel_directory.twin;
  52.      add_directory(path,fz_sys);
  53.      path.append("loadpath.");
  54.      path.append(system_name);
  55.      file.connect_to(path);
  56.      if file.is_connected then
  57.         from
  58.         until
  59.            file.end_of_input
  60.         loop
  61.            file.read_line;
  62.            Result.add_last(file.last_string.twin);
  63.         end;
  64.         file.disconnect;
  65.      else
  66.         echo.w_put_string("No default path (file %"");
  67.         echo.w_put_string(path);
  68.         echo.w_put_string("%" not found).%N");
  69.      end;
  70.       end;
  71.    
  72. feature 
  73.    
  74.    is_ready: BOOLEAN;
  75.      -- True when type inference algorithm is done : all 
  76.      -- needed classes are loaded, `at_run_time' classes are
  77.      -- known, falling down is done, ...
  78.  
  79. feature 
  80.    
  81.    get_class(str: STRING): BASE_CLASS is
  82.       do
  83.      if base_class_dictionary.has(str) then
  84.         Result := base_class_dictionary.at(str);
  85.      else
  86.         tmp_class_name.make(str,Void);
  87.         Result := tmp_class_name.base_class;
  88.      end;
  89.       ensure
  90.      Result /= Void;
  91.       end;
  92.    
  93.    base_class(class_name: CLASS_NAME): BASE_CLASS is
  94.       require
  95.      class_name /= Void;
  96.       do
  97.      if base_class_dictionary.has(class_name.to_string) then
  98.         Result := base_class_dictionary.at(class_name.to_string);
  99.      elseif eiffel_parser.is_running then
  100.         fatal_error("Internal Error #1 in SMALL_EIFFEL.");
  101.      else
  102.         if parser_buffer_for(class_name.to_string) then
  103.            Result := eiffel_parser.analyse_class(class_name);
  104.            check
  105.           Result /= Void
  106.              implies
  107.                   base_class_dictionary.has(class_name.to_string);
  108.            end;
  109.         end;
  110.         if Result = Void then
  111.            eh.add_position(class_name.start_position);
  112.            fatal_error("Unable to load class.");
  113.         end;
  114.      end;
  115.       end;
  116.    
  117.    load_class(name: STRING): BASE_CLASS is
  118.      -- Try to load the `name' class where `name' is given
  119.      -- in a command line (it can be a class name or a path).
  120.       require
  121.      not eiffel_parser.is_running
  122.       do
  123.      if parser_buffer_for(name) then
  124.         Result := eiffel_parser.analyse_class(Void);
  125.         if Result = Void then
  126.            fatal_error("Cannot load class.");
  127.         end;
  128.      else
  129.         fatal_error("Cannot find class.");
  130.      end;
  131.       end;
  132.  
  133. feature {PRETTY}
  134.  
  135.    re_load_class(e_class: BASE_CLASS): BOOLEAN is
  136.       require
  137.      e_class /= Void;
  138.       local
  139.      name: STRING;
  140.      new_class: like e_class;
  141.       do
  142.      name := e_class.base_class_name.to_string;
  143.      check 
  144.         base_class_dictionary.has(name);
  145.      end;
  146.      base_class_dictionary.remove(name);
  147.      new_class := load_class(name);
  148.      Result := new_class /= Void;
  149.       end;
  150.    
  151. feature {EIFFEL_PARSER}
  152.    
  153.    add_class(c: BASE_CLASS) is
  154.       require
  155.      c /= Void
  156.       do      
  157.      check
  158.         not base_class_dictionary.has(c.base_class_name.to_string);
  159.      end;
  160.      base_class_dictionary.put(c,c.base_class_name.to_string);
  161.      incr_magic_count;
  162.       ensure
  163.      base_class_dictionary.has(c.base_class_name.to_string);
  164.       end;
  165.  
  166. feature {FINDER} 
  167.  
  168.    find_path_for(arg: STRING): STRING is
  169.       do
  170.      if parser_buffer_for(arg) then
  171.         Result := parser_buffer.path;
  172.      end;
  173.      parser_buffer.unset_is_ready;
  174.       end;
  175.  
  176. feature {NONE}
  177.  
  178.    parser_buffer_path: STRING is
  179.       once
  180.      !!Result.make(256);
  181.       end;
  182.  
  183.    parser_buffer_for(name: STRING): BOOLEAN is
  184.      -- SmallEiffel algorithm for searching classes on the disk.
  185.      -- When Result, `parser_buffer' is ready to be used.
  186.       require
  187.      name /= Void;
  188.      not parser_buffer.is_ready
  189.       local
  190.      i: INTEGER;
  191.       do
  192.      tmp_tail.copy(name);
  193.      tmp_tail.to_lower;
  194.      if not tmp_tail.has_suffix(eiffel_suffix) then
  195.         tmp_tail.append(eiffel_suffix);
  196.      end;
  197.      from  
  198.         i := loading_path.lower;
  199.      until
  200.         i > loading_path.upper or else Result
  201.      loop
  202.         parser_buffer_path.copy(loading_path.item(i));
  203.         parser_buffer_path.append(tmp_tail);
  204.         parser_buffer.load_file(parser_buffer_path);
  205.         Result := parser_buffer.is_ready;
  206.         i := i + 1;
  207.      end;
  208.      if not Result and then rename_dictionary.has(tmp_tail) then
  209.         parser_buffer_path.copy(rename_dictionary.at(tmp_tail));
  210.         parser_buffer.load_file(parser_buffer_path);
  211.         if parser_buffer.is_ready then
  212.            Result := true;
  213.         else
  214.            echo.w_put_string("Bad %"rename.se%" file.%NCannot open %"");
  215.            echo.w_put_string(parser_buffer_path);
  216.            echo.w_put_string(fz_03);
  217.            die_with_code(exit_failure_code);
  218.         end;
  219.      end;
  220.      if not Result then
  221.         tmp_tail.copy(name);
  222.         if not tmp_tail.has_suffix(eiffel_suffix) then
  223.            tmp_tail.append(eiffel_suffix);
  224.         end;
  225.         from  
  226.            i := loading_path.lower;
  227.         until
  228.            i > loading_path.upper or else Result
  229.         loop
  230.            parser_buffer_path.copy(loading_path.item(i));
  231.            parser_buffer_path.append(tmp_tail);
  232.            parser_buffer.load_file(parser_buffer_path);
  233.            Result := parser_buffer.is_ready;
  234.            i := i + 1;
  235.         end;
  236.      end;
  237.      if not Result then
  238.         echo.w_put_string("Unable to find file for class %"");
  239.         echo.w_put_string(name);
  240.         echo.w_put_string("%". ");
  241.         parser_buffer_path.clear;
  242.         append_loading_path_in(parser_buffer_path);
  243.         echo.w_put_string(parser_buffer_path);
  244.      end;
  245.       ensure
  246.      Result implies parser_buffer.is_ready
  247.       end;
  248.    
  249.    rename_dictionary: DICTIONARY[STRING,STRING] is
  250.      -- Handling of "rename.se" files.
  251.       local
  252.      i: INTEGER;
  253.      full_name, short_name: STRING;
  254.       once
  255.      from  
  256.         !!Result.make;
  257.         i := 1;
  258.      until
  259.         i > loading_path.upper
  260.      loop
  261.         tmp_path.copy(loading_path.item(i));
  262.         tmp_path.append("rename.se");
  263.         echo.sfr_connect(tmp_file_read,tmp_path);
  264.         if tmp_file_read.is_connected then
  265.            from
  266.            until
  267.           tmp_file_read.end_of_input
  268.            loop
  269.           tmp_file_read.read_word;
  270.           full_name := tmp_file_read.last_string.twin;
  271.           tmp_file_read.read_word;
  272.           short_name := tmp_file_read.last_string.twin;
  273.           short_name.prepend(loading_path.item(i));
  274.           if Result.has(full_name) then
  275.              echo.w_put_string("Multiple entry for %"");
  276.              echo.w_put_string(full_name);
  277.              echo.w_put_string("%" in %"rename.se%" files.%N%
  278.                        %Clash for %N%"");
  279.              echo.w_put_string(short_name);
  280.              echo.w_put_string("%" and %N%"");
  281.              echo.w_put_string(Result.at(full_name));
  282.              echo.w_put_string(".%N");
  283.              die_with_code(exit_failure_code);
  284.           end;
  285.           Result.put(short_name,full_name)
  286.           tmp_file_read.skip_separators;
  287.            end;           
  288.            tmp_file_read.disconnect;
  289.         end;
  290.         i := i + 1;
  291.      end;
  292.       end;
  293.  
  294. feature
  295.  
  296.    short_flag: BOOLEAN;
  297.      -- True when command `short' is running.
  298.  
  299. feature {SHORT}
  300.  
  301.    set_short_flag is
  302.       do
  303.      short_flag := true;
  304.       end;
  305.  
  306. feature 
  307.    
  308.    string_at_run_time: BOOLEAN is
  309.       require
  310.      is_ready
  311.       local
  312.      rc: RUN_CLASS;
  313.       do
  314.      if run_class_dictionary.has(us_string) then
  315.         rc := run_class_dictionary.at(us_string);
  316.         Result := rc.at_run_time;
  317.      end;
  318.       end;
  319.  
  320.    is_used(cn: STRING): BOOLEAN is
  321.      -- Is the base class `cn' used (loaded) ?
  322.       do
  323.      Result := base_class_dictionary.has(cn);
  324.       end;
  325.    
  326.    run_class(t: TYPE): RUN_CLASS is
  327.       require
  328.      t.run_type = t;
  329.       local
  330.      run_string: STRING;
  331.       do
  332.      run_string := t.run_time_mark;
  333.      if run_class_dictionary.has(run_string) then
  334.         Result := run_class_dictionary.at(run_string);
  335.      else        
  336.         !!Result.make(t);
  337.         check
  338.            run_class_dictionary.has(run_string);
  339.         end;
  340.      end;
  341.       ensure
  342.      Result /= Void
  343.       end;
  344.    
  345. feature 
  346.    
  347.    base_class_count: INTEGER is
  348.      -- Total number of base class actually loaded.
  349.       do
  350.      Result := base_class_dictionary.count;
  351.       end;
  352.    
  353. feature 
  354.    
  355.    compile_to_c(root_class, procedure: STRING) is
  356.      -- Produce C code for `root_class'/`procedure'.
  357.       require
  358.      not root_class.empty;
  359.      not procedure.empty
  360.       local
  361.      rc: RUN_CLASS;
  362.      t: TYPE;
  363.      run_count: INTEGER;
  364.      rf3: RUN_FEATURE_3;
  365.      i: INTEGER;
  366.      gc_flag: BOOLEAN;
  367.       do
  368.      rf3 := get_started(root_class,procedure);
  369.      if nb_errors = 0 then
  370.         check 
  371.            rf3 /= Void
  372.         end;
  373.         cpp.get_started;
  374.         cpp.swap_on_h;
  375.         gc_flag := gc_handler.is_on;
  376.         -- ---------------------------------------------------------
  377.         cpp.put_string("%N/* --- Mangling Table Start ---%N");
  378.         from   
  379.            i := 1;
  380.         until
  381.            i > run_class_dictionary.count
  382.         loop
  383.            rc := run_class_dictionary.item(i);
  384.            if rc.at_run_time then
  385.           run_count := run_count + 1;
  386.            end;
  387.            rc.demangling;
  388.            i := i + 1;
  389.         end;
  390.         cpp.put_string(" --- Mangling Table End --- */%N");
  391.         -- ---------------------------------------------------------
  392.         from
  393.            cpp.put_comment_line("C Header Pass 1 :");
  394.            i := 1;
  395.         until
  396.            i > run_class_dictionary.count
  397.         loop
  398.            rc := run_class_dictionary.item(i);
  399.            rc.c_header_pass1;
  400.            i := i + 1;
  401.         end;
  402.         -- ---------------------------------------------------------
  403.         from
  404.            cpp.put_comment_line("C Header Pass 2 :");
  405.            i := 1;
  406.         until
  407.            i > run_class_dictionary.count
  408.         loop
  409.            rc := run_class_dictionary.item(i);
  410.            rc.c_header_pass2;
  411.            i := i + 1;
  412.         end;
  413.         -- ---------------------------------------------------------
  414.         from
  415.            cpp.put_comment_line("C Header Pass 3 :");
  416.            i := 1;
  417.         until
  418.            i > run_class_dictionary.count
  419.         loop
  420.            rc := run_class_dictionary.item(i);
  421.            rc.c_header_pass3;
  422.            i := i + 1;
  423.         end;
  424.         -- ---------------------------------------------------------
  425.         from
  426.            cpp.put_comment_line("C Header Pass 4 :");
  427.            i := 1;
  428.         until
  429.            i > run_class_dictionary.count
  430.         loop
  431.            rc := run_class_dictionary.item(i);
  432.            rc.c_header_pass4;
  433.            i := i + 1;
  434.         end;
  435.         -- ---------------------------------------------------------
  436.         if gc_handler.is_on then
  437.            gc_handler.define1;
  438.         end;
  439.         -- ---------------------------------------------------------
  440.         compile_routines;
  441.         cpp.cecil_define;
  442.         -- ---------------------------------------------------------
  443.         if gc_handler.is_on then
  444.            gc_handler.define2;
  445.         end;
  446.         cpp.define_main(rf3);
  447.         cpp.define_used_basics;
  448.         debug
  449.            echo.put_string("Very Final magic_count : ");
  450.            echo.put_integer(magic_count);
  451.            echo.put_character('%N');
  452.         end;
  453.         cpp.write_make_file;
  454.      else
  455.         eh.error("Cannot produce C code.");
  456.      end;
  457.       end;
  458.    
  459.    compile_to_jvm(root_class, procedure: STRING) is
  460.      -- Produce Java Byte Code for `root_class'/`procedure'.
  461.       require
  462.      not root_class.empty;
  463.      not procedure.empty
  464.       local
  465.      rf3: RUN_FEATURE_3;
  466.      rc: RUN_CLASS;
  467.      run_count, i: INTEGER;
  468.       do
  469.      rf3 := get_started(root_class,procedure);
  470.      if nb_errors = 0 then
  471.         check 
  472.            rf3 /= Void
  473.         end;
  474.         jvm.mkdir(rf3);
  475.         from
  476.            i := 1;
  477.         until
  478.            i > run_class_dictionary.count
  479.         loop
  480.            rc := run_class_dictionary.item(i);
  481.            if rc.at_run_time then
  482.           run_count := run_count + 1;
  483.           rc.compile_to_jvm;
  484.            end;
  485.            i := i + 1;
  486.         end;
  487.         echo.print_count("Used Type",run_count);
  488.         jvm.write_jvm_root_class;
  489.         jvm.write_main_class(rf3);
  490.      else
  491.         eh.error("Cannot produce Java Byte Code.");
  492.      end;
  493.       end;
  494.  
  495. feature {NONE}
  496.    
  497.    base_class_dictionary: DICTIONARY[BASE_CLASS,STRING] is
  498.      -- When looking for a BASE_CLASS using the name of 
  499.      -- base class (ie FOO[BAR] is stored at key "FOO").
  500.       once
  501.      !!Result.make;
  502.       end;
  503.    
  504. feature 
  505.    
  506.    magic_count: INTEGER;
  507.      -- Grow each time a new run class is added, each time a new 
  508.      -- class is loaded, each time a new feature is checked, 
  509.      -- each time ... 
  510.      -- Thus when `magic_count' stops growing, we are really 
  511.      -- ready to run :-).
  512.  
  513. feature {RUN_CLASS,RUN_FEATURE}
  514.    
  515.    incr_magic_count is
  516.       do
  517.      magic_count := magic_count + 1;
  518.       end;
  519.    
  520. feature {BASE_CLASS,RUN_CLASS,GC_HANDLER}
  521.          
  522.    run_class_dictionary: DICTIONARY[RUN_CLASS,STRING] is
  523.       once
  524.      !!Result.make;
  525.       end;
  526.    
  527. feature {CALL_PROC_CALL}
  528.  
  529.    run_class_with(run_time_mark: STRING): RUN_CLASS is
  530.       do
  531.      if run_class_dictionary.has(run_time_mark) then
  532.         Result := run_class_dictionary.at(run_time_mark);
  533.      end;
  534.       end;
  535.  
  536. feature {RUN_CLASS}
  537.  
  538.    is_tagged(rc: RUN_CLASS): BOOLEAN is
  539.       require
  540.      is_ready;
  541.      rc.at_run_time;
  542.      rc.current_type.is_reference;
  543.      run_control.boost
  544.       local
  545.      i, up: INTEGER;
  546.      r: ARRAY[RUN_CLASS];
  547.      rcd: like run_class_dictionary;
  548.      rc2: RUN_CLASS;
  549.       do
  550.      from
  551.         i := 1;
  552.         rcd := run_class_dictionary;
  553.         up := rcd.count;
  554.      until
  555.         Result or else i > up
  556.      loop
  557.         rc2 := rcd.item(i);
  558.         r := rc2.running;
  559.         if r = Void then
  560.         elseif r.fast_has(rc) then
  561.            Result := r.count > 1;
  562.         end;
  563.         i := i + 1;
  564.      end;
  565.       end;
  566.    
  567. feature {NONE}
  568.    
  569.    get_started(root_class, procedure: STRING): RUN_FEATURE_3 is
  570.      -- Get started to compile using creation `procedure' 
  571.      -- of base class `root_class'.
  572.       require
  573.      not root_class.empty;
  574.      not procedure.empty
  575.       local
  576.      root_name: CLASS_NAME;
  577.      root_proc_name: SIMPLE_FEATURE_NAME;
  578.      root: BASE_CLASS;
  579.      root_proc: PROCEDURE;
  580.      root_type: TYPE;
  581.      magic: INTEGER;
  582.       do
  583.      echo.put_string(copyright);
  584.      echo.put_string("Parsing :%N");
  585.      root := load_class(root_class);
  586.      if root = Void then
  587.         eh.append("Cannot load root class ");
  588.         eh.append(root_class);
  589.         eh.error(fz_dot);
  590.      else
  591.         root_name := root.base_class_name;
  592.         !!root_proc_name.make(procedure,Void);
  593.         root_proc := root.root_procedure(procedure);
  594.      end;
  595.      if nb_errors = 0 then
  596.         if root_proc.arguments /= Void then
  597.            eh.add_position(root_proc.start_position);
  598.            eh.append("Creation procedure ");
  599.            eh.append(procedure);
  600.            eh.error(" must not have arguments.");
  601.         end;
  602.      end;
  603.      if nb_errors = 0 then
  604.         root_type := root.run_class.current_type;
  605.      end;
  606.      if nb_errors = 0 then
  607.         Result := root_proc.to_run_feature(root_type,root_proc_name);
  608.         if gc_handler.is_on then
  609.            Result.do_not_inline;
  610.         end;
  611.      end;
  612.      if nb_errors = 0 then
  613.         echo.put_string("Starting Falling Down (");
  614.         echo.put_integer(magic_count);
  615.         echo.put_string(em1);
  616.         from  
  617.            falling_down;
  618.            cecil_pool.fill_up;
  619.         until
  620.            magic = magic_count or else nb_errors > 0
  621.         loop
  622.            magic := magic_count;
  623.            falling_down;
  624.         end;
  625.         echo.put_string("End of Falling Down (");
  626.         echo.put_integer(magic_count);
  627.         echo.put_string(em1);
  628.      end;
  629.      if nb_errors = 0 then
  630.         echo.put_string("Starting AFD Check (");
  631.         echo.put_integer(magic_count);
  632.         echo.put_string(em1);
  633.         from
  634.            afd_check;
  635.         until
  636.            magic = magic_count or else nb_errors > 0
  637.         loop
  638.            magic := magic_count;
  639.            falling_down;
  640.            afd_check;
  641.         end;
  642.         echo.put_string("End of AFD Check (");
  643.         echo.put_integer(magic_count);
  644.         echo.put_string(em1);
  645.         check_for_deferred;
  646.      end;
  647.      if not eh.empty then
  648.         eh.append("Internal Warning #1 (Error Handler Not Empty) : ");
  649.         eh.print_as_warning;
  650.      end;
  651.      if nb_errors = 0 then
  652.         is_ready := true;
  653.         echo.print_count("Loaded Classe",base_class_dictionary.count);
  654.      end;
  655.       end;
  656.    
  657. feature -- To add more Context for some `to_runnable' :
  658.    
  659.    top_rf: RUN_FEATURE is
  660.       do
  661.      Result := stack_rf.item(top);
  662.       end;
  663.       
  664.    push(rf: RUN_FEATURE) is
  665.       do
  666.      top := top + 1;
  667.      stack_rf.force(rf,top);
  668.       end;
  669.    
  670.    pop is
  671.       do     
  672.      check
  673.         1 <= top;
  674.      end;
  675.      top := top - 1;
  676.       ensure
  677.      old(top) = top + 1
  678.       end;
  679.    
  680. feature {NONE}
  681.    
  682.    stack_rf: ARRAY[RUN_FEATURE] is
  683.       once
  684.      !!Result.make(1,50);
  685.       end;
  686.    
  687.    top: INTEGER;
  688.    
  689. feature {NONE}
  690.    
  691.    falling_down is
  692.       local
  693.      rc: RUN_CLASS;
  694.      i: INTEGER;
  695.       do
  696.      switch_collection.falling_down;
  697.      from
  698.         i := 1;
  699.      until
  700.         i > run_class_dictionary.count
  701.      loop
  702.         rc := run_class_dictionary.item(i);
  703.         rc.falling_down;
  704.         i := i + 1;
  705.      end;
  706.       end;
  707.  
  708.    afd_check is
  709.       local
  710.      rc: RUN_CLASS;
  711.      i: INTEGER;
  712.       do
  713.      from
  714.         i := 1;
  715.      until
  716.         i > run_class_dictionary.count
  717.      loop
  718.         rc := run_class_dictionary.item(i);
  719.         rc.afd_check;
  720.         i := i + 1;
  721.      end;
  722.       end;
  723.  
  724. feature {RUN_FEATURE_9}
  725.  
  726.    afd_check_deferred(rf9: RUN_FEATURE) is
  727.       do
  728.      if not rf9_memory.fast_has(rf9) then
  729.         rf9_memory.add_last(rf9);
  730.      end;
  731.       end;
  732.  
  733. feature {NONE}
  734.  
  735.    rf9_memory: FIXED_ARRAY[RUN_FEATURE] is
  736.       once
  737.      !!Result.with_capacity(256);
  738.       end;
  739.  
  740.    check_for_deferred is
  741.       local
  742.      i: INTEGER;
  743.      rf9: RUN_FEATURE;
  744.      rc: RUN_CLASS;
  745.       do
  746.      from
  747.         i := rf9_memory.upper
  748.         echo.print_count("Deferred Routine",i+1);
  749.      until
  750.         i < 0
  751.      loop
  752.         rf9 := rf9_memory.item(i);
  753.         rc := rf9.current_type.run_class;
  754.         if rc.at_run_time then
  755.            eh.add_position(rf9.start_position);
  756.            eh.append(rf9.name.to_string);
  757.            eh.append(" is a deferred feature in ");
  758.            eh.append(rf9.current_type.written_mark);
  759.            fatal_error(fz_dot);
  760.         end;
  761.         i := i - 1;
  762.      end;
  763.       end;
  764.  
  765. feature {CST_ATT_UNIQUE}
  766.    
  767.    next_unique: INTEGER is
  768.       do
  769.      if last_unique < 1000 then        
  770.         last_unique := 1000
  771.      end;
  772.      last_unique := last_unique + 1;
  773.      Result := last_unique;
  774.       end;
  775.    
  776. feature {C_PRETTY_PRINTER}
  777.  
  778.    define_extern_tables is
  779.       local
  780.      size: INTEGER;
  781.       do
  782.      size := id_provider.max_id + 1;
  783.      if cpp.generator_used then
  784.         cpp.put_extern4(fz_t7_star,"g",size);
  785.      end;
  786.      if cpp.generating_type_used then
  787.         cpp.put_extern4(fz_t7_star,"t",size);
  788.      end;
  789.      if run_control.no_check then
  790.         cpp.put_extern4("char*","p",size);
  791.      end;
  792.       end;
  793.    
  794.    initialize_path_table is
  795.       require
  796.      cpp.on_c;
  797.       local
  798.      i: INTEGER;
  799.      bc: BASE_CLASS;
  800.      rc: RUN_CLASS;
  801.       do
  802.      from  
  803.         cpp.put_string("p[0]=%"???%";%N");
  804.         i := 1;
  805.      until
  806.         i > base_class_dictionary.count
  807.      loop
  808.         bc := base_class_dictionary.item(i);
  809.         cpp.put_string("p[");
  810.         cpp.put_integer(bc.id);
  811.         cpp.put_string("]=");
  812.         cpp.put_string_c(bc.path);
  813.         cpp.put_string(fz_00);
  814.         i := i + 1;
  815.      end;     
  816.      from  
  817.         i := 1;
  818.      until
  819.         i > run_class_dictionary.count
  820.      loop
  821.         rc := run_class_dictionary.item(i);
  822.         if rc.at_run_time and then rc.current_type.is_generic then
  823.            cpp.put_string("p[");
  824.            cpp.put_integer(rc.id);
  825.            cpp.put_string("]=p[");
  826.            cpp.put_integer(rc.base_class.id);
  827.            cpp.put_string("];%N");
  828.         end;
  829.         i := i + 1;
  830.      end;     
  831.       ensure
  832.      cpp.on_c;
  833.       end;
  834.    
  835.    initialize_generator is
  836.       require
  837.      cpp.on_c;
  838.       local
  839.      i: INTEGER;
  840.      bc: BASE_CLASS;
  841.      rc: RUN_CLASS;
  842.       do
  843.      from  
  844.         i := 1;
  845.      until
  846.         i > base_class_dictionary.count
  847.      loop
  848.         bc := base_class_dictionary.item(i);
  849.         cpp.put_string("g[");
  850.         cpp.put_integer(bc.id);
  851.         cpp.put_string("]=e2s(");
  852.         cpp.put_string_c(bc.base_class_name.to_string);
  853.         cpp.put_string(fz_14);
  854.         i := i + 1;
  855.      end;     
  856.      from  
  857.         i := 1;
  858.      until
  859.         i > run_class_dictionary.count
  860.      loop
  861.         rc := run_class_dictionary.item(i);
  862.         if rc.at_run_time and then rc.current_type.is_generic then
  863.            cpp.put_string("g[");
  864.            cpp.put_integer(rc.id);
  865.            cpp.put_string("]=g[");
  866.            cpp.put_integer(rc.base_class.id);
  867.            cpp.put_string("];%N");
  868.         end;
  869.         i := i + 1;
  870.      end;     
  871.       ensure
  872.      cpp.on_c;
  873.       end;
  874.    
  875.    initialize_generating_type is
  876.       require
  877.      cpp.on_c;
  878.       local
  879.      i: INTEGER;
  880.      rc: RUN_CLASS;
  881.       do
  882.      from  
  883.         i := 1;
  884.      until
  885.         i > run_class_dictionary.count
  886.      loop
  887.         rc := run_class_dictionary.item(i);
  888.         if rc.at_run_time then
  889.            cpp.put_string("t[");
  890.            cpp.put_integer(rc.id);
  891.            cpp.put_string("]=");
  892.            if rc.current_type.is_generic then
  893.           cpp.put_string("e2s(");
  894.           cpp.put_string_c(rc.current_type.run_time_mark);
  895.           cpp.put_character(')');
  896.            else
  897.           cpp.put_string("g[");
  898.           cpp.put_integer(rc.id);
  899.           cpp.put_character(']');
  900.            end;
  901.            cpp.put_string(fz_00);
  902.         end;
  903.         i := i + 1;
  904.      end;     
  905.       ensure
  906.      cpp.on_c;
  907.       end;
  908.    
  909. feature {NONE}
  910.    
  911.    tmp_class_name: CLASS_NAME is
  912.       once
  913.      !!Result.make(us_any,Void);
  914.       end
  915.  
  916. feature {NONE}
  917.  
  918.    compile_routines is
  919.       -- Try to give the best order to the C output.
  920.       local
  921.      rc, rc_string: RUN_CLASS;
  922.      ct: TYPE;
  923.      deep, i: INTEGER;
  924.      stop: BOOLEAN;
  925.      bcn: STRING;
  926.       do
  927.      echo.put_string("Compiling/Sorting routines for ");
  928.      echo.put_integer(run_class_dictionary.count);
  929.      echo.put_string(" run classes :%N");
  930.      cpp.swap_on_c;
  931.      from   
  932.         i := 1;
  933.      until
  934.         i > run_class_dictionary.count
  935.      loop
  936.         rc := run_class_dictionary.item(i);
  937.         ct := rc.current_type;
  938.         if ct.is_basic_eiffel_expanded then
  939.            rc.compile_to_c(0);
  940.         elseif ct.is_string then
  941.            rc_string := rc;
  942.         end;
  943.         i := i + 1;
  944.      end;
  945.      from   
  946.         i := 1;
  947.      until
  948.         i > run_class_dictionary.count
  949.      loop
  950.         rc := run_class_dictionary.item(i);
  951.         ct := rc.current_type;
  952.         if ct.is_bit then
  953.            rc.compile_to_c(0);
  954.         end;
  955.         i := i + 1;
  956.      end;
  957.      from   
  958.         i := 1;
  959.      until
  960.         i > run_class_dictionary.count
  961.      loop
  962.         rc := run_class_dictionary.item(i);
  963.         bcn := rc.base_class_name.to_string;
  964.         if us_native_array = bcn then
  965.            rc.compile_to_c(0);
  966.         end;
  967.         i := i + 1;
  968.      end;
  969.      if rc_string /= Void then
  970.         rc_string.compile_to_c(0);
  971.      end;
  972.      from   
  973.         i := 1;
  974.      until
  975.         i > run_class_dictionary.count
  976.      loop
  977.         rc := run_class_dictionary.item(i);
  978.         ct := rc.current_type;
  979.         bcn := ct.base_class_name.to_string;
  980.         if us_array = bcn or else us_fixed_array = bcn then
  981.            rc.compile_to_c(0);
  982.         end;
  983.         i := i + 1;
  984.      end;
  985.      from   
  986.         i := 1;
  987.      until
  988.         i > run_class_dictionary.count
  989.      loop
  990.         rc := run_class_dictionary.item(i);
  991.         ct := rc.current_type;
  992.         if ct.is_generic then
  993.            rc.compile_to_c(0);
  994.         end;
  995.         i := i + 1;
  996.      end;
  997.      from -- General sorting :
  998.         deep := 6;
  999.      until
  1000.         stop
  1001.      loop
  1002.         from   
  1003.            stop := true;
  1004.            i := 1;
  1005.         until
  1006.            i > run_class_dictionary.count
  1007.         loop
  1008.            rc := run_class_dictionary.item(i);
  1009.            if not rc.compile_to_c_done then
  1010.           stop := false;
  1011.           rc.compile_to_c(deep);
  1012.            end;
  1013.            i := i + 1;
  1014.         end;
  1015.         deep := deep - 1;
  1016.      end;
  1017.       end;
  1018.  
  1019. feature {NONE}
  1020.    
  1021.    tmp_tail: STRING is
  1022.       once
  1023.      !!Result.make(64);
  1024.       end;
  1025.  
  1026. feature {NONE}
  1027.  
  1028.    last_unique: INTEGER;
  1029.  
  1030. feature {NONE}
  1031.  
  1032.    em1: STRING is " items).%N";
  1033.  
  1034. feature {NONE}
  1035.    
  1036.    append_loading_path_in(str: STRING) is
  1037.       local      
  1038.      i: INTEGER;
  1039.      sed: STRING;
  1040.       do
  1041.      str.append("%NLoading path is :%N");
  1042.      from  
  1043.         i := loading_path.lower;
  1044.      until
  1045.         i > loading_path.upper 
  1046.      loop
  1047.         str.extend('%"');
  1048.         str.append(loading_path.item(i));
  1049.         str.extend('%"');
  1050.         str.extend('%N');
  1051.         i := i + 1;
  1052.      end;
  1053.      str.append("Environment Variable %"");
  1054.      str.append(fz_se);
  1055.      sed := get_environment_variable(fz_se);
  1056.      str.append("%" is%N");
  1057.      if sed = Void then
  1058.         str.append("not set. ");
  1059.      else
  1060.         str.append("set to %"");
  1061.         str.append(sed);
  1062.         str.append("%". ");
  1063.      end;
  1064.      str.extend('%N');
  1065.       end;
  1066.  
  1067. end -- SMALL_EIFFEL
  1068.