home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / turbopas / tptc17sc.arc / TPCDECL.INC < prev    next >
Text File  |  1988-03-26  |  17KB  |  728 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.  * process pascal data type specifications
  12.  *
  13.  *)
  14.  
  15. function psimpletype: string80;
  16.    {parse a simple (single keyword and predefined) type; returns the
  17.     translated type specification; sets the current data type}
  18. var
  19.    sym: symptr;
  20.  
  21. begin
  22.    if debug_parse then write(' <simpletype>');
  23.  
  24.    sym := locatesym(ltok);
  25.    if sym <> nil then
  26.    begin
  27.       curtype := sym^.symtype;
  28.       if cursuptype = ss_none then
  29.          cursuptype := sym^.suptype;
  30.       curlimit := sym^.limit;
  31.       curbase := sym^.base;
  32.       curpars := sym^.parcount;
  33.    end;
  34.  
  35.    psimpletype := usetok;
  36. end;
  37.  
  38.  
  39. (********************************************************************)
  40. procedure pdatatype(stoclass: anystring;
  41.                     var vars: paramlist;
  42.                     prefix:   anystring;
  43.                     suffix:   anystring;
  44.                     addsemi:  boolean);
  45.    {parse any full data type specification;  input is a list of variables
  46.     to be declared with this data type; stoclass is a storage class prefix
  47.     (usually 'static ', '', 'typedef ', or 'extern '.  prefix and suffix
  48.     are variable name modifiers used in pointer and subscript translations;
  49.     recursive for complex data types}
  50.  
  51. const
  52.    forward_typedef: anystring = '';
  53.    forward_undef:   anystring = '';
  54.  
  55. var
  56.    i:      integer;
  57.    ts:     anystring;
  58.    ex:     anystring;
  59.    sym:    symptr;
  60.    nbase:  integer;
  61.    bbase:  integer;
  62.    nsuper: supertypes;
  63.    
  64.    procedure pvarlist;
  65.    var
  66.       i:    integer;
  67.       pcnt: integer;
  68.  
  69.    begin
  70.       ts := '';
  71.       pcnt := -1;
  72.             
  73.       if tok = 'ABSOLUTE' then
  74.       begin
  75.          if debug_parse then write(' <abs>');
  76.          gettok;        {consume the ABSOLUTE}
  77.          ts := pexpr;   {get the absolute lvalue}
  78.  
  79.          if tok[1] = ':' then    {absolute addressing}
  80.          begin
  81.             gettok;
  82.             ts := ' = MK_FP('+ts+','+pexpr+')';
  83.          end
  84.          
  85.          else                 {variable aliasing}
  86.          begin
  87.             if ts[1] = '*' then
  88.                ts := ' = ' + copy(ts,2,255)
  89.             else
  90.                ts := ' = &(' + ts + ')';
  91.          end;
  92.          
  93.          {convert new variable into a pointer if needed}
  94.          if length(prefix) = 0 then
  95.             prefix := '*';
  96.             
  97.          {force automatic pointer dereference in expressions}
  98.          pcnt := -2;
  99.       end;
  100.  
  101.       if cursuptype = ss_none then
  102.          cursuptype := ss_scalar;
  103.                           
  104.       for i := 1 to vars.n do
  105.       begin
  106.          newsym(vars.id[i],curtype,cursuptype,pcnt,withlevel,curlimit,nbase);
  107.          puts(prefix+vars.id[i]+suffix+ts);
  108.          if i < vars.n then
  109.             puts(', ');
  110.       end;
  111.    end;
  112.  
  113.  
  114.    procedure parray;
  115.    begin
  116.       if debug_parse then write(' <array>');
  117.       gettok;     {consume the ARRAY}
  118.  
  119.       repeat
  120.          gettok;        {consume the [ or ,}
  121.  
  122.          ts := pexpr;   {consume the lower subscript expression}
  123.          if isnumber(ts) then
  124.             nbase := atoi(ts)
  125.          else
  126.             nbase := curbase;
  127.  
  128.          if tok = '..' then
  129.          begin
  130.             gettok;   {consume the ..}
  131.             ts := pexpr;
  132.  
  133.             subtract_base(ts,nbase-1);
  134.          end
  135.          else
  136.  
  137.          begin    {subscript by typename - look up type range}
  138.             sym := locatesym(ts);
  139.             if sym <> nil then
  140.             begin
  141.                nbase := sym^.base;
  142.                if (sym^.limit > 0) and (sym^.suptype <> ss_const) then
  143.                   ts := ' /* ' + ts + ' */ ' + itoa(sym^.limit-nbase+1);
  144.             end;
  145.          end;
  146.    
  147.          suffix := suffix + '[' + ts + ']'; 
  148.  
  149.       until tok[1] <> ',';
  150.       
  151.       gettok;     {consume the ]}
  152.       gettok;     {consume the OF}
  153.  
  154.       cursuptype := ss_array;
  155.    end;
  156.  
  157.  
  158.    procedure pstring;
  159.    begin
  160.       if debug_parse then write(' <string>');
  161.       gettok;     {consume the STRING}
  162.  
  163.       if tok[1] = '[' then
  164.       begin
  165.          gettok;     {consume the [}
  166.  
  167.          nsuper := cursuptype;
  168.          ts := pexpr;
  169.          cursuptype := nsuper;
  170.          subtract_base(ts,-1);            {increment string size by one}
  171.          suffix := suffix + '[' + ts + ']'; 
  172.          
  173.          gettok;     {consume the ]}
  174.       end
  175.       else
  176.          suffix := suffix + '[STRSIZ]';
  177.  
  178.       puts(ljust(stoclass+'char',identlen));
  179.       curtype := s_string;
  180.       nbase := 1;
  181.       pvarlist;
  182.    end;
  183.  
  184.  
  185.    procedure ptext;
  186.    begin
  187.       if debug_parse then write(' <text>');
  188.       gettok;     {consume the TEXT}
  189.  
  190.       if tok[1] = '[' then
  191.       begin
  192.          gettok;     {consume the [}
  193.          nsuper := cursuptype;
  194.          ts := pexpr;
  195.          cursuptype := nsuper;
  196.          gettok;     {consume the ]}
  197.       end;
  198.  
  199.       puts(ljust(stoclass+'text',identlen));
  200.       curtype := s_file;
  201.       pvarlist;
  202.    end;
  203.  
  204.  
  205.    procedure pfile;
  206.    begin
  207.       if debug_parse then write(' <file>');
  208.       gettok;     {consume the FILE}
  209.  
  210.       if tok = 'OF' then
  211.       begin
  212.          gettok;     {consume the OF}
  213.          ts := tok;
  214.          gettok;     {consume the recordtype}
  215.          ts := '/* file of '+ts+' */ ';
  216.       end
  217.       else
  218.          ts := '/* untyped file */ ';
  219.  
  220.       puts(ljust(stoclass+'int',identlen)+ts);
  221.       curtype := s_file;
  222.       pvarlist;
  223.    end;
  224.  
  225.  
  226.    procedure pset;
  227.    begin
  228.       if debug_parse then write(' <set>');
  229.       gettok;     {consume the SET}
  230.       gettok;     {consume the OF}
  231.  
  232.       ts := '/* ';
  233.       if toktype = identifier then
  234.          ts := ts + usetok
  235.       else
  236.  
  237.       if tok = '(' then
  238.       begin
  239.          repeat
  240.             ts := ts + usetok
  241.          until (tok[1] = ')') or recovery;
  242.          ts := ts + usetok;
  243.       end
  244.  
  245.       else
  246.          ts := ts + psetof;
  247.  
  248.       puts(ljust(stoclass+'setrec',identlen)+ts+' */ ');
  249.       curtype := s_struct;
  250.       pvarlist;
  251.    end;
  252.  
  253.  
  254.    procedure pvariant;
  255.    begin
  256.       if debug_parse then write(' <variant>');
  257.       gettok;     {consume the CASE}
  258.  
  259.       ts := ltok;
  260.       gettok;     {consume the selector identifier}
  261.  
  262.       if tok[1] = ':' then
  263.       begin
  264.          gettok;     {consume the :}
  265.          puts(ltok+' '+ts+ ';  /* Selector */');
  266.          gettok;     {consume the selector type}
  267.       end
  268.       else
  269.          puts(' /* Selector is '+ts+' */');
  270.  
  271.       gettok;
  272.       puts('union { ');
  273.       newline;
  274.  
  275.       while (tok <> '}') and not recovery do
  276.       begin
  277.          ts := pexpr;      {parse the selector constant}
  278.          while tok[1] = ',' do
  279.          begin
  280.             gettok;
  281.             ts := pexpr;
  282.          end;
  283.  
  284.          gettok;    {consume the :}
  285.  
  286.          puts(' struct {  ');
  287.  
  288.          ts := 's' + ts;
  289.          decl_prefix := 'v.'+ts+'.';
  290.          pvar;
  291.          decl_prefix := '';
  292.          
  293.          gettok;    {consume the ')'}
  294.  
  295.          puts(' } '+ts+';');
  296.  
  297.          {arrange for reference translation}
  298.          newsym(ts,s_void,ss_struct,-1,0,0,0);
  299.          cursym^.repid := ts;
  300.  
  301.          if tok[1] = ';' then
  302.             gettok;
  303.       end;
  304.  
  305.       puts(' } v;');
  306.       newline;
  307.    end;
  308.  
  309.  
  310.    procedure precord;
  311.    begin
  312.       if debug_parse then write(' <record>');
  313.       puts(stoclass+'struct '+vars.id[1]+' { ');
  314.  
  315.       inc(withlevel);
  316.       pvar;     {process each record member}
  317.  
  318.       if tok = 'CASE' then    {process the variant part, if any}
  319.          pvariant;
  320.       dec(withlevel);
  321.  
  322.       puttok;   {output the closing brace}
  323.       gettok;   {and consume it}
  324.  
  325.       curtype := s_struct;
  326.       cursuptype := ss_struct;
  327.       pvarlist; {output any variables of this record type}
  328.  
  329.       {convert a #define into a typedef in case of a forward pointer decl}
  330.       if length(forward_typedef) > 0 then
  331.       begin
  332.          puts(';'); 
  333.          newline;
  334.          puts(forward_undef); 
  335.          newline;
  336.          puts(forward_typedef);
  337.          forward_typedef := '';
  338.       end;
  339.    end;
  340.  
  341.  
  342.    procedure penum;
  343.    var
  344.       members: integer;
  345.  
  346.    begin
  347.       if debug_parse then write(' <enum>');
  348.       puts(stoclass+'enum {  ');
  349.  
  350.       gettok;
  351.       members := 0;
  352.       repeat
  353.          puts(ltok);
  354.          if toktype = identifier then
  355.             inc(members);
  356.          gettok;
  357.       until (tok[1] = ')') or recovery;
  358.  
  359.       puts(' } ');
  360.       gettok;   {consume the )}
  361.  
  362.       curtype := s_int;
  363.       curlimit := members-1;
  364.       nbase := 0;
  365.       pvarlist;
  366.    end;
  367.  
  368.  
  369.    procedure pintrange;
  370.    begin
  371.       if debug_parse then write(' <int.range>');
  372.       ex := pexpr;   {consume the lower limit expression}
  373.       nbase := atoi(ex);
  374.       
  375.       if tok <> '..' then
  376.       begin
  377.          syntax('".." expected');
  378.          exit;
  379.       end;
  380.       
  381.       gettok;        {consume the ..}
  382.       ts := pexpr;   {consume the number}
  383.  
  384.       sym := locatesym(ts);
  385.       if sym <> nil then
  386.          if sym^.limit > 0 then
  387.             ts := itoa(sym^.limit);
  388.  
  389.       curtype := s_int;
  390.       curlimit := atoi(ts);
  391.       puts(ljust(stoclass+'int',identlen)+'/* '+ex+'..'+ts+' */ ');
  392.       pvarlist;
  393.    end;
  394.  
  395.    procedure pcharrange;
  396.    begin
  397.       if debug_parse then write(' <char.range>');
  398.       ex := pexpr;   {consume the lower limit expression}
  399.       nbase := ord(ex[2]);
  400.  
  401.       if tok <> '..' then
  402.       begin
  403.          syntax('".." expected');
  404.          exit;
  405.       end;
  406.  
  407.       gettok;        {consume the ..}
  408.       ts := pexpr;   {consume the number}
  409.  
  410.       sym := locatesym(ts);
  411.       if sym <> nil then
  412.          if sym^.limit > 0 then
  413.             ts := itoa(sym^.limit);
  414.  
  415.       curtype := s_char;
  416.       curlimit := ord(ts[2]);
  417.       puts(ljust(stoclass+'char',identlen)+'/* '+ex+'..'+ts+' */ ');
  418.       pvarlist;
  419.    end;
  420.  
  421.    procedure psimple;
  422.    begin
  423.       ex := psimpletype;
  424.       if cursuptype <> ss_array then
  425.          nbase := curbase;
  426.       
  427.       if tok =  '..' then
  428.       begin
  429.          if debug_parse then write(' <range>');
  430.          gettok;        {consume the ..}
  431.          ts := pexpr;   {consume the high limit}
  432.    
  433.          sym := locatesym(ts);
  434.          if sym <> nil then
  435.             if sym^.limit > 0 then
  436.                ts := itoa(sym^.limit);
  437.    
  438.          curtype := s_int;
  439.          curlimit := curbase;
  440.          puts(ljust(stoclass+'int',identlen)+'/* '+ex+'..'+ex+' */ ');
  441.          pvarlist;
  442.          exit;
  443.       end;
  444.  
  445.       {pointer to simpletype?}      
  446.       i := pos('^',ex);
  447.       if i <> 0 then
  448.       begin
  449.          if debug_parse then write(' <pointer>');
  450.          delete(ex,i,1);
  451.          prefix := '*';
  452.          cursuptype := ss_pointer;
  453.       end;
  454.    
  455.       sym := locatesym(ex);
  456.       
  457.       {potential forward pointer reference?}
  458.       if (stoclass = 'typedef ') and (vars.n = 1) and 
  459.          (prefix = '*') and (sym = nil) then
  460.       begin
  461.          if debug_parse then write(' <forward>');
  462.          newsym(vars.id[1],curtype,cursuptype,-1,0,curlimit,0);
  463.          puts(ljust('#define '+vars.id[1],identlen)+'struct '+ex+' *');
  464.          forward_undef := '#undef '+vars.id[1];
  465.          forward_typedef := 'typedef struct '+ex+' *'+vars.id[1];
  466.          addsemi := false;
  467.       end
  468.       else
  469.  
  470.       {ordinary simple types}
  471.       begin
  472.          if debug_parse then write(' <simple>');
  473.          puts(ljust(stoclass+ex,identlen));
  474.          pvarlist;
  475.       end;
  476.    end;
  477.  
  478. begin
  479.    cursuptype := ss_none;
  480.    curlimit := 0;
  481.    nbase := 0;
  482.  
  483.    if tok = 'EXTERNAL' then
  484.    begin
  485.       gettok;     {consume the EXTERNAL}
  486.       stoclass := 'extern '+stoclass;
  487.    end;
  488.    
  489.    if tok = 'PACKED' then
  490.       gettok;
  491.    while tok = 'ARRAY' do
  492.       parray;
  493.    if tok = 'PACKED' then
  494.       gettok;
  495.  
  496.    if tok = 'STRING'        then pstring
  497.    else if tok = 'TEXT'     then ptext
  498.    else if tok = 'FILE'     then pfile
  499.    else if tok = 'SET'      then pset
  500.    else if tok = '('        then penum
  501.    else if tok = 'RECORD'   then precord
  502.    else if toktype = number then pintrange
  503.    else if toktype = chars  then pcharrange
  504.    else psimple;
  505.  
  506.    if addsemi then
  507.       puts(';');
  508.    puts(' ');
  509.  
  510.    if tok[1] = ';' then
  511.       gettok;
  512. end;
  513.  
  514.  
  515. (********************************************************************)
  516. (*
  517.  * declaration keyword processors
  518.  *   const, type, var, label
  519.  *
  520.  * all enter with tok=section type
  521.  * exit with tok=new section or begin or proc or func
  522.  *
  523.  *)
  524.  
  525. procedure pconst;
  526.    {parse and translate a constant section}
  527. var
  528.    vars:    paramlist;
  529.    parlev:  integer;
  530.    exp:     string;
  531.    dup:     boolean;
  532.  
  533. begin
  534.    if debug_parse then write(' <const>');
  535.    gettok;
  536.  
  537.    while (toktype <> keyword) and not recovery do
  538.    begin
  539.       nospace := false;
  540.       vars.n := 1;
  541.       vars.id[1] := ltok;
  542.  
  543.       gettok;    {consume the id}
  544.  
  545.       if tok[1] = '=' then     {untyped constant}
  546.       begin
  547.          if debug_parse then write(' <untyped.const>');
  548.  
  549.          {$b-} {requires short-circuit evaluation}
  550.          dup := (unitlevel > 0) and (cursym <> nil) and 
  551.                 (cursym^.suptype = ss_const);
  552.                      
  553.          gettok;   {consume the =}
  554.  
  555.          exp := pexpr;
  556.          curtype := cexprtype;
  557.          if isnumber(exp) then
  558.             curlimit := atoi(exp);
  559.             
  560.          {prefix identifier if needed to prevent conflict with other defines}
  561.          newsym(vars.id[1],curtype,ss_const,-1,0,curlimit,0);
  562.          if dup then
  563.          begin
  564.             vars.id[1] := procnum + '_' + vars.id[1];
  565.             cursym^.repid := vars.id[1];
  566.          end;
  567.          
  568.          puts(ljust('#define '+vars.id[1],identlen));
  569.          puts(exp);
  570.          puts('  ');
  571.  
  572.          gettok;   {consume the ;}
  573.       end
  574.       else
  575.  
  576.       begin               {typed constants}
  577.          if debug_parse then write(' <typed.const>');
  578.  
  579.          gettok;   {consume the :}
  580.  
  581.          pdatatype('',vars,'','',false);
  582.  
  583.          if tok[1] <> '=' then
  584.          begin
  585.             syntax('"=" expected');
  586.             exit;
  587.          end;
  588.             
  589.          gettok;   {consume the =}
  590.  
  591.          puts(' = ');
  592.          parlev := 0;
  593.  
  594.          repeat
  595.             if tok[1] = '[' then
  596.             begin
  597.                gettok;
  598.                exp := psetof;
  599.                gettok;
  600.                puts(exp);
  601.             end
  602.             else
  603.             
  604.             if tok[1] = '(' then
  605.             begin
  606.                inc(parlev);
  607.                puts('{');
  608.                gettok;
  609.             end
  610.             else
  611.  
  612.             if tok[1] = ')' then
  613.             begin
  614.                dec(parlev);
  615.                puts('}');
  616.                gettok;
  617.             end
  618.             else
  619.  
  620.             if tok[1] = ',' then
  621.             begin
  622.                puttok;
  623.                gettok;
  624.             end
  625.             else
  626.  
  627.             if (parlev > 0) and (tok[1] = ';') then
  628.             begin
  629.                puts(',');
  630.                gettok;
  631.             end
  632.             else
  633.  
  634.             if tok[1] <> ';' then
  635.             begin
  636.                exp := pexpr;
  637.                if tok[1] = ':' then
  638.                   gettok   {discard 'member-identifier :'}
  639.                else
  640.                   puts(exp);
  641.             end;
  642.  
  643.          until ((parlev = 0) and (tok[1] = ';')) or recovery;
  644.  
  645.          puttok;      {output the final ;}
  646.          gettok;
  647.       end;
  648.    end;
  649. end;
  650.  
  651.  
  652. (********************************************************************)
  653. procedure ptype;
  654.    {parse and translate a type section}
  655. var
  656.    vars: paramlist;
  657.  
  658. begin
  659.    if debug_parse then write(' <type>');
  660.    gettok;
  661.  
  662.    while (toktype <> keyword) do
  663.    begin
  664.       vars.n := 1;
  665.       vars.id[1] := usetok;
  666.  
  667.       if tok = '=' then
  668.          gettok
  669.       else
  670.       begin
  671.          syntax('"=" expected');
  672.          exit;
  673.       end;
  674.       
  675.       nospace := false;
  676.       pdatatype('typedef ',vars,'','',true);
  677.    end;
  678.  
  679. end;
  680.  
  681.  
  682. (********************************************************************)
  683. procedure pvar;
  684.    {parse and translate a variable section}
  685. var
  686.    vars:  paramlist;
  687.    sto:   string20;
  688. begin
  689.    if debug_parse then write(' <var>');
  690.  
  691.    if in_interface and (withlevel = 0) then
  692.       sto := 'extern '
  693.    else
  694.       sto := '';
  695.  
  696.    vars.n := 0;
  697.    gettok;
  698.  
  699.    while (toktype <> keyword) and (tok[1] <> '}') and (tok[1] <> ')') do
  700.    begin
  701.       nospace := true;
  702.  
  703.       repeat
  704.          if tok[1] = ',' then
  705.             gettok;
  706.  
  707.          inc(vars.n);
  708.          if vars.n > maxparam then
  709.             fatal('Too many identifiers (pvar)');
  710.          vars.id[vars.n] := ltok;
  711.          gettok;
  712.       until tok[1] <> ',';
  713.  
  714.       if tok[1] <> ':' then       
  715.       begin
  716.          syntax('":" expected');
  717.          exit;
  718.       end;
  719.          
  720.       gettok;   {consume the :}
  721.       nospace := false;
  722.       pdatatype(sto,vars,'','',true);
  723.       vars.n := 0;
  724.    end;
  725. end;
  726.  
  727.  
  728.