[comp.sources.misc] v04i024: Turbo Pascal to C, part 3/4

alan@leadsv.UUCP (Alan Strassberg) (08/15/88)

Posting-number: Volume 4, Issue 24
Submitted-by: "Alan Strassberg" <alan@leadsv.UUCP>
Archive-name: tptc/Part3

[WARNING!!!  This software is shareware and copyrighted.  Those who do not
accept such programs should give this a miss.  ++bsa]

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--   1 allbery  System     22616 Aug 14 16:46 tpcstmt.inc
# -rw-r--r--   1 allbery  System      7059 Aug 14 16:46 tpcsym.inc
# -rw-r--r--   1 allbery  System     12098 Aug 14 16:46 tpcunit.inc
# -rw-r--r--   1 allbery  System     11061 Aug 14 16:46 tptc.doc
#
echo 'x - tpcstmt.inc'
if test -f tpcstmt.inc; then echo 'shar: not overwriting tpcstmt.inc'; else
sed 's/^X//' << '________This_Is_The_END________' > tpcstmt.inc
X
X(*
X * TPTC - Turbo Pascal to C translator
X *
X * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
X *
X *)
X
X(********************************************************************)
X(*
X * control statement processors
X *    for, while, repeat, with, idents
X *
X * all expect tok to be keyword
X * all exit at end of statement with ltok as ; or end
X *
X *)
X
Xprocedure pfor;
Xvar
X   up:       boolean;
X   id:       string80;
X   low,high: string80;
X
Xbegin
X   if debug_parse then write(' <for>');
X
X   nospace := true;
X   puts('for (');
X   gettok;   {consume the FOR}
X
X   id := plvalue;
X   gettok;   {consume the :=}
X
X   low := pexpr;
X
X   if tok = 'TO' then
X      up := true
X   else
X
X   if tok = 'DOWNTO' then
X      up := false;
X
X   gettok;
X   high := pexpr;
X
X   if up then
X      puts(id+' = '+low+'; '+id+' <= '+high+'; '+id+'++) ')
X   else
X      puts(id+' = '+low+'; '+id+' >= '+high+'; '+id+'--) ');
X
X   nospace := false;
X   gettok;   {consume the DO}
X   pstatement;
Xend;
X
X
X(********************************************************************)
Xprocedure pwhile;
Xbegin
X   if debug_parse then write(' <while>');
X   gettok;   {consume the WHILE}
X
X   nospace := true;
X   puts('while ('+pexpr+') ');
X   nospace := false;
X
X   gettok;   {consume the DO}
X   pstatement;
Xend;
X
X
X(********************************************************************)
Xprocedure pwith;
Xvar
X   prefix: string;
X   levels: integer;
X   
Xbegin
X   if debug_parse then write(' <with>');
X   gettok;   {consume the WITH}
X
X   {warning('WITH not translated');}
X   levels := 0;
X   puts('{ ');
X   nospace := true;
X      
X   repeat
X      if tok[1] = ',' then 
X      begin
X         gettok;
X         newline;
X         puts('  ');
X      end;
X         
X      prefix := plvalue;
X      make_pointer(prefix);
X      
X      inc(levels);
X      inc(withlevel);
X      puts('void *with'+itoa(withlevel)+' = '+prefix+'; ');
X      
X   until tok[1] <> ',';
X   
X   nospace := false;
X   gettok;   {consume the DO}
X   
X   if tok[1] <> '{' then
X      pstatement
X   else
X
X   begin
X      gettok;                 {consume the open brace}
X   
X      while (tok[1] <> '}') and not recovery do
X      begin
X         pstatement;          {process the statement}
X   
X         if tok[1] = ';' then
X         begin
X            puttok;
X            gettok;           {get first token of next statement}
X         end;
X      end;
X      
X      gettok;                 {consume the close brace}
X   end;
X
X   puts('   } ');
X   newline;
X
X   if tok[1] = ';' then
X      gettok;
X
X   dec(withlevel,levels);
Xend;
X
X
X(********************************************************************)
Xprocedure prepeat;
Xbegin
X   if debug_parse then write(' <repeat>');
X   puts('do { ');
X   gettok;
X
X   while (tok <> 'UNTIL') and not recovery do
X   begin
X      pstatement;
X
X      if tok[1] = ';' then
X      begin
X         puttok;
X         gettok;
X      end;
X   end;
X
X   gettok;
X   nospace := true;
X   puts('}  while (!('+ pexpr+ '))');
X   nospace := false;
Xend;
X
X
X(********************************************************************)
Xprocedure pcase;
Xvar
X   ex:  string80;
X   ex2: string80;   
X   i:   integer;
X   c:   char;
X
Xbegin
X   if debug_parse then write(' <case>');
X   gettok;
X   ex := pexpr;
X   puts('switch ('+ex+') {');
X
X   gettok;   {consume the OF}
X
X   while (tok[1] <> '}') and (tok <> 'ELSE') and not recovery do
X   begin
X
X      repeat
X         if tok[1] = ',' then
X            gettok;
X
X         if tok = '..' then
X         begin
X            gettok;
X            ex2 := pexpr;
X            
X            if (ex2[1] = '''') or (ex2[1] = '"') then
X               for c := succ(ex[2]) to ex2[2] do
X               begin
X                  newline;
X                  puts('case '''+c+''':   ');
X               end
X            else
X            
X            if atoi(ex2) - atoi(ex) > 128 then
X            begin
X               ltok := ex+'..'+ex2;
X               warning('Gigantic case range');
X            end 
X            else
X            
X            for i := succ(atoi(ex)) to atoi(ex2) do
X            begin
X               newline;
X               write(ofd[unitlevel],'case ',i,':   ');
X            end;
X         end
X         else
X         
X         begin
X            ex := pexpr;
X            newline;
X            puts('case '+ex+':   ');
X         end;
X
X      until (tok[1] = ':') or recovery;
X      gettok;
X
X      if (tok[1] <> '}') and (tok <> 'ELSE') then
X         pstatement;
X      puts('break; ');
X      newline;
X
X      if tok[1] = ';' then
X         gettok;
X   end;
X
X   if tok = 'ELSE' then
X   begin
X      newline;
X      puts('default: ');
X      gettok;   {consume the else}
X
X      while (tok[1] <> '}') and not recovery do
X      begin
X         if (tok[1] <> '}') and (tok <> 'ELSE') then
X            pstatement;
X         if tok[1] = ';' then
X            gettok;
X      end;
X   end;
X
X   puttok;
X   gettok;
X
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
Xprocedure pif;
Xvar
X   pspace: integer;
Xbegin
X   if debug_parse then write(' <if>');
X   gettok;   {consume the IF}
X
X   pspace := length(spaces);
X   nospace := true;
X   puts('if ('+ pexpr+ ') ');
X   nospace := false;
X   
X   gettok;   {consume the THEN}
X
X   if (tok[1] <> '}') and (tok <> 'ELSE') then
X      pstatement;
X
X   if tok = 'ELSE' then
X   begin
X      spaces := copy(spaces,1,pspace);
X      if not linestart then
X         newline;
X      puts('else ');
X
X      gettok;
X      if tok[1] <> '}' then
X         pstatement;
X   end;
X
Xend;
X
X
X(********************************************************************)
Xprocedure pexit;
Xbegin
X   if debug_parse then write(' <exit>');
X   puts('return;');
X
X   gettok;
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
Xprocedure pgoto;
Xvar
X   ex:  anystring;
X
Xbegin
X   gettok;                      {consume the goto}
X
X   if toktype = number then
X      ltok := 'label_' + ltok;  {modify numeric labels}
X
X   puts('goto '+ltok+';');
X
X   gettok;                      {consume the label}
X
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
Xprocedure phalt;
Xvar
X   ex: anystring;
X
Xbegin
X   if debug_parse then write(' <halt>');
X   gettok;
X
X   if tok[1] = '(' then
X   begin
X      gettok;
X      ex := pexpr;
X      gettok;
X   end
X   else
X      ex := '0';     {default exit expression}
X
X   puts('exit('+ex+');');
X
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
Xprocedure pread;
Xvar
X   ctl:  string;
X   func: anystring;
X   ex:   paramlist;
X   p:    string;
X   ln:   boolean;
X   ty:   string[2];
X   i:    integer;
X
Xbegin
X   if debug_parse then write(' <read>');
X   
X   nospace := true;   {don't copy source whitespace to output during
X                       this processing.  this prevents spaces from
X                       getting moved around}
X
X   ln := tok = 'READLN';
X   nospace := true;
X   func := 'scanv(';
X
X   gettok;   {consume the read}
X
X   if tok[1] = '(' then
X   begin
X      gettok;
X
X      if ltok[1] = '[' then   {check for MT+ [addr(name)], form}
X      begin
X         gettok;   {consume the '[' }
X
X         if tok[1] = ']' then
X            func := 'scanf('
X         else
X
X         begin
X            gettok;   {consume the ADDR}
X            gettok;   {consume the '(' }
X            func := 'fiscanf(' + usetok + ',';
X            gettok;   {consume the ')'}
X         end;
X
X         gettok;   {consume the ']'}
X         if tok[1] = ',' then
X            gettok;
X      end;
X
X      ctl := '';
X      ex.n := 0;
X
X      while (tok[1] <> ')') and not recovery do
X      begin
X         p := pexpr;
X         ty := exprtype;
X
X         {convert to fprintf if first param is a file variable}
X         if (ex.n = 0) and (ty = '@') then
X            func := 'fscanv(' + p + ','
X         else
X
X         {process a new expression; add expressions to ex.id table
X          and append proper control codes to the control string}
X         begin
X            if ty <> 's' then
X               if p[1] = '*' then
X                  delete(p,1,1)
X               else
X                  p := '&' + p;
X            inc(ex.n);
X            if ex.n > maxparam then
X               fatal('Too many params (pread)');
X            ex.id[ex.n] := p;
X            ctl := ctl + '%'+ty;
X         end;
X
X         if tok[1] = ',' then
X            gettok;
X      end;
X
X      gettok;   {consume the )}
X
X      if ctl = '%s' then
X         ctl := '#';
X      if ln then
X         ctl := ctl + '\n';
X
X      if func[1] <> 'f' then
X         func := 'f' + func + 'stdin,';
X
X      puts(func+'"'+ctl+'"');
X      for i := 1 to ex.n do
X         puts(','+ex.id[i]);
X
X      puts(')');
X   end
X
X   else   {otherwise there is no param list}
X      if ln then
X         puts('scanf("\n")');
X
X   nospace := false;
X
X   if tok[1] = ';' then
X   begin
X      puttok;
X      gettok;
X   end
X   else
X
X   begin
X      puts('; ');
X      newline;
X   end;
X
Xend;
X
X
X(********************************************************************)
Xtype
X   write_modes = (m_write, m_writeln, m_str);
X
Xprocedure pwrite(mode: write_modes);
Xvar
X   ctl:  string;
X   func: anystring;
X   ex:   paramlist;
X   p:    string;
X   ty:   string[2];
X   i:    integer;
X
X   procedure addform(f: anystring);
X      {add a form parameter, special handling for form expressions}
X   begin
X      if isnumber(f) then
X         ctl := ctl + f      {pass literal form}
X      else
X      begin                      {insert form expression in parlist}
X         ctl := ctl + '*';
X         inc(ex.n);
X         if ex.n > maxparam then
X            fatal('Too many params (pwrite.form)');
X         ex.id[ex.n] := ex.id[ex.n-1];
X         ex.id[ex.n-1] := f;
X      end;
X   end;
X   
Xbegin
X   if debug_parse then write(' <write>');
X   
X   nospace := true;   {don't copy source whitespace to output during
X                       this processing.  this prevents spaces from
X                       getting moved around}
X
X   nospace := true;
X
X   if mode = m_str then
X      func := 'sbld('
X   else
X      func := 'printf(';
X      
X   gettok;   {consume the write}
X   
X   if tok[1] = '(' then
X   begin
X      gettok;   {consume the (}
X
X      if ltok[1] = '[' then   {check for MT+ [addr(name)], form}
X      begin
X         gettok;   {consume the '[' }
X
X         if tok[1] <> ']' then
X         begin
X            gettok;   {consume the ADDR}
X            gettok;   {consume the '(' }
X            func := 'iprintf(' + usetok + ',';
X            gettok;   {consume the ')'}
X         end;
X
X         gettok;   {consume the ']'}
X         if tok[1] = ',' then
X            gettok;
X      end;
X
X      ctl := '';
X      ex.n := 0;
X
X      while (tok[1] <> ')') and not recovery do
X      begin
X         p := pexpr;
X         ty := exprtype;
X
X         {convert to fprintf if first param is a file variable}
X         if (ex.n = 0) and (ty = '@') then
X            func := 'fprintf(' + p + ','
X         else
X
X         {process a new expression; add expressions to ex.id table
X          and append proper control codes to the control string}
X         begin
X            inc(ex.n);
X            if ex.n > maxparam then
X               fatal('Too many params (pwrite)');
X            ex.id[ex.n] := p;
X
X            if ty = 'D' then
X               ty := 'ld';
X            if ty = 'b' then
X               ty := 'd';
X
X            {decode optional form parameters}
X            if tok[1] = ':' then
X            begin
X               ctl := ctl + '%';
X               gettok;
X               addform(pexpr);               
X               
X               if tok[1] = ':' then
X               begin
X                  ctl := ctl + '.';
X                  gettok;
X                  addform(pexpr);
X                  ty := 'f';
X               end;
X               
X               ctl := ctl + ty;
X            end
X            else
X
X            begin
X               {pass literals into the control string}
X               if (p[1] = '"') or (p[1] = '''') then
X               begin
X                  ctl := ctl + copy(p,2,length(p)-2);
X                  dec(ex.n);
X               end
X
X               {otherwise put in the control string for this param}
X               else
X                  ctl := ctl + '%'+ty;
X            end;
X         end;
X
X         if tok[1] = ',' then
X            gettok;
X      end;
X
X      gettok;   {consume the )}
X
X      {add newline in 'writeln' translation}
X      if mode = m_writeln then
X         ctl := ctl + '\n';
X
X      {convert last parameter into destination in 'str' translation}
X      if mode = m_str then
X      begin
X         func := func + ex.id[ex.n] + ',';
X         dec(ex.n);
X         delete(ctl,length(ctl)-1,2);
X      end;
X
X      {produce the translated statement}
X      puts(func+'"'+ctl+'"');
X      for i := 1 to ex.n do
X         puts(','+ex.id[i]);
X
X      puts(')');
X   end
X
X   else   {otherwise there is no param list}
X      if mode = m_writeln then
X         puts('printf("\n")');
X
X   nospace := false;
X
X   if tok[1] = ';' then
X   begin
X      puttok;
X      gettok;
X   end
X   else
X
X   begin
X      puts('; ');
X      newline;
X   end;
X
Xend;
X
X
X(********************************************************************)
Xprocedure pnew;
Xvar
X   lv: string;
Xbegin
X   if debug_parse then write(' <new>');
X
X   gettok;   {consume the new}
X   gettok;   {consume the (}
X
X   lv := plvalue;
X   puts(lv+' = malloc(sizeof(*'+lv+'));');
X
X   gettok;   {consume the )}
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
Xprocedure pport(kw: string);
X   {translate port/portw/mem/memw}
Xvar
X   lv: string;
X
Xbegin
X   if debug_parse then write(' <port>');
X   lv := kw + '(';
X
X   gettok;     {consume the keyword}
X   gettok;     {consume the [ }
X
X   repeat
X      lv := lv + pexpr;
X      if tok[1] = ':' then
X      begin
X         gettok;
X         lv := lv + ',';
X      end;
X   until (tok[1] = ']') or recovery;
X
X   gettok;     {consume the ] }
X
X   if tok = ':=' then
X   begin
X      gettok;       {consume :=, assignment statement}
X      lv := lv + ',' + pexpr;
X   end;
X
X   puts(lv+');');
X
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
Xprocedure pinline;
X   {translate inline statements}
X
Xvar
X   sixteen: boolean;
X
Xbegin
X   if debug_parse then write(' <inline>');
X
X   gettok;     {consume the keyword}
X   nospace := true;
X   gettok;
X
X   while (tok[1] <> ')') and not recovery do
X   begin
X      if tok[1] = '/' then
X         gettok;
X
X      if tok[1] = '>' then
X      begin
X         gettok;
X         sixteen := true;
X      end
X      else
X         sixteen := htoi(ltok) > $00ff;
X
X      putline;
X      if sixteen then
X         puts('      asm DW '+ltok+'; ')
X      else
X         puts('      asm DB '+ltok+'; ');
X      gettok;
X   end;
X
X   nospace := false;
X   gettok;     {consume the ) }
X
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
Xprocedure pident;
X   {parse statements starting with an identifier;  these are either
X    assignment statements, function calls, return-value assignments,
X    or label identifiers}
Xvar
X   ex: string;
X   lv: string;
X   lvt,ext: char;
X
Xbegin
X   if debug_parse then write(' <ident>');
X
X   nospace := true;   {don't copy source whitespace to output during
X                       this processing.  this prevents spaces from
X                       getting moved around}
X
X   lv := plvalue;     {destination variable or function name}
X   lvt := exprtype;   {destination data type}
X
X   if tok = ':=' then
X   begin
X      if debug_parse then write(' <assign>');
X      
X      gettok;       {consume :=, assignment statement}
X      ex := pexpr;
X      ext := exprtype;
X
X      if iscall(lv) then      {assignment to function name}
X         puts('return '+ex)
X      else
X
X      begin
X         if copy(ex,1,5) = 'scat(' then
X            puts('sbld('+lv+',' + copy(ex,6,255))
X         else
X
X         if lvt = 's' then
X            if ext = 's' then
X               puts('strcpy('+lv+','+ex+')')
X            else
X               puts('sbld('+lv+',"%'+ext+'",'+ex+')')
X         else
X
X         if lvt = 'c' then
X            if ext = 's' then
X               puts(lv+' = first('+ex+')')
X            else
X               puts(lv+' = '+ex)
X         else
X            puts(lv+' = '+ex);
X      end;
X   end
X   else
X
X   if tok[1] = ':' then
X   begin
X      if debug_parse then write(' <label>');
X      
X      putline;
X      puts(lv+': ');
X
X      gettok;       {label identifier}
X
X      if tok[1] = ';' then
X         gettok;
X
X      exit;
X   end
X   else
X
X   begin   
X      if debug_parse then write(' <call>');
X
X      if iscall(lv) then
X         puts(lv)
X      else
X         puts(lv+'()');
X   end;
X   
X   nospace := false;
X
X   if tok[1] = ';' then
X   begin
X      puttok;
X      gettok;
X   end
X   else
X
X   begin
X      puts('; ');
X      {newline;?}
X   end;
X
Xend;
X
X
X
X
X(********************************************************************)
Xprocedure pnumlabel;
X   {parse statements starting with an number;  these must be
X    numeric labels}
Xbegin
X   if debug_parse then write(' <numlabel>');
X   putline;
X   puts('label_'+tok+': ');
X
X   gettok;      {consume the number}
X   gettok;      {consume the :}
Xend;
X
X
X(********************************************************************)
Xprocedure plabel;
X   {parse (and throw away) a label section}
Xbegin
X   if debug_parse then write(' <label>');
X
X   while tok[1] <> ';' do
X      gettok;
X
X   gettok;
Xend;
X
X
X
X
X(********************************************************************)
X(*
X * process single statement
X *
X * expects tok to be first token of statement
X * processes nested blocks
X * exits with tok as end of statement
X *
X *)
X
Xprocedure pstatement;
Xvar
X   builtin: boolean;
X   
Xbegin
X
X   if recovery then
X   begin
X      while tok[1] <> ';' do
X         gettok;
X      gettok;
X      {warning('Error recovery (pstatement)');}
X      recovery := false;
X      exit;
X   end;
X   
X   if (toktype = identifier) and (cursym <> nil) then
X      builtin := cursym^.suptype = ss_builtin
X   else
X      builtin := false;
X
X   if debug_parse then write(' <stmt>');
X
X   if toktype = number then
X      pnumlabel
X   else
X   
X   case tok[1] of
X   '.':
X      exit;
X
X   ';':
X      begin
X         puts('; ');
X         gettok;
X      end;
X      
X   '{':
X      pblock;
X
X   'C':
X      if tok = 'CASE' then
X         pcase
X      else
X         pident;
X
X   'E':
X      if builtin and (tok = 'EXIT') then
X         pexit
X      else
X         pident;
X
X   'F':
X      if tok = 'FOR' then
X         pfor
X      else
X         pident;
X      
X   'G':
X      if tok = 'GOTO' then
X         pgoto
X      else
X         pident;
X         
X   'H':
X      if tok = 'HALT' then
X         phalt
X      else
X         pident;
X         
X   'I':
X      if tok = 'IF' then
X         pif
X      else
X      if tok = 'INLINE' then
X         pinline
X      else
X         pident;
X         
X   'M':
X      if builtin and (tok = 'MEM') then
X         pport('pokeb')
X      else
X      if builtin and (tok = 'MEMW') then
X         pport('poke')
X      else
X         pident;
X         
X   'N':
X      if tok = 'NEW' then
X         pnew
X      else
X         pident;
X         
X   'P':
X      if builtin and (tok = 'PORT') then
X         pport('outportb')
X      else
X      if builtin and (tok = 'PORTW') then
X         pport('outport')
X      else
X         pident;
X         
X   'R':
X      if tok = 'REPEAT' then
X         prepeat
X      else
X      if tok = 'READ' then
X         pread
X      else
X      if tok = 'READLN' then
X         pread
X      else
X         pident;
X
X   'S':
X      if builtin and (tok = 'STR') then
X         pwrite(m_str)
X      else
X         pident;
X                  
X   'W':
X      if tok = 'WHILE' then
X         pwhile
X      else
X      if tok = 'WITH' then
X         pwith
X      else
X      if tok = 'WRITE' then
X         pwrite(m_write)
X      else
X      if tok = 'WRITELN' then
X         pwrite(m_writeln)
X      else
X         pident;
X   else
X      pident;
X   end;
Xend;
X
X
X(********************************************************************)
X(*
X * process begin...end blocks
X *
X * expects tok to be begin
X * exits with tok = end
X *
X *)
X
Xprocedure pblock;
Xbegin
X   if debug_parse then write(' <block>');
X
X   puts('{ ');
X   gettok;                 {get first token of first statement}
X
X   while (tok[1] <> '}') and not recovery do
X   begin
X      pstatement;          {process the statement}
X
X      if tok[1] = ';' then
X      begin
X         puttok;
X         gettok;           {get first token of next statement}
X      end;
X   end;
X
X   if not linestart then
X      newline;
X      
X   puttok;                 {put the closing brace}
X
X   gettok;
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
X(*
X * process interface, implementation and uses statements
X *
X *)
X
X(********************************************************************)
Xprocedure puses;
X   {parse a uses clause}
Xbegin
X   if debug_parse then write(' <uses>');
X
X   gettok;     {consume the USES}
X   
X   repeat
X
X      {generate an include for the unit header file}
X      puts('#include "'+ltok+'.UNH"');
X      newline;                      
X      
X      {load the saved unit header symbol table}
X      load_unitfile(ltok+'.UNS',globals);
X
X      {move interface section to skip new entries}
X      top_interface := globals;     
X      
X      gettok;                       {consume the unit name}
X      if tok[1] = ',' then
X         gettok;
X   until (tok[1] = ';') or recovery;
X   
Xend;
X
X
X(********************************************************************)
Xprocedure pinterface;
Xbegin
X   if debug_parse then write(' <interface>');
X   gettok;
X   if tok = 'USES' then
X      puses;
X      
X   in_interface := true;
X   top_interface := globals;
X
X   putline;
X   putln('#define extern /* globals defined here */');
X   putln('#include "'+unitname+'.UNH"');
X   putln('#undef extern');
X   
X   inc(unitlevel);
X   assign(ofd[unitlevel],unitname+'.UNH');
X   rewrite(ofd[unitlevel]);
X   getmem(outbuf[unitlevel],inbufsiz);
X   SetTextBuf(ofd[unitlevel],outbuf[unitlevel]^,inbufsiz);
X
X   putline;
X   putln('/* Unit header for: '+outname+' -- Made by '+version1+' */');
X
X   if tok[1] = ';' then
X      gettok;
Xend;
X
X
X(********************************************************************)
Xprocedure pimplementation;
Xbegin
X   if debug_parse then write(' <implementation>');
X   if not in_interface then
X      exit;
X   in_interface := false;
X
X   {terminate the .unh file being generated}
X   close(ofd[unitlevel]);
X   freemem(outbuf[unitlevel],inbufsiz);
X   dec(unitlevel);
X   
X   {create the requested unit symbol file}
X   create_unitfile(unitname+'.UNS',globals,top_interface);
X
X   gettok;
Xend;
X
X
________This_Is_The_END________
if test `wc -c < tpcstmt.inc` -ne 22616; then
	echo 'shar: tpcstmt.inc was damaged during transit (should have been 22616 bytes)'
