home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / turbopas / tptc17sc.arc / TPCUNIT.INC < prev    next >
Text File  |  1988-03-26  |  13KB  |  606 lines

  1.  
  2. (*
  3.  * TPTC - Turbo Pascal to C translator
  4.  *
  5.  * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
  6.  *
  7.  *)
  8.  
  9.    
  10. (********************************************************************)
  11. (*
  12.  * process generic declaration section
  13.  *   dispatches to const, type, var, proc, func
  14.  *   enter with tok=section type
  15.  *   exit with tok=next section type
  16.  *
  17.  *)
  18.  
  19. procedure psection;
  20. begin
  21.    if recovery then
  22.    begin
  23.       while toktype <> keyword do
  24.          gettok;
  25.       {warning('Error recovery (psection)');}
  26.       recovery := false;
  27.    end;
  28.  
  29.    if debug_parse then write(' <section>');
  30.  
  31.    if (tok = 'EXTERNAL')  or (tok = 'OVERLAY') or
  32.       (tok = 'PROCEDURE') or (tok = 'FUNCTION') then
  33.       punit
  34.    else
  35.  
  36.    if tok = 'INTERFACE' then
  37.       pinterface
  38.    else
  39.    
  40.    if tok = 'IMPLEMENTATION' then
  41.       pimplementation
  42.    else
  43.    
  44.    if tok = 'USES' then
  45.    begin
  46.       puses;
  47.       if tok[1] = ';' then 
  48.          gettok;
  49.    end
  50.    else
  51.    
  52.    if tok = 'UNIT' then
  53.       comment_statement
  54.    else
  55.    
  56.    if tok = 'CONST' then
  57.       pconst
  58.    else
  59.  
  60.    if tok = 'TYPE' then
  61.       ptype
  62.    else
  63.  
  64.    if tok = 'VAR' then
  65.       pvar
  66.    else
  67.  
  68.    if tok = 'LABEL' then
  69.       plabel
  70.    else
  71.  
  72.    if tok[1] = '{' then
  73.       pblock
  74.    else
  75.  
  76.    if (tok[1] = '.') or (tok[1] = '}') then
  77.    begin
  78.       tok := '.';
  79.       exit;
  80.    end
  81.    else
  82.       syntax('Section header expected (psection)');
  83. end;
  84.  
  85.  
  86. (********************************************************************)
  87. (*
  88.  * process argument declarations to
  89.  *    program, procedure, function
  90.  *
  91.  * enter with header as tok
  92.  * exits with tok as ; or :
  93.  *
  94.  *)
  95.  
  96. const
  97.    extern = true;
  98.    
  99. procedure punitheader(is_external: boolean);
  100. var
  101.    proc:    string40;
  102.    proclit: string40;
  103.    vars:    paramlist;
  104.    types:   paramlist;
  105.    bases:   array [1..maxparam] of integer;
  106.    i:       integer;
  107.    ii:      integer;
  108.    rtype:   string40;
  109.    varval:  integer;
  110.    varon:   boolean;
  111.    locvar:  integer;
  112.    iptr:    integer;
  113.  
  114. begin
  115.    gettok;                 {skip unit type}
  116.    proclit := ltok;
  117.  
  118.    if (unitlevel > 1) and (not in_interface) then
  119.    begin
  120.       {make name unique if it clashes with an existing global}
  121.       if cursym = nil then
  122.          proc := proclit
  123.       else
  124.          proc := procnum + '_' + proclit;
  125.          
  126.       warning('Nested function');
  127.       
  128.       writeln(ofd[unitlevel-1],^M^J'   /* Nested function: ',proc,' */ ');
  129.       inc(objtotal,2);
  130.    end
  131.    else
  132.       proc := proclit;
  133.  
  134.    gettok;                 {skip unit identifier}
  135.  
  136.    vars.n := 0;
  137.    varval := 0;       { 0 bit means value, 1 = var }
  138.    varon  := false;
  139.  
  140.    (* process param list, if any *)
  141.    if tok[1] = '(' then
  142.    begin
  143.       gettok;
  144.  
  145.       while (tok[1] <> ')') and not recovery do
  146.       begin
  147.  
  148.          ii := vars.n + 1;
  149.          repeat
  150.             if tok[1] = ',' then
  151.                gettok;
  152.  
  153.             if tok = 'VAR' then
  154.             begin
  155.                gettok;
  156.                varon := true;
  157.             end;
  158.  
  159.             inc(vars.n);
  160.             if vars.n > maxparam then
  161.                fatal('Too many params (punitheader)');
  162.             vars.id[vars.n] := ltok;
  163.             gettok;
  164.  
  165.          until tok[1] <> ',';
  166.  
  167.          if tok[1] = ':' then       
  168.          begin
  169.             gettok;   {consume the :}
  170.    
  171.             {parse the param type}
  172.             rtype := psimpletype;
  173.          end
  174.          else
  175.  
  176.          begin    {untyped variable if ':' is missing}
  177.             rtype := 'void';
  178.             curtype := s_void;
  179.             curbase := 0;
  180.             cursuptype := ss_scalar; {ss_array?}
  181.          end;
  182.  
  183.          {assign and param types, converting 'var' and 'array' params}
  184.          iptr := 0;
  185.          if rtype[1] = '^' then
  186.             rtype[1] := '*';
  187.  
  188.          {flag var parameters; strings and arrays are implicitly var in C}
  189.          if varon and (curtype <> s_string) and (cursuptype <> ss_array) then
  190.             iptr := 1 shl (ii - 1);
  191.  
  192.          if curtype = s_string then
  193.             rtype := 'char *'
  194.          else
  195.          if cursuptype = ss_array then
  196.             rtype := typename[curtype] + ' *';
  197.  
  198.          {assign data types for each ident}
  199.          for i := ii to vars.n do   
  200.          begin
  201.             types.id[i] := rtype;
  202.             types.stype[i] := curtype;
  203.             types.sstype[i] := cursuptype;
  204.             bases[i] := curbase;
  205.             varval := varval or iptr;
  206.             iptr := iptr shl 1;
  207.          end;
  208.  
  209.          if tok[1] = ';' then
  210.          begin
  211.             gettok;
  212.             varon := false;
  213.          end;
  214.  
  215.       end;   {) seen}
  216.  
  217.       gettok;   {consume the )}
  218.    end;
  219.  
  220.    (* process function return type, if any *)
  221.    if tok[1] = ':' then
  222.    begin
  223.       gettok;            {consume the :}
  224.       rtype := psimpletype;
  225.  
  226.       if curtype = s_string then
  227.          rtype := 'char *'
  228.       else
  229.       if cursuptype = ss_array then
  230.          rtype := typename[curtype] + ' *';
  231.    end
  232.    else
  233.  
  234.    begin
  235.       rtype := 'void';
  236.       curtype := s_void;
  237.    end;
  238.  
  239.    putline;
  240.    
  241.    (* prefix procedure decl's when external *)
  242.    if is_external then
  243.    begin
  244.       putln(ljust('extern '+rtype,identlen)+proc+'();');
  245.       addsym(globals,proc,curtype,ss_func,0,varval,0,9,false);
  246.       exit;
  247.    end;
  248.  
  249.  
  250.    (* process 'as NEWNAME' clause, if present (tptc extention to specify
  251.       the replacement name in the symbol table *)
  252.    if tok = 'AS' then
  253.    begin
  254.       gettok;
  255.       proc := usetok;
  256.    end;
  257.     
  258.  
  259.    (* output the return type, proc name, formal param list *)
  260.    if in_interface then
  261.       rtype := 'extern '+rtype;
  262.    puts(ljust(rtype,identlen)+proc+'(');
  263.  
  264.    if vars.n = 0 then
  265.       puts('void');
  266.  
  267.  
  268.    (* output the formal param declarations *)
  269.    locvar := varval;
  270.    for i := 1 to vars.n do
  271.    begin
  272.       iptr := -1;
  273.  
  274.       if (locvar and 1) = 1 then
  275.       begin
  276.          iptr := -2;
  277.          types.id[i] := types.id[i] + ' *';
  278.       end;
  279.  
  280.       puts(ljust(types.id[i],identlen)+vars.id[i]);
  281.       addsym(locals,vars.id[i],types.stype[i],ss_scalar,iptr,0,0,bases[i],true);
  282.       locvar := locvar shr 1;
  283.  
  284.       if i < vars.n then
  285.       begin
  286.          putln(','); 
  287.          puts(ljust('',identlen+length(proc)+1));
  288.       end;
  289.    end;
  290.  
  291.    puts(')');
  292.    nospace := false;
  293.  
  294.    {enter the procedure in the global symbol table}
  295.    addsym(globals,proclit,curtype,ss_func,vars.n,varval,0,0,false);
  296.    cursym^.repid := proc;
  297. end;
  298.  
  299.  
  300. (********************************************************************)
  301. (*
  302.  * process body of program unit
  303.  *   handles all declaration sections
  304.  *   and a single begin...end
  305.  *   recursively handles procedure declarations
  306.  *   ends with tok=}
  307.  *)
  308.  
  309. procedure punitbody;
  310. begin
  311.    gettok;
  312.  
  313.    if tok = 'INTERRUPT' then
  314.    begin
  315.       warning('Interrupt handler');
  316.       gettok;
  317.    end;
  318.    
  319.    if tok = 'FORWARD' then
  320.    begin
  321.       puts(';');
  322.       gettok;
  323.    end
  324.    else
  325.  
  326.    if tok = 'EXTERNAL' then
  327.    begin
  328.       puts('/* ');
  329.       repeat
  330.          puttok;
  331.          gettok;
  332.       until tok[1] = ';';
  333.       puts(' */ ;');
  334.    end
  335.    else
  336.  
  337.    if tok = 'INLINE' then
  338.    begin
  339.       newline;
  340.       putln('{');
  341.       puts('   ');
  342.       pinline;
  343.       putln('}');
  344.    end
  345.    else
  346.  
  347.    begin
  348.       puts('{ ');
  349.  
  350.       repeat
  351.          if tok[1] = ';' then
  352.          begin
  353.             puttok;
  354.             gettok;
  355.          end;
  356.  
  357.          if tok[1] <> '{' then
  358.             psection;
  359.       until tok[1] = '{';
  360.  
  361.       gettok;                 {get first token of first statement}
  362.  
  363.       while (tok[1] <> '}') and not recovery do
  364.       begin
  365.          pstatement;             {process the statement}
  366.  
  367.          if tok[1] = ';' then
  368.          begin
  369.             puttok;
  370.             gettok;              {get first token of next statement}
  371.          end;
  372.       end;
  373.  
  374.       puttok;
  375.    end;
  376. end;
  377.  
  378.  
  379. (********************************************************************)
  380. procedure enter_procdef;
  381.    {increase output file level and direct output to the new file}
  382. var
  383.    nam:  anystring;
  384. begin
  385.    {increment this procedure number}
  386.    inc(procnum[2]);
  387.    if procnum[2] > 'Z' then
  388.    begin
  389.       inc(procnum[1]);
  390.       procnum[2] := 'A';
  391.    end;
  392.  
  393.    inc(unitlevel);
  394.    if unitlevel > maxnest then
  395.       fatal('Functions nested too deeply');
  396.  
  397.    str(unitlevel,nam);
  398.    nam := workdir + nestfile + nam;
  399.  
  400.    assign(ofd[unitlevel],nam);
  401.    {$i-} rewrite(ofd[unitlevel]); {$i+}
  402.  
  403.    if ioresult <> 0 then
  404.    begin
  405.       dec(unitlevel);
  406.       ltok := nam;
  407.       fatal('Can''t create tempfile');
  408.    end;
  409.  
  410.    if maxavail-300 <= inbufsiz then
  411.    begin
  412.       ltok := nam;
  413.       fatal('Out of memory');
  414.    end;
  415.  
  416.    getmem(outbuf[unitlevel],inbufsiz);
  417.    SetTextBuf(ofd[unitlevel],outbuf[unitlevel]^,inbufsiz);
  418. end;
  419.  
  420.  
  421. (********************************************************************)
  422. procedure exit_procdef;
  423.    {copy the outer output file to the next lower level output
  424.     and reduce output level by 1}
  425. var
  426.    line:  string;
  427.  
  428. begin
  429.    if unitlevel < 1 then 
  430.       exit;
  431.    
  432.    close(ofd[unitlevel]);
  433.    reset(ofd[unitlevel]);
  434.    SetTextBuf(ofd[unitlevel],outbuf[unitlevel]^,inbufsiz);
  435.  
  436.    while not eof(ofd[unitlevel]) do
  437.    begin
  438.       readln(ofd[unitlevel],line);
  439.       writeln(ofd[0],line);
  440.    end;
  441.  
  442.    close(ofd[unitlevel]);
  443.    erase(ofd[unitlevel]);
  444.    freemem(outbuf[unitlevel],inbufsiz);
  445.    dec(unitlevel);
  446. end;
  447.  
  448.  
  449. (********************************************************************)
  450. (*
  451.  * process program, procedure and function declaration
  452.  *
  453.  * enter with tok=function
  454.  * exit with tok=;
  455.  *
  456.  *)
  457.  
  458. procedure punit;
  459. var
  460.    top: symptr;
  461. begin
  462.    if debug_parse then write(' <unit>');
  463.  
  464.    nospace := true;
  465.    top := locals;
  466.  
  467.    if (tok = 'OVERLAY') then
  468.       gettok;
  469.  
  470.    if (tok = 'EXTERNAL') then  {mt+}
  471.    begin
  472.       gettok;      {consume the EXTERNAL}
  473.  
  474.       if tok[1] = '[' then
  475.       begin
  476.          gettok;   {consume the '['}
  477.  
  478.          puts('/* overlay '+ltok+' */ ');
  479.          gettok;   {consume the overlay number}
  480.  
  481.          gettok;   {consume the ']'}
  482.       end;
  483.  
  484.       punitheader(extern);
  485.       if tok[1] = ';' then
  486.          gettok;
  487.       purgetable(locals,top);
  488.    end
  489.    else
  490.  
  491.    if in_interface then
  492.    begin
  493.       nospace := false;
  494.       punitheader(not extern);
  495.  
  496.       puts(';');
  497.       if tok[1] = ';' then
  498.          gettok;
  499.       
  500.       if tok = 'INLINE' then
  501.       begin
  502.          pinline;
  503.          warning('Inline procedure');
  504.       end;
  505.  
  506.       purgetable(locals,top);
  507.    end
  508.    else
  509.    
  510.    begin
  511.       {enter a (possibly nested) procedure}
  512.       enter_procdef;
  513.  
  514.       punitheader(not extern);
  515.       punitbody;
  516.       gettok;
  517.       if tok[1] = ';' then
  518.          gettok;
  519.       purgetable(locals,top);
  520.  
  521.       {exit the (possibly nested) procedure, append text to toplevel outfile}
  522.       exit_procdef;
  523.    end;
  524.  
  525. end;
  526.  
  527.  
  528.  
  529. (********************************************************************)
  530. (*
  531.  * process main program
  532.  *
  533.  *  expects program head
  534.  *  optional declarations
  535.  *  block of main code
  536.  *  .
  537.  *
  538.  *)
  539.  
  540. procedure pprogram;
  541. begin
  542.    putline;
  543.    putln('/*');
  544.    putln(' * Generated by '+version1);
  545.    putln(' *     '+version2);
  546.    putln(' */');
  547.    putln('#include "tptcmac.h"');
  548.    
  549.    getchar;  {get first char}
  550.    gettok;   {get first token}
  551.  
  552.    if (tok = 'PROGRAM') or (tok = 'UNIT') then
  553.    begin
  554.       comment_statement;
  555.       gettok;
  556.    end;
  557.  
  558.    if tok = 'MODULE' then
  559.    begin
  560.       mt_plus := true;   {shift into pascal/mt+ mode}
  561.       comment_statement;
  562.       gettok;
  563.    end;
  564.  
  565.    repeat
  566.       if tok[1] = ';' then
  567.       begin
  568.          puttok;
  569.          gettok;
  570.       end;
  571.  
  572.       if tok = 'MODEND' then
  573.          exit;
  574.  
  575.       if (tok[1] <> '{') then
  576.          psection;
  577.    until (tok[1] = '{') or (tok[1] = '.') or recovery;
  578.  
  579.    {process the main block, if any}
  580.    if tok[1] = '{' then
  581.    begin
  582.       putline;
  583.       putln('main(int   argc,');
  584.       putln('     char  *argv[])');
  585.       
  586.       puttok;
  587.       gettok;                 {get first token of main block}
  588.    
  589.       while (tok[1] <> '}') and (tok[1] <> '.') do
  590.       begin
  591.          pstatement;                {process the statement}
  592.    
  593.          if tok[1] = ';' then
  594.          begin
  595.             puttok;
  596.             gettok;              {get first token of next statement}
  597.          end;
  598.       end;
  599.  
  600.       putln('}');
  601.    end;
  602.    
  603.    putline;
  604. end;
  605.  
  606.