home *** CD-ROM | disk | FTP | other *** search
-
- (*
- * TPTC - Turbo Pascal to C translator
- *
- * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
- *
- *)
-
-
- (********************************************************************)
- (*
- * process generic declaration section
- * dispatches to const, type, var, proc, func
- * enter with tok=section type
- * exit with tok=next section type
- *
- *)
-
- procedure psection;
- begin
- if recovery then
- begin
- while toktype <> keyword do
- gettok;
- {warning('Error recovery (psection)');}
- recovery := false;
- end;
-
- if debug_parse then write(' <section>');
-
- if (tok = 'EXTERNAL') or (tok = 'OVERLAY') or
- (tok = 'PROCEDURE') or (tok = 'FUNCTION') then
- punit
- else
-
- if tok = 'INTERFACE' then
- pinterface
- else
-
- if tok = 'IMPLEMENTATION' then
- pimplementation
- else
-
- if tok = 'USES' then
- begin
- puses;
- if tok[1] = ';' then
- gettok;
- end
- else
-
- if tok = 'UNIT' then
- comment_statement
- else
-
- if tok = 'CONST' then
- pconst
- else
-
- if tok = 'TYPE' then
- ptype
- else
-
- if tok = 'VAR' then
- pvar
- else
-
- if tok = 'LABEL' then
- plabel
- else
-
- if tok[1] = '{' then
- pblock
- else
-
- if (tok[1] = '.') or (tok[1] = '}') then
- begin
- tok := '.';
- exit;
- end
- else
- syntax('Section header expected (psection)');
- end;
-
-
- (********************************************************************)
- (*
- * process argument declarations to
- * program, procedure, function
- *
- * enter with header as tok
- * exits with tok as ; or :
- *
- *)
-
- const
- extern = true;
-
- procedure punitheader(is_external: boolean);
- var
- proc: string40;
- proclit: string40;
- vars: paramlist;
- types: paramlist;
- bases: array [1..maxparam] of integer;
- i: integer;
- ii: integer;
- rtype: string40;
- varval: integer;
- varon: boolean;
- locvar: integer;
- iptr: integer;
-
- begin
- gettok; {skip unit type}
- proclit := ltok;
-
- if (unitlevel > 1) and (not in_interface) then
- begin
- {make name unique if it clashes with an existing global}
- if cursym = nil then
- proc := proclit
- else
- proc := procnum + '_' + proclit;
-
- warning('Nested function');
-
- writeln(ofd[unitlevel-1],^M^J' /* Nested function: ',proc,' */ ');
- inc(objtotal,2);
- end
- else
- proc := proclit;
-
- gettok; {skip unit identifier}
-
- vars.n := 0;
- varval := 0; { 0 bit means value, 1 = var }
- varon := false;
-
- (* process param list, if any *)
- if tok[1] = '(' then
- begin
- gettok;
-
- while (tok[1] <> ')') and not recovery do
- begin
-
- ii := vars.n + 1;
- repeat
- if tok[1] = ',' then
- gettok;
-
- if tok = 'VAR' then
- begin
- gettok;
- varon := true;
- end;
-
- inc(vars.n);
- if vars.n > maxparam then
- fatal('Too many params (punitheader)');
- vars.id[vars.n] := ltok;
- gettok;
-
- until tok[1] <> ',';
-
- if tok[1] = ':' then
- begin
- gettok; {consume the :}
-
- {parse the param type}
- rtype := psimpletype;
- end
- else
-
- begin {untyped variable if ':' is missing}
- rtype := 'void';
- curtype := s_void;
- curbase := 0;
- cursuptype := ss_scalar; {ss_array?}
- end;
-
- {assign and param types, converting 'var' and 'array' params}
- iptr := 0;
- if rtype[1] = '^' then
- rtype[1] := '*';
-
- {flag var parameters; strings and arrays are implicitly var in C}
- if varon and (curtype <> s_string) and (cursuptype <> ss_array) then
- iptr := 1 shl (ii - 1);
-
- if curtype = s_string then
- rtype := 'char *'
- else
- if cursuptype = ss_array then
- rtype := typename[curtype] + ' *';
-
- {assign data types for each ident}
- for i := ii to vars.n do
- begin
- types.id[i] := rtype;
- types.stype[i] := curtype;
- types.sstype[i] := cursuptype;
- bases[i] := curbase;
- varval := varval or iptr;
- iptr := iptr shl 1;
- end;
-
- if tok[1] = ';' then
- begin
- gettok;
- varon := false;
- end;
-
- end; {) seen}
-
- gettok; {consume the )}
- end;
-
- (* process function return type, if any *)
- if tok[1] = ':' then
- begin
- gettok; {consume the :}
- rtype := psimpletype;
-
- if curtype = s_string then
- rtype := 'char *'
- else
- if cursuptype = ss_array then
- rtype := typename[curtype] + ' *';
- end
- else
-
- begin
- rtype := 'void';
- curtype := s_void;
- end;
-
- putline;
-
- (* prefix procedure decl's when external *)
- if is_external then
- begin
- putln(ljust('extern '+rtype,identlen)+proc+'();');
- addsym(globals,proc,curtype,ss_func,0,varval,0,9,false);
- exit;
- end;
-
-
- (* process 'as NEWNAME' clause, if present (tptc extention to specify
- the replacement name in the symbol table *)
- if tok = 'AS' then
- begin
- gettok;
- proc := usetok;
- end;
-
-
- (* output the return type, proc name, formal param list *)
- if in_interface then
- rtype := 'extern '+rtype;
- puts(ljust(rtype,identlen)+proc+'(');
-
- if vars.n = 0 then
- puts('void');
-
-
- (* output the formal param declarations *)
- locvar := varval;
- for i := 1 to vars.n do
- begin
- iptr := -1;
-
- if (locvar and 1) = 1 then
- begin
- iptr := -2;
- types.id[i] := types.id[i] + ' *';
- end;
-
- puts(ljust(types.id[i],identlen)+vars.id[i]);
- addsym(locals,vars.id[i],types.stype[i],ss_scalar,iptr,0,0,bases[i],true);
- locvar := locvar shr 1;
-
- if i < vars.n then
- begin
- putln(',');
- puts(ljust('',identlen+length(proc)+1));
- end;
- end;
-
- puts(')');
- nospace := false;
-
- {enter the procedure in the global symbol table}
- addsym(globals,proclit,curtype,ss_func,vars.n,varval,0,0,false);
- cursym^.repid := proc;
- end;
-
-
- (********************************************************************)
- (*
- * process body of program unit
- * handles all declaration sections
- * and a single begin...end
- * recursively handles procedure declarations
- * ends with tok=}
- *)
-
- procedure punitbody;
- begin
- gettok;
-
- if tok = 'INTERRUPT' then
- begin
- warning('Interrupt handler');
- gettok;
- end;
-
- if tok = 'FORWARD' then
- begin
- puts(';');
- gettok;
- end
- else
-
- if tok = 'EXTERNAL' then
- begin
- puts('/* ');
- repeat
- puttok;
- gettok;
- until tok[1] = ';';
- puts(' */ ;');
- end
- else
-
- if tok = 'INLINE' then
- begin
- newline;
- putln('{');
- puts(' ');
- pinline;
- putln('}');
- end
- else
-
- begin
- puts('{ ');
-
- repeat
- if tok[1] = ';' then
- begin
- puttok;
- gettok;
- end;
-
- if tok[1] <> '{' then
- psection;
- until tok[1] = '{';
-
- gettok; {get first token of first statement}
-
- while (tok[1] <> '}') and not recovery do
- begin
- pstatement; {process the statement}
-
- if tok[1] = ';' then
- begin
- puttok;
- gettok; {get first token of next statement}
- end;
- end;
-
- puttok;
- end;
- end;
-
-
- (********************************************************************)
- procedure enter_procdef;
- {increase output file level and direct output to the new file}
- var
- nam: anystring;
- begin
- {increment this procedure number}
- inc(procnum[2]);
- if procnum[2] > 'Z' then
- begin
- inc(procnum[1]);
- procnum[2] := 'A';
- end;
-
- inc(unitlevel);
- if unitlevel > maxnest then
- fatal('Functions nested too deeply');
-
- str(unitlevel,nam);
- nam := workdir + nestfile + nam;
-
- assign(ofd[unitlevel],nam);
- {$i-} rewrite(ofd[unitlevel]); {$i+}
-
- if ioresult <> 0 then
- begin
- dec(unitlevel);
- ltok := nam;
- fatal('Can''t create tempfile');
- end;
-
- if maxavail-300 <= inbufsiz then
- begin
- ltok := nam;
- fatal('Out of memory');
- end;
-
- getmem(outbuf[unitlevel],inbufsiz);
- SetTextBuf(ofd[unitlevel],outbuf[unitlevel]^,inbufsiz);
- end;
-
-
- (********************************************************************)
- procedure exit_procdef;
- {copy the outer output file to the next lower level output
- and reduce output level by 1}
- var
- line: string;
-
- begin
- if unitlevel < 1 then
- exit;
-
- close(ofd[unitlevel]);
- reset(ofd[unitlevel]);
- SetTextBuf(ofd[unitlevel],outbuf[unitlevel]^,inbufsiz);
-
- while not eof(ofd[unitlevel]) do
- begin
- readln(ofd[unitlevel],line);
- writeln(ofd[0],line);
- end;
-
- close(ofd[unitlevel]);
- erase(ofd[unitlevel]);
- freemem(outbuf[unitlevel],inbufsiz);
- dec(unitlevel);
- end;
-
-
- (********************************************************************)
- (*
- * process program, procedure and function declaration
- *
- * enter with tok=function
- * exit with tok=;
- *
- *)
-
- procedure punit;
- var
- top: symptr;
- begin
- if debug_parse then write(' <unit>');
-
- nospace := true;
- top := locals;
-
- if (tok = 'OVERLAY') then
- gettok;
-
- if (tok = 'EXTERNAL') then {mt+}
- begin
- gettok; {consume the EXTERNAL}
-
- if tok[1] = '[' then
- begin
- gettok; {consume the '['}
-
- puts('/* overlay '+ltok+' */ ');
- gettok; {consume the overlay number}
-
- gettok; {consume the ']'}
- end;
-
- punitheader(extern);
- if tok[1] = ';' then
- gettok;
- purgetable(locals,top);
- end
- else
-
- if in_interface then
- begin
- nospace := false;
- punitheader(not extern);
-
- puts(';');
- if tok[1] = ';' then
- gettok;
-
- if tok = 'INLINE' then
- begin
- pinline;
- warning('Inline procedure');
- end;
-
- purgetable(locals,top);
- end
- else
-
- begin
- {enter a (possibly nested) procedure}
- enter_procdef;
-
- punitheader(not extern);
- punitbody;
- gettok;
- if tok[1] = ';' then
- gettok;
- purgetable(locals,top);
-
- {exit the (possibly nested) procedure, append text to toplevel outfile}
- exit_procdef;
- end;
-
- end;
-
-
-
- (********************************************************************)
- (*
- * process main program
- *
- * expects program head
- * optional declarations
- * block of main code
- * .
- *
- *)
-
- procedure pprogram;
- begin
- putline;
- putln('/*');
- putln(' * Generated by '+version1);
- putln(' * '+version2);
- putln(' */');
- putln('#include "tptcmac.h"');
-
- getchar; {get first char}
- gettok; {get first token}
-
- if (tok = 'PROGRAM') or (tok = 'UNIT') then
- begin
- comment_statement;
- gettok;
- end;
-
- if tok = 'MODULE' then
- begin
- mt_plus := true; {shift into pascal/mt+ mode}
- comment_statement;
- gettok;
- end;
-
- repeat
- if tok[1] = ';' then
- begin
- puttok;
- gettok;
- end;
-
- if tok = 'MODEND' then
- exit;
-
- if (tok[1] <> '{') then
- psection;
- until (tok[1] = '{') or (tok[1] = '.') or recovery;
-
- {process the main block, if any}
- if tok[1] = '{' then
- begin
- putline;
- putln('main(int argc,');
- putln(' char *argv[])');
-
- puttok;
- gettok; {get first token of main block}
-
- while (tok[1] <> '}') and (tok[1] <> '.') do
- begin
- pstatement; {process the statement}
-
- if tok[1] = ';' then
- begin
- puttok;
- gettok; {get first token of next statement}
- end;
- end;
-
- putln('}');
- end;
-
- putline;
- end;
-
-