fi
fi		; : end of overwriting check
echo 'x - tpcsym.inc'
if test -f tpcsym.inc; then echo 'shar: not overwriting tpcsym.inc'; else
sed 's/^X//' << '________This_Is_The_END________' > tpcsym.inc
X
X(*
X * TPTC - Turbo Pascal to C translator
X *
X * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
X *
X *)
X
X(********************************************************************)
Xfunction findsym( table: symptr;
X                  id:    string40): symptr;
X   {locate a symbol in a specified symbol table.  returns pointer to
X    the entry if found, otherwise nil is returned}
Xvar
X   sym: symptr;
X   
Xbegin
X   stoupper(id);
X   
X   sym := table;
X   while sym <> nil do
X   begin
X
X      if sym^.id[1] = id[1] then             {for speed, try first char}
X      if length(sym^.id) = length(id) then   {... then verify length}
X      if sym^.id = id then                   {... finally compare strings}
X      begin
X         findsym := sym;    {symbol found}
X         exit;
X      end;
X
X      sym := sym^.next;
X   end;
X
X   findsym := nil;   {symbol not found}
Xend;
X
X
X(********************************************************************)
Xfunction locatesym(id:    string40): symptr;
X   {locate a symbol in either the local or the global symbol table.
X    returns the symbol table entry pointer, if found.  returns
X    nil when not in either table}
Xvar
X   sym: symptr;
X
Xbegin
X   if id[1] = '^' then
X      delete(id,1,1);
X      
X   sym := findsym(locals,id);
X   if sym = nil then
X      sym := findsym(globals,id);
X
X   locatesym := sym;
Xend;
X
X
X(********************************************************************)
Xprocedure addsym( var table: symptr;
X                  id:        string40;
X                  symtype:   symtypes;
X                  suptype:   supertypes;
X                  parcount:  integer;
X                  varmap:    integer;
X                  lim:       integer;
X                  base:      integer;
X                  dup_ok:    boolean);
X   {add a symbol to a specific symbol table.  duplicates hide prior entries.
X    new symbol pointed to by cursym}
Xbegin
X   if maxavail-300 < sizeof(cursym^) then
X   begin
X      ltok := id;
X      fatal('Out of memory');
X   end;
X
X   if (not dup_ok) and (not in_interface) then
X   begin
X      cursym := findsym(table,id);
X      if cursym <> nil then
X      begin
X         ltok := id;
X         if (cursym^.parcount <> parcount) or 
X            (cursym^.symtype <> symtype) or (cursym^.limit <> lim) then
X            warning('Redeclaration not identical');
X         ltok := tok;
X      end;
X   end;
X   
X   new(cursym);
X   cursym^.next := table;
X   table := cursym;
X
X   cursym^.repid := decl_prefix + id;
X   stoupper(id);
X   cursym^.id := id;
X   cursym^.symtype := symtype;
X   cursym^.suptype := suptype;
X   cursym^.parcount := parcount;
X   cursym^.limit := lim;
X   cursym^.base := base;
X   cursym^.pvar := varmap;
Xend;
X
X
X(********************************************************************)
Xprocedure newsym( id:       string40;
X                  symtype:  symtypes;
X                  suptype:  supertypes;
X                  parcount: integer;
X                  varmap:   integer;
X                  lim:      integer;
X                  base:     integer);
X   {enter a new symbol into the current symbol table (local or global)}
Xbegin
X   if (unitlevel = 0) or (in_interface) then
X      addsym(globals,id,symtype,suptype,parcount,varmap,lim,base,false)
X   else
X      addsym(locals,id,symtype,suptype,parcount,varmap,lim,base,true);
Xend;
X
X
X
X(********************************************************************)
Xprocedure dumptable(sym: symptr; top: symptr);
X   {dump entries from the specified symbol table, stopping where indicated}
Xvar
X   info: string40;
X   
Xbegin
X      
X   if (not dumpsymbols) or (sym = nil) or (sym = top) then
X      exit;
X
X   {putline;}
X   putln('/* User symbols:');
X   putln(' *    Class        Type        Base   Limit Pars  Pvar   Identifier');
X   putln(' *   ------------ ------------ ----- ------ ---- ------ --------------');
X   
X   while (sym <> nil) and (sym <> top) do
X   begin
X   
X      if sym^.repid = '<predef>' then
X      begin
X         if dumppredef then
X         begin
X            putln(' *');
X            putln(' * Predefined symbols:');
X            putln(' *    Class        Type        Base   Limit Pars  Pvar   Identifier');
X            putln(' *   ------------ ------------ ----- ------ ---- ------ --------------');
X         end
X         else
X            sym := nil;
X      end
X      else
X      
X      begin         
X         write(ofd[unitlevel],' *    ',
X           ljust(supertypename[sym^.suptype],13),
X           ljust(typename[sym^.symtype],12),
X           sym^.base:5,' ',
X           sym^.limit:6,' ',
X           sym^.parcount:4,' ',
X           sym^.pvar:6,'   ',
X           sym^.repid);
X         putline;
X      end;
X
X      if sym <> nil then
X         sym := sym^.next;
X   end;
X
X   putln(' */');
X   putline;
Xend;
X
X
X(********************************************************************)
Xprocedure purgetable( var table: symptr; top: symptr);
X   {purge all entries from the specified symbol table}
Xvar
X   sym: symptr;
X
Xbegin
X   dumptable(table, top);
X   
X   while (table <> nil) and (table <> top) do
X   begin
X      sym := table;
X      table := table^.next;
X
X      {if sym^.suptype = ss_const then
X         putln('#undef '+sym^.repid);}
X         
X      dispose(sym);
X   end;
Xend;
X
X
X(********************************************************************)
Xprocedure create_unitfile(name: string64; sym, top: symptr);
X   {dump symbol table to the specified unit symbol file}
Xvar
X   fd:      text;
X   outbuf:  array[1..inbufsiz] of byte;
X   
Xbegin
X   assign(fd,name);
X{$I-}
X   rewrite(fd);
X{$I+}
X   if ioresult <> 0 then
X   begin
X      ltok := name;
X      fatal('Can''t create unit symbol file');
X   end;
X   
X   setTextBuf(fd,outbuf);
X
X   while (sym <> nil) and (sym <> top) do
X   begin
X      writeln(fd,sym^.id);
X      writeln(fd,sym^.repid);
X      writeln(fd,ord(sym^.suptype),' ',
X                 ord(sym^.symtype),' ',
X                 sym^.base,' ',
X                 sym^.limit,' ',
X                 sym^.parcount,' ',
X                 sym^.pvar);
X      
X      inc(objtotal,3);
X      sym := sym^.next;
X   end;
X
X   close(fd);
Xend;
X
X
X(********************************************************************)
Xprocedure load_unitfile(name: string64; var table: symptr);
X   {load symbol table fromthe specified unit symbol file}
Xvar
X   fd:      text;
X   sym:     symptr;
X   sstype:  byte;
X   stype:   byte;
X   inbuf:   array[1..inbufsiz] of byte;
X      
Xbegin
X   assign(fd,name);
X   {$I-} reset(fd); {$I+}
X   if ioresult <> 0 then
X   begin
X      name := symdir + name;
X      assign(fd,name);
X      {$I-} reset(fd); {$I+}
X   end;
X   
X   if ioresult <> 0 then
X   begin
X      ltok := name;
X      fatal('Can''t open unit symbol file');
X   end;
X   
X   setTextBuf(fd,inbuf);
X   
X   while not eof(fd) do
X   begin
X      new(sym);
X      sym^.next := table;
X      table := sym;
X      
X      readln(fd,sym^.id);
X      readln(fd,sym^.repid);
X      readln(fd,sstype,stype,
X                sym^.base,
X                sym^.limit,
X                sym^.parcount,
X                sym^.pvar);
X
X      sym^.suptype := supertypes(sstype);
X      sym^.symtype := symtypes(stype);
X   end;
X
X   close(fd);
Xend;
X
X
________This_Is_The_END________
if test `wc -c < tpcsym.inc` -ne 7059; then
	echo 'shar: tpcsym.inc was damaged during transit (should have been 7059 bytes)'
fi
fi		; : end of overwriting check
echo 'x - tpcunit.inc'
if test -f tpcunit.inc; then echo 'shar: not overwriting tpcunit.inc'; else
sed 's/^X//' << '________This_Is_The_END________' > tpcunit.inc
X
X(*
X * TPTC - Turbo Pascal to C translator
X *
X * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
X *
X *)
X
X   
X(********************************************************************)
X(*
X * process generic declaration section
X *   dispatches to const, type, var, proc, func
X *   enter with tok=section type
X *   exit with tok=next section type
X *
X *)
X
Xprocedure psection;
Xbegin
X   if recovery then
X   begin
X      while toktype <> keyword do
X         gettok;
X      {warning('Error recovery (psection)');}
X      recovery := false;
X   end;
X
X   if debug_parse then write(' <section>');
X
X   if (tok = 'EXTERNAL')  or (tok = 'OVERLAY') or
X      (tok = 'PROCEDURE') or (tok = 'FUNCTION') then
X      punit
X   else
X
X   if tok = 'INTERFACE' then
X      pinterface
X   else
X   
X   if tok = 'IMPLEMENTATION' then
X      pimplementation
X   else
X   
X   if tok = 'USES' then
X   begin
X      puses;
X      if tok[1] = ';' then 
X         gettok;
X   end
X   else
X   
X   if tok = 'UNIT' then
X      comment_statement
X   else
X   
X   if tok = 'CONST' then
X      pconst
X   else
X
X   if tok = 'TYPE' then
X      ptype
X   else
X
X   if tok = 'VAR' then
X      pvar
X   else
X
X   if tok = 'LABEL' then
X      plabel
X   else
X
X   if tok[1] = '{' then
X      pblock
X   else
X
X   if (tok[1] = '.') or (tok[1] = '}') then
X   begin
X      tok := '.';
X      exit;
X   end
X   else
X      syntax('Section header expected (psection)');
Xend;
X
X
X(********************************************************************)
X(*
X * process argument declarations to
X *    program, procedure, function
X *
X * enter with header as tok
X * exits with tok as ; or :
X *
X *)
X
Xconst
X   extern = true;
X   
Xprocedure punitheader(is_external: boolean);
Xvar
X   proc:    string40;
X   proclit: string40;
X   vars:    paramlist;
X   types:   paramlist;
X   bases:   array [1..maxparam] of integer;
X   i:       integer;
X   ii:      integer;
X   rtype:   string40;
X   varval:  integer;
X   varon:   boolean;
X   locvar:  integer;
X   iptr:    integer;
X
Xbegin
X   gettok;                 {skip unit type}
X   proclit := ltok;
X
X   if (unitlevel > 1) and (not in_interface) then
X   begin
X      {make name unique if it clashes with an existing global}
X      if cursym = nil then
X         proc := proclit
X      else
X         proc := procnum + '_' + proclit;
X         
X      warning('Nested function');
X      
X      writeln(ofd[unitlevel-1],^M^J'   /* Nested function: ',proc,' */ ');
X      inc(objtotal,2);
X   end
X   else
X      proc := proclit;
X
X   gettok;                 {skip unit identifier}
X
X   vars.n := 0;
X   varval := 0;       { 0 bit means value, 1 = var }
X   varon  := false;
X
X   (* process param list, if any *)
X   if tok[1] = '(' then
X   begin
X      gettok;
X
X      while (tok[1] <> ')') and not recovery do
X      begin
X
X         ii := vars.n + 1;
X         repeat
X            if tok[1] = ',' then
X               gettok;
X
X            if tok = 'VAR' then
X            begin
X               gettok;
X               varon := true;
X            end;
X
X            inc(vars.n);
X            if vars.n > maxparam then
X               fatal('Too many params (punitheader)');
X            vars.id[vars.n] := ltok;
X            gettok;
X
X         until tok[1] <> ',';
X
X         if tok[1] = ':' then       
X         begin
X            gettok;   {consume the :}
X   
X            {parse the param type}
X            rtype := psimpletype;
X         end
X         else
X
X         begin    {untyped variable if ':' is missing}
X            rtype := 'void';
X            curtype := s_void;
X            curbase := 0;
X            cursuptype := ss_scalar; {ss_array?}
X         end;
X
X         {assign and param types, converting 'var' and 'array' params}
X         iptr := 0;
X         if rtype[1] = '^' then
X            rtype[1] := '*';
X
X         {flag var parameters; strings and arrays are implicitly var in C}
X         if varon and (curtype <> s_string) and (cursuptype <> ss_array) then
X            iptr := 1 shl (ii - 1);
X
X         if curtype = s_string then
X            rtype := 'char *'
X         else
X         if cursuptype = ss_array then
X            rtype := typename[curtype] + ' *';
X
X         {assign data types for each ident}
X         for i := ii to vars.n do   
X         begin
X            types.id[i] := rtype;
X            types.stype[i] := curtype;
X            types.sstype[i] := cursuptype;
X            bases[i] := curbase;
X            varval := varval or iptr;
X            iptr := iptr shl 1;
X         end;
X
X         if tok[1] = ';' then
X         begin
X            gettok;
X            varon := false;
X         end;
X
X      end;   {) seen}
X
X      gettok;   {consume the )}
X   end;
X
X   (* process function return type, if any *)
X   if tok[1] = ':' then
X   begin
X      gettok;            {consume the :}
X      rtype := psimpletype;
X
X      if curtype = s_string then
X         rtype := 'char *'
X      else
X      if cursuptype = ss_array then
X         rtype := typename[curtype] + ' *';
X   end
X   else
X
X   begin
X      rtype := 'void';
X      curtype := s_void;
X   end;
X
X   putline;
X   
X   (* prefix procedure decl's when external *)
X   if is_external then
X   begin
X      putln(ljust('extern '+rtype,identlen)+proc+'();');
X      addsym(globals,proc,curtype,ss_func,0,varval,0,9,false);
X      exit;
X   end;
X
X
X   (* process 'as NEWNAME' clause, if present (tptc extention to specify
X      the replacement name in the symbol table *)
X   if tok = 'AS' then
X   begin
X      gettok;
X      proc := usetok;
X   end;
X    
X
X   (* output the return type, proc name, formal param list *)
X   if in_interface then
X      rtype := 'extern '+rtype;
X   puts(ljust(rtype,identlen)+proc+'(');
X
X   if vars.n = 0 then
X      puts('void');
X
X
X   (* output the formal param declarations *)
X   locvar := varval;
X   for i := 1 to vars.n do
X   begin
X      iptr := -1;
X
X      if (locvar and 1) = 1 then
X      begin
X         iptr := -2;
X         types.id[i] := types.id[i] + ' *';
X      end;
X
X      puts(ljust(types.id[i],identlen)+vars.id[i]);
X      addsym(locals,vars.id[i],types.stype[i],ss_scalar,iptr,0,0,bases[i],true);
X      locvar := locvar shr 1;
X
X      if i < vars.n then
X      begin
X         putln(','); 
X         puts(ljust('',identlen+length(proc)+1));
X      end;
X   end;
X
X   puts(')');
X   nospace := false;
X
X   {enter the procedure in the global symbol table}
X   addsym(globals,proclit,curtype,ss_func,vars.n,varval,0,0,false);
X   cursym^.repid := proc;
Xend;
X
X
X(********************************************************************)
X(*
X * process body of program unit
X *   handles all declaration sections
X *   and a single begin...end
X *   recursively handles procedure declarations
X *   ends with tok=}
X *)
X
Xprocedure punitbody;
Xbegin
X   gettok;
X
X   if tok = 'INTERRUPT' then
X   begin
X      warning('Interrupt handler');
X      gettok;
X   end;
X   
X   if tok = 'FORWARD' then
X   begin
X      puts(';');
X      gettok;
X   end
X   else
X
X   if tok = 'EXTERNAL' then
X   begin
X      puts('/* ');
X      repeat
X         puttok;
X         gettok;
X      until tok[1] = ';';
X      puts(' */ ;');
X   end
X   else
X
X   if tok = 'INLINE' then
X   begin
X      newline;
X      putln('{');
X      puts('   ');
X      pinline;
X      putln('}');
X   end
X   else
X
X   begin
X      puts('{ ');
X
X      repeat
X         if tok[1] = ';' then
X         begin
X            puttok;
X            gettok;
X         end;
X
X         if tok[1] <> '{' then
X            psection;
X      until tok[1] = '{';
X
X      gettok;                 {get first token of first statement}
X
X      while (tok[1] <> '}') and not recovery do
X      begin
X         pstatement;             {process the statement}
X
X         if tok[1] = ';' then
X         begin
X            puttok;
X            gettok;              {get first token of next statement}
X         end;
X      end;
X
X      puttok;
X   end;
Xend;
X
X
X(********************************************************************)
Xprocedure enter_procdef;
X   {increase output file level and direct output to the new file}
Xvar
X   nam:  anystring;
Xbegin
X   {increment this procedure number}
X   inc(procnum[2]);
X   if procnum[2] > 'Z' then
X   begin
X      inc(procnum[1]);
X      procnum[2] := 'A';
X   end;
X
X   inc(unitlevel);
X   if unitlevel > maxnest then
X      fatal('Functions nested too deeply');
X
X   str(unitlevel,nam);
X   nam := workdir + nestfile + nam;
X
X   assign(ofd[unitlevel],nam);
X   {$i-} rewrite(ofd[unitlevel]); {$i+}
X
X   if ioresult <> 0 then
X   begin
X      dec(unitlevel);
X      ltok := nam;
X      fatal('Can''t create tempfile');
X   end;
X
X   if maxavail-300 <= inbufsiz then
X   begin
X      ltok := nam;
X      fatal('Out of memory');
X   end;
X
X   getmem(outbuf[unitlevel],inbufsiz);
X   SetTextBuf(ofd[unitlevel],outbuf[unitlevel]^,inbufsiz);
Xend;
X
X
X(********************************************************************)
Xprocedure exit_procdef;
X   {copy the outer output file to the next lower level output
X    and reduce output level by 1}
Xvar
X   line:  string;
X
Xbegin
X   if unitlevel < 1 then 
X      exit;
X   
X   close(ofd[unitlevel]);
X   reset(ofd[unitlevel]);
X   SetTextBuf(ofd[unitlevel],outbuf[unitlevel]^,inbufsiz);
X
X   while not eof(ofd[unitlevel]) do
X   begin
X      readln(ofd[unitlevel],line);
X      writeln(ofd[0],line);
X   end;
X
X   close(ofd[unitlevel]);
X   erase(ofd[unitlevel]);
X   freemem(outbuf[unitlevel],inbufsiz);
X   dec(unitlevel);
Xend;
X
X
X(********************************************************************)
X(*
X * process program, procedure and function declaration
X *
X * enter with tok=function
X * exit with tok=;
X *
X *)
X
Xprocedure punit;
Xvar
X   top: symptr;
Xbegin
X   if debug_parse then write(' <unit>');
X
X   nospace := true;
X   top := locals;
X
X   if (tok = 'OVERLAY') then
X      gettok;
X
X   if (tok = 'EXTERNAL') then  {mt+}
X   begin
X      gettok;      {consume the EXTERNAL}
X
X      if tok[1] = '[' then
X      begin
X         gettok;   {consume the '['}
Xi         puts('/* overlay '+ltok+' */ ');
X         gettok;   {consume the overlay number}
X
X         gettok;   {consume the ']'}
X      end;
X
X      punitheader(extern);
X      if tok[1] = ';' then
X         gettok;
X      purgetable(locals,top);
X   end
X   else
X
X   if in_interface then
X   begin
X      nospace := false;
X      punitheader(not extern);
X
X      puts(';');
X      if tok[1] = ';' then
X         gettok;
X      
X      if tok = 'INLINE' then
X      begin
X         pinline;
X         warning('Inline procedure');
X      end;
X
X      purgetable(locals,top);
X   end
X   else
X   
X   begin
X      {enter a (possibly nested) procedure}
X      enter_procdef;
X
X      punitheader(not extern);
X      punitbody;
X      gettok;
X      if tok[1] = ';' then
X         gettok;
X      purgetable(locals,top);
X
X      {exit the (possibly nested) procedure, append text to toplevel outfile}
X      exit_procdef;
X   end;
X
Xend;
X
X
X
X(********************************************************************)
X(*
X * process main program
X *
X *  expects program head
X *  optional declarations
X *  block of main code
X *  .
X *
X *)
X
Xprocedure pprogram;
Xbegin
X   putline;
X   putln('/*');
X   putln(' * Generated by '+version1);
X   putln(' *     '+version2);
X   putln(' */');
X   putln('#include "tptcmac.h"');
X   
X   getchar;  {get first char}
X   gettok;   {get first token}
X
X   if (tok = 'PROGRAM') or (tok = 'UNIT') then
X   begin
X      comment_statement;
X      gettok;
X   end;
X
X   if tok = 'MODULE' then
X   begin
X      mt_plus := true;   {shift into pascal/mt+ mode}
X      comment_statement;
X      gettok;
X   end;
X
X   repeat
X      if tok[1] = ';' then
X      begin
X         puttok;
X         gettok;
X      end;
X
X      if tok = 'MODEND' then
X         exit;
X
X      if (tok[1] <> '{') then
X         psection;
X   until (tok[1] = '{') or (tok[1] = '.') or recovery;
X
X   {process the main block, if any}
X   if tok[1] = '{' then
X   begin
X      putline;
X      putln('main(int   argc,');
X      putln('     char  *argv[])');
X      
X      puttok;
X      gettok;                 {get first token of main block}
X   
X      while (tok[1] <> '}') and (tok[1] <> '.') do
X      begin
X         pstatement;                {process the statement}
X   
X         if tok[1] = ';' then
X         begin
X            puttok;
X            gettok;              {get first token of next statement}
X         end;
X      end;
X
X      putln('}');
X   end;
X   
X   putline;
Xend;
X
________This_Is_The_END________
if test `wc -c < tpcunit.inc` -ne 12098; then
	echo 'shar: tpcunit.inc was damaged during transit (should have been 12098 bytes)'
fi
fi		; : end of overwriting check
echo 'x - tptc.doc'
if test -f tptc.doc; then echo 'shar: not overwriting tptc.doc'; else
sed 's/^X//' << '________This_Is_The_END________' > tptc.doc
X
X
X                       TPTC16 - Translate Pascal to C
X                           Version 1.6, 13-Feb-88
X
X                 (C) Copyright 1986, 1988 by Samuel H. Smith
X                            All rights reserved.
X
X
XThis program will read a turbo pascal source file and convert it into
Xthe  corresponding C source code.   It does much of the work required in
Xa full translation.
X
XUsage:   TPTC input_file [output_file] [options]
X
XWhere:   input_file      specifies the main source file, .PAS default
X         output_file     specifies the output file, .C default
X         -B              deBug trace during scan
X         -BP             deBug trace during Parse
X         -D              Dump user symbols
X         -DP             Dump Predefined system symbols
X         -I              output Include files' contents
X         -L              map all identifiers to Lower case
X         -M              use Pascal/MT+ specific translations
X         -NC             No Comments passed to output file
X         -Q              Quiet mode; suppress warnings
X         -Sdir\          search dir\ for .UNS symbol files
X         -Tnn            Tab nn columns in declarations
X         -Wdrive:        use drive: for Work/scratch files (ramdrive)
X         -#              don't translate lines starting with "#"
X
XDefault command parameters are loaded from TPTC environment variable.
X
XExample: tptc fmap
X         tptc fmap -L -d -wj:\tmp\
X         tptc -l -d -wj: -i -q -t15 fmap.pas fmap.out
X
X         set tptc=-wj: -i -l -sc:\libs
X         tptc test       ;uses options specified earlier
X
X
XLICENSE
X=======
X
X   SourceWare: What is it?
X   -----------------------
X   SourceWare is my name for a unique concept in user supported software. 
X   
X   Programs distributed under the SourceWare concept always offer complete 
X   source code. 
X
X   This package can be freely distributed so long as it is not modified 
X   or sold for profit.  If you find that this program is valuable,  you 
X   can send me a donation for what you think it is worth.  I suggest
X   about $20.
X
X   Send your contributions to:
X      Samuel. H. Smith
X      5119 N. 11 ave 332
X      Phoenix, Az 85013
X
X
X   Why SourceWare?
X   ---------------
X   Why do I include source code?  Why isn't the donation manditory?  The
X   value of good software should be self-evident.  The source code is
X   the key to complete understanding of a program.  You can read it to
X   find out how things are done.  You can also change it to suit your
X   needs, so long as you do not distribute the modified version without
X   my consent.
X
X
X   Copyright
X   ---------
X   If you modify this program, I would appreciate a copy of the new
X   source code.   I am holding the copyright on the source code, so
X   please don't delete my name from the program files or from the
X   documentation.
X
X
XSUPPORT
X=======
X
X   I work very hard to produce a software package of the highest
X   quality and functionality.  I try to look into all reported bugs, and
X   will generally fix reported problems within a few days.
X
X   Since this is user supported software under the SourceWare  concept,
X   I don't expect you to contribute if you don't like it or if it
X   doesn't meet your needs.
X
X   If you have any questions, bugs, or suggestions, please contact  me
X   at:  The Tool Shop BBS (602) 279-2673
X
X   The latest version is always available for downloading. 
X
X   Enjoy!     Samuel H. Smith
X              Author and Sysop of The Tool Shop.
X
X
X
X
XThe following language constructs are translated:
X------------------------------------------------
X
X   Comments are translated from either {...} or (*...*) into /*...*/.
X
X   Begin and End are translated into { and }.
X
X   Const declarations are translated from
X      ID = VALUE
X   into
X      static ID = VALUE.
X
X   Simple Var declarations are translated from
X      ID TYPE
X   into
X      TYPE ID.
X
X   Integer subrange types are translated into integers.
X
X   Record types are translated from
X      ID = record MEMBER-LIST end
X   into
X      typedef struct { MEMBER-LIST } ID.
X
X   Enumeration types are translated from
X      ID = (...)
X   into
X      typedef enum {...} ID.
X
X   Array types are translated from
X      ID = array [RANGE] of TYPE
X   into
X      typedef TYPE ID[RANGE].
X
X   Pointer types are translated from
X      ID = ^DEFINED-TYPE
X   into
X      DEFINED-TYPE *ID.
X
X   String types are translated from
X      ID = string[N]
X   into
X      typedef char ID[N+1].
X
X   File types are translated from
X      ID = text[N]
X      ID = file
X   into
X      FILE *ID
X      int ID.
X
X   For statements are translated from
X      for VAR := FIRST to LAST do STATEMENT
X      for VAR := FIRST downto LAST do statement
X   into
X      for (VAR = FIRST; VAR <= LAST; VAR++) STATEMENT
X      for (VAR = FIRST; VAR >= LAST; VAR--) STATEMENT
X
X   While statements are translated from
X      while COND do STATEMENT
X   into
X      while (COND) statement.
X
X   Repeat statements are translated from
X      repeat STATEMENTS until COND
X   into
X      do { STATEMENTS } while(!COND).
X
X   If statements are translated from
X      if COND then STATEMENT else STATEMENT
X   into
X      if (COND) STATEMENT; else STATEMENT.
X
X   Case statements are translated from
X      case VALUE of
X         V:    STATEMENT;
X         V,U:  STATEMENT;
X         else  STATEMENT
X      end
X   into
X      switch (VALUE) {
X         case V:  STATEMENT; break;
X         case V:
X         case U:  STATEMENT; break;
X         default: STATEMENT;
X      }.
X      
X   Ranges in the form VAL..VAL automatically include cases for 
X   intermediate values.
X
X   The IN operator is translated from
X      VAL in [A,B,C]
X    into
X      inset(VAL, setof(A,B,C,-1)).
X
X   The ParamCount and ParamStr functions are translated from
X      paramcount
X      paramstr(n)
X   into
X      argc
X      argv[n].
X
X   Dummy parameter lists are added to function and procedure calls,
X   where they are required in C but not in Pascal.
X
X   The following expression operators are translated
X      from  DIV  to  / ,     MOD  to  % ,
X            AND  to  &&,     OR   to  ||,
X            XOR  to  ~ ,     <>   to  !=,
X            NOT  to  ! ,     SHR  to  >>,
X            SHL  to  <<,     =    to  ==,               {+others}
X            :=   to  = .
X   Bitwise AND and OR operators are translated into & and |.
X
X   The '^' symbol is translated
X      from  VAR^          to  *VAR,
X            VAR^.MEMBER   to  VAR->MEMBER.
X
X   Exit statements are translated
X      from  exit    to  return.
X
X   The New operator is translated from
X      new(VAR)
X   into
X      VAR = malloc(sizeof(*VAR)).
X
X
X   Procedure/function formal parameter lists are translated into the
X      new form defined in ANSI C (and as used by Turbo C):
X   from
X      function NAME(V1: TYPE1; V2: TYPE2): TYPE3
X   into
X      TYPE3 NAME(TYPE1 V1,TYPE2 V2)
X
X   Procedures are translated into functions with 'void' return types.
X
X   The special character literal syntax, ^C or #nn, is translated into
X   '\ooo', where ooo is the octal notation for the ascii code.
X
X   Hex constants $hhhh are translated into 0xhhhh.
X
X   Write and WriteLn are translated from:
X      write(VAR,VAR:n,VAR:n:m)
X      writeln(FILE,VAR,VAR,VAR)
X   into
X      printf("%d%nd%n.md",VAR,VAR,VAR)
X      fprintf(FILE,"%d%d%d\n",VAR,VAR,VAR).
X
X   Read and ReadLn are translated from:
X      read(VAR,VAR,VAR)
X      readln(FILE,VAR,VAR,VAR)
X   into
X      scanf("%d%nd%d",&VAR,&VAR,&VAR)
X      fscanf(FILE,"%d%d%d\n",&VAR,&VAR,&VAR).
X
X   String assignments are translated from:
X      VAR := "string"
X      VAR := "string1(" + VAR1 + ")string2"
X   into
X      strcpy(VAR, "string")
X      sbld(VAR,"string1(%s)string2",VAR1).      {+other compound forms}
X
X   String comparisons are translated from:
X      VAR == "string"
X      VAR < "string"
X      "string" >= VAR
X   into
X      (strcmp(VAR,"string") == 0)
X      (strcmp(VAR,"string") < 0)
X      (strcmp("string",VAR) >= 0).
X
X   Function value assignments are translated from:
X      FUN_NAME := expr
X   into
X      return expr.
X
X   Numeric statement labels are translated to label_nn.  
X   Label identifiers are not changed.  
X   Local GOTO statements are handled properly. 
X
X   Nested procedures are "flattened" out, but local variable sharing and 
X   local scoping are not translated. 
X
X   Direct I/O port and memory references are translated:
X      portw[expr] := expr + port[n]
X      mem[seg:ofs] := memw[seg:ofs] + expr
X   into
X      outport(expr, expr+inportb(n))
X      pokeb(seg,ofs, peek(seg,ofs)+expr)
X
X   VAR parameters are translated into pointer variables; 
X   references to formal parameters are implicitly dereferenced (i.e. * added);
X   references to actual parameters are implicitly referenced (i.e. & added).
X
X   Forward pointer type declarations are translated, but will not compile 
X   in C.  They must be manually recoded. 
X
X   Variant record type declarations are translated into unions.
X
X   Absolute variables are translated into initialized pointer variables.
X   
X
X
XSupport Pascal/MT+:
X-------------------
X
X   Var declarations are translated from
X      ID external TYPE
X   into
X      extern TYPE ID.
X
X   The following expression operators are translated
X      from   !   to  | ,    |    to   |,
X             &   to  & ,    ~    to   !,
X             ?   to  ! ,    \    to   !.
X
X   External function declarations are translated
X   from
X      external function NAME(V1: TYPE1; V2: TYPE2): TYPE3
X      external [n] function NAME(V1: TYPE1; V2: TYPE2): TYPE3
X   into
X      extern TYPE3 NAME()
X
X   External procedure declarations are translated
X   from
X      external procedure NAME(V1: TYPE1; V2: TYPE2)
X      external [n] procedure NAME(V1: TYPE1; V2: TYPE2)
X   into
X      extern void NAME()
X
X   Write and WriteLn are translated from:
X      write([ADDR(FUN)],VAR:n,VAR:n:m)
X      write([],VAR:n,VAR:n:m)
X   into
X      iprintf(FUN,"%nd%n.md",VAR,VAR)
X      printf("%nd%n.md",VAR,VAR)
X
X   Read and ReadLn are translated from:
X      read([ADDR(FUN)],VAR,VAR)
X      read([],VAR,VAR)
X   into
X      iscanf(FUN,"%d%nd%d",&VAR,&VAR,&VAR)
X      scanf("%d%nd%d",&VAR,&VAR,&VAR)
X
X   Long integer constants #nnn are translated into nnnL.
X
X
X
XSome language features that are not yet translated:
X---------------------------------------------------
X
X   File access procedures are only partially supported (assign, close, 
X   etc.). 
X
X   Variant record type decl's are translated into unions, but expressions
X   using the variant part are not translated.
X
X   C operator precedence differs from that of Pascal, and the differences 
X   are not translated. 
X
X   The WITH statement is not translated.
X
X   Local variable sharing among nested procedures is not translated. 
X
X
X
XRevision history
X----------------
X
X  See HISTORY.DOC for the complete revision history.
X  
X  I continue to update and improve TPTC.  If you have a program that
X  TPTC will not translate, please send me a copy of it.  This will help
X  me in future versions.  I will not redistribute the file without your
X  permission.
X
X  Send sample sources to:
X      Samuel. H. Smith
X      (602) 279-2673 (data)
X      5119 N. 11 ave 332
X      Phoenix, Az 85013
X
________This_Is_The_END________
if test `wc -c < tptc.doc` -ne 11061; then
	echo 'shar: tptc.doc was damaged during transit (should have been 11061 bytes)'
fi
fi		; : end of overwriting check
exit 